#!/bin/sh
# 
# apmd_proxy - program dispatcher for APM daemon
# Craig Markwardt (craigm@lheamail.gsfc.nasa.gov) 21 May 1999
# David Brownell (db@post.harvard.edu) 9 June 1999
#
# This shell script is called by the APM daemon (apmd) when the state
# of any power management function has changed.  The exact events that
# trigger the calling of apmd_proxy depend on how apmd was configured
# at compile time.
#
# Within this script the system administrator should put any commands
# or actions which should be performed upon state transitions.
#
# apmd_proxy is called with specific arguments that describe the event
# that has occurred.  It is this script's responsibility to query the
# hardware or the APM service (via /proc/apm) for more information,
# and to take the appropriate action.
#
# For example, apmd will call "apmd_proxy suspend system" just before
# the system is scheduled to go into suspend mode.  The administrator
# may wish to perform site-specific actions like unloading drivers or
# disabling the network interface.  When the system is resumed later,
# apmd will call "apmd_proxy resume normal", at which time those actions
# should be reversed.
#
# If the kernel APM driver supports it, apmd_proxy can return an error
# code for the suspend and standby events, indicating whether the
# pending mode should be rejected.  For example, apmd_proxy may decide
# if, based on CPU or network activity or user instructions, a suspend
# initiated by the APM BIOS should be rejected.
#
#    !! NOTE !!   This is not the apmd_proxy used on most Debian systems!
#
#   RETURN VALUE:
#     0 - nominal return; suspend and standby events are accepted
#     1 - reject a suspend or standby (MUST HAVE APM KERNEL SUPPORT)
#
# Here are the calling sequences for apmd_proxy:
#
# apmd_proxy start              - APM daemon has started
# apmd_proxy stop               - APM daemon is shutting down
# apmd_proxy suspend system     - APM system has requested suspend mode
# apmd_proxy suspend critical   - APM system indicates critical suspend (*)
# apmd_proxy standby system     - APM system has requested standby mode 
# apmd_proxy suspend user       - User has requested suspend mode
# apmd_proxy standby user       - User has requested standby mode
# apmd_proxy resume suspend     - System has resumed from suspend mode
# apmd_proxy resume standby     - System has resumed from standby mode
# apmd_proxy resume critical    - System has resumed from critical suspend
# apmd_proxy change battery     - APM system reported low battery
# apmd_proxy change power       - APM system reported AC/battery change
# apmd_proxy change time        - APM system reported need for time update (*)
# apmd_proxy change capability  - APM system reported config. change (+)
#
# (*) - APM daemon may be modified to call these sequences
# (+) - Available if kernel APM driver supports it (e.g. 2.2 kernels)
#
#
# A convenience bash routine is included to show how to query AC power
# status.
#
# *******************************************************************


power_conserve() {
	# Set IDE hard disk spindown time to a short time
#	/sbin/hdparm -q -S 18 /dev/hda			# 18 == 1.5 minutes
	true;
}

power_performance() {
	# Disable IDE hard disk spindown
#	/sbin/hdparm -q -S 0 /dev/hda
	true;
}

# Set this here if you don't have /etc/sysconfig/clock.
# (It probably only exists on Red Hat systems)
UTC=false

# NOTE:  APM BIOS drivers in kernel 2.2 and later have handled this
update_clock () {
	# update kernel to match hardware clock
	if [ -f /etc/sysconfig/clock ]; then
	    . /etc/sysconfig/clock
	    # old style
	    if [ "$CLOCKMODE" = GMT ]; then
		UTC=true
	    fi
	fi
	if [ $UTC = false ]; then
	    FLAG=""
	else
	    FLAG="-u"
	fi
	[ -x /sbin/clock ] && clock -s $FLAG || hwclock -s $FLAG
}


# Start of main procedure.  This is an example of some mild power
# management profiling.  Timer-based system suspends and standbys are
# rejected if we are on AC power.
#
# The idea here is that if we are running on AC power, power saving modes
# are just annoying.  Standby often blanks the screen unnecessarily, for
# example.

case "$1" in

  # Handle standby and suspend events here.
  standby|suspend)
	if [ $2 = system ]; then
		# Reject system standbys and (noncritical) suspends if we
		# are on AC power; this assumes we should always spend AC
		# power if it's there.
		if on_ac_power >/dev/null; then
			exit 1  # Reject (NOTE kernel support must be enabled)
		fi
	fi
	if [ $1 = suspend ]; then
		# tell PCMCIA support to suspend -- power down sockets, stop
		# modems, etc
		if [ -x /sbin/cardctl ]; then
			/sbin/cardctl suspend
		fi

		# other common actions:  unload troublesome drivers
	fi
	;;

  # Resume ... from standby is a NOP, except the clock update.
  resume)
	update_clock
	if [ $2 = suspend -o $2 = critical ]; then
		# tell PCMCIA support to resume
		if [ -x /sbin/cardctl ]; then
			/sbin/cardctl resume
		fi

		# other common actions:  reload troublesome drivers
	fi
	;;

  # If we are on battery power, then attempt to "conserve" power.
  start)
  	if on_ac_power >/dev/null; then
		power_performance
	else
		power_conserve
	fi
	;;

  # Default mode, when apmd is off, is to be in "performance" mode.
  stop)
	power_performance
	;; 

  change)
	case $2 in
	    power)
		# switched to/from AC power, added/removed battery, etc
		if on_ac_power >/dev/null; then
			power_performance
		else
			power_conserve
		fi
		;;
	    time)
		# normally not called
		update_clock
		;;
	    battery)
		# battery is at "low" level (BIOS defines -- e.g. as 50%)
		# can't do much of anything useful
		;;
	    capability)
		# e.g. added new hardware (not battery!)
		;;
	esac
	;;

esac

exit 0
