#!/bin/bash
# ---------------------------------------------------------------------------
# NAME
#
#     SetPowerSwitch - sets the state of one of the configurable power
#                      switches
#
# SYNOPSIS
#
#     sudo SetPowerSwitch switch-number new-state
#
# DESCRIPTION
#
#     The SMC has four (4) power switches that can be controller through
#     software.  This script sets the state of any one switch.
#
#         switch-number is a number 1..4
#
#         new-state is a number 0 (turn off) or 1 (turn on)
#
# ---------------------------------------------------------------------------

# exit if not run as root
CURUSER=`whoami`

if [ "$CURUSER" != "root" ]
then
	echo "This script must be run as root "
	exit 1
fi

# alias parameters and check ranges
base=`basename $0`
switch_num="$1"
state="$2"

if [ -z "$switch_num" ]
then
	echo "$base: switch number was not specified"
	exit 1
fi

if [ "$switch_num" -lt 1 ]
then
	echo "$base: switch number ($switch_num) must be in the range 1..4"
	exit 1
fi

if [ "$switch_num" -gt 4 ]
then
	echo "$base: switch number ($switch_num) must be in the range 1..4"
	exit 1
fi

if [ -z "$state" ]
then
	state="1"
fi

state_ok="no"

if [ "$state" != "0" ]
then
	if [ "$state" != "1" ]
	then
		echo "State value ($state) must be 0 or 1"
		exit 1
	fi
fi

# the script terminates when any command fails
set -e

# compute the masks to affect
affectmask=`echo "2^($switch_num-1)" | bc`
statemask=$(( $state * $affectmask ))
expectedmask=$(( $affectmask * 17 ))
expected=$(( $statemask * 17 ))

# using a file lock prevents contention over the I2C bus
(
flock -x 200

# affect the switch
i2cset -y -mask $affectmask 2 0x3C 0x01 $statemask
i2cset -y -mask $affectmask 2 0x3C 0x03 0

# wait for the state to change or timeout
ctr="4"

while [ $ctr -gt 0 ]
do
	# decrements the counter
	ctr=$(( $ctr - 1 ))

	# read the state of the port
	status0=`i2cget -y 2 0x3C 0x00`
	status=$(( $status0 ))

	resultingmask=$(( $status & $expectedmask ))

	# exit here because the expected state was reached
	if [ $resultingmask -eq $expected ]
	then
		echo "$base: $status0"
		exit 0
	fi

	# wait for 50 ms
	if [ $ctr -gt 0 ]
	then
		sleep 0.05
	fi
done

# show the new state of the switches (failed because switch states were wrong)
echo "$base: $status0"
echo "$base: affected bits resulted in $resultingmask, but $expected was expected"
exit 2

) 200>"$0.lockfile"
