[ltp] Script to manage ACPI Events on T42

Jerome Poggi linux-thinkpad@linux-thinkpad.org
Mon, 21 Mar 2005 13:14:27 +0100


I work a lot on ACPI event, and what do I must do when event arrive.
With all of this avent I done a single script, and I share it, so
allbody can use some part or all parts.

It's a little personnalised, so you must review the code to see if
somethink don't work correctly.

the module ibm-acpi is loaded with this parameters :
experimental=1 hotkey=enable,0x087c

If some key don't work or don't send ACPI event, try to put hotkey to
0xFFFF, and retry. If it's the same problem, you must need to upgrade
your Bios and Embedded Controller.

Jerome.

--
Jerome POGGI                                     Jerome.Poggi@hsc.fr
Herve Schauer Consultants   -=-   Network security consultant, CISSP
http://www.hsc.fr/                             Tel : +33 141 409 700

----- 8< --- Cut Here --- 8< -----

#!/bin/sh
# Copyright 1999-2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/sys-apps/acpid/files/acpid-1.0.4-default.sh,v 1.1 2004/10/19 08:07:45 brix Exp $

# Default acpi script that takes an entry for all actions
#
# JP : Version 1.1 - Initial Version
# JP : Version 1.2 - English Version and more generic

set $*

group=${1/\/*/}
action=${1/*\//}

element=$2
param1=$3
param2=$4

# ONLY FOR DEBUG
#logger "ACPI : group='$group' action='$action' element='$2' param1='$3' param2='$4'"

ALARM_LOW=11
ALARM_VERY_LOW=6
WIFI_MODULE=ipw2200
MY_LOGON=poggi

single_beep()
{
  echo  3 > /proc/acpi/ibm/beep
}
high_low_beep()
{
  echo  4 > /proc/acpi/ibm/beep
}
high_beep()
{
  echo  7 > /proc/acpi/ibm/beep
}
triple_beep()
{
  echo  9 > /proc/acpi/ibm/beep
}
low_beep()
{
  echo 12 > /proc/acpi/ibm/beep
}

button_sleep()
{
  /usr/bin/logger "Fn+F4 Suspending to RAM"
  single_beep
  /usr/sbin/dodo       # Call my script to go to Sleep State
  /usr/bin/logger "Resuming from Fn+F4 Suspending to RAM"
}

button_hybernate()
{
  logger "Switching to ACPI S4 Mode - Hybernation"
  single_beep
  /usr/sbin/hybernate  # Call my script to go to Hybernate State
}

button_lid()
{
  STATE_LIC=`cat /proc/acpi/button/lid/LID/state | sed 's/.*  //'`
  logger "ACPI : Screen $STATE_LIC"
  single_beep
  if [ "$STATE_LIC" = "open" ]
  then
    /usr/bin/radeontool light on
  else
    /usr/bin/radeontool light off
    PID=`pidof /usr/X11R6/bin/X`
    AUTH=`perl -ne'/\x00-auth\x00(.*?)\x00.*/&&print$1' /proc/$PID/cmdline`
    if [ x"$AUTH" = x ]; then
      AUTH=`perl -ne'/(^|\x00)XAUTHORITY=(.*?)\x00/&&print$2' /proc/$PID/environ`
    fi
    export XAUTHORITY=$AUTH
    /usr/X11R6/bin/xset -display :0 dpms force standby
  fi
}

button_power()
{
  if [ -e /var/run/PowerOFF_wanted ]
  then
    logger "PowerOFF Canceled"
    high_low_beep
    #shutdown -c
    rm -f /var/run/PowerOFF_wanted
  else
    touch /var/run/PowerOFF_wanted
    chmod 600 /var/run/PowerOFF_wanted
    triple_beep
    logger "Power OFF !"
    #shutdown -hFP -t 15
  fi
}

blank_DPMS()
{
  PID=`pidof /usr/X11R6/bin/X`
  AUTH=`perl -ne'/\x00-auth\x00(.*?)\x00.*/&&print$1' /proc/$PID/cmdline`
  if [ x"$AUTH" = x ]; then
      AUTH=`perl -ne'/(^|\x00)XAUTHORITY=(.*?)\x00/&&print$2' /proc/$PID/environ`
  fi
  export XAUTHORITY=$AUTH
  /usr/X11R6/bin/xset -display :0 dpms force standby
}

CheckBattery()
{
  ACPI_BATTERY=`acpi -b`
  logger ${ACPI_BATTERY}

  STATE_BATTERY1=`echo ${ACPI_BATTERY} | grep "Battery 1" | cut -d':' -f2 | cut -d',' -f1-2`
  STATE_BATTERY2=`echo ${ACPI_BATTERY} | grep "Battery 2" | cut -d':' -f2 | cut -d',' -f1-2`
  if [ -z ${STATE_BATTERY2} ]
  then
    POWER_BAT1=`echo ${STATE_BATTERY1} | cut -d',' -f2 | sed 's/%//;s/ //'`
    STATE_BAT1=`echo ${STATE_BATTERY1} | cut -d',' -f1 | sed 's/ //'`
    if [ "$STATE_BAT1" = "discharging" ]
    then
      if [ $POWER_BAT1 -lt $ALARM_LOW ]
      then
	triple_beep
        echo -n "1 blink" > /proc/acpi/ibm/led
        echo -n "2 blink" > /proc/acpi/ibm/led
        DISPLAY=:0 /usr/X11R6/bin/xmessage -center -nearmouse -timeout 5 "===== URGENT !!! Battery LOW ===="
	logger "===== URGENT !!! Battery LOW ===="
	echo "===== URGENT !!! Battery LOW ====" | wall
        blank_DPMS
      fi
      if [ $POWER_BAT1 -lt $ALARM_VERY_LOW ]
      then
        triple_beep
        echo -n "0 blink" > /proc/acpi/ibm/led
	logger "ACPI : BackLight is OFF"
	/usr/bin/radeontool light off
        logger "===== URGENT !!! Go to Hybernation ====="
        echo "===== URGENT !!! Go to Hybernation =====" | wall
        button_hybernate
        exit 0
      fi
    fi
  fi
}

battery_battery()
{
  cat /proc/acpi/ac_adapter/AC/state | grep "on-line" > /dev/null 2>&1
  ret=$?
  [[ -e /proc/acpi/battery/BAT0/state ]] && BAT0_PRESENT=1 || BAT0_PRESENT=0
  [[ -e /proc/acpi/battery/BAT1/state ]] && BAT1_PRESENT=1 || BAT1_PRESENT=0
  # Si on est sur batterie
  if [ $BAT0_PRESENT = 1 -a $BAT1_PRESENT = 1 ]
  then
    [[ $element = BAT1 ]] && logger `acpi`
  else
    CheckBattery
  fi
}

ac_adapter_ac_adapter()
{
  ACAD_HD=12
  BATT_HD=1

  ACAD_DPMS="120 300 1200"
  BATT_DPMS="60 120 300"

  if [ "$param2" = "00000001" ]
  then
    logger "On-Line AC"
    echo -n "0 on" > /proc/acpi/ibm/led
    hdparm -S $ACAD_HD  /dev/hda > /dev/null
    hdparm -B 255 /dev/hda > /dev/null
    /usr/sbin/laptop_mode stop
    #/usr/bin/speedfreq -p performance
    echo -n "ondemand" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
    echo -n "level 7" > /proc/acpi/ibm/brightness
    echo -n $ACAD_THR > /proc/acpi/processor/CPU/throttling
    echo -n enable > /proc/acpi/ibm/fan
    if [ -e /tmp/.X0-lock ]; then
      su - ${MY_LOGON} -c "DISPLAY=:0.0 /usr/X11R6/bin/xmessage -center -nearmouse -timeout 3 'On-Line AC'"
      su - ${MY_LOGON} -c "DISPLAY=:0.0 /usr/X11R6/bin/xset -display :0 dpms $ACAD_DPMS"
    fi
  else
    logger "Switching to Battery"
    echo -n "0 off" > /proc/acpi/ibm/led
    # Alarm at 4100mw of remaining capacity not 2000mw, it's 10% for a 6 cell battery
    echo "4100" > /proc/acpi/battery/BAT0/alarm
    hdparm -S $BATT_HD /dev/hda > /dev/null
    hdparm -B 1 /dev/hda > /dev/null
    /usr/sbin/laptop_mode start
    echo -n "powersave" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
    #/usr/bin/speedfreq -p powersave
    echo "level 2" > /proc/acpi/ibm/brightness
    echo -n disable > /proc/acpi/ibm/fan
    echo -n $BATT_THR > /proc/acpi/processor/CPU/throttling
    if [ -e /tmp/.X0-lock ]; then
      su - ${MY_LOGON} -c "DISPLAY=:0 /usr/X11R6/bin/xmessage -center -nearmouse -timeout 3 'Switching to Battery'"
      su - ${MY_LOGON} -c "DISPLAY=:0.0 /usr/X11R6/bin/xset -display :0 dpms $BATT_DPMS"
    fi
  fi
}

processor_processor()
{
  TRIP_POINT=`grep passive /proc/acpi/thermal_zone/THM0/trip_points | sed 's/passive: *//;s/C:.*/C/'`
  TEMPERATURE=`sed 's/.*: *//' /proc/acpi/thermal_zone/THM0/temperature`
  case "$param2" in
    00000005)
      echo enable > /proc/acpi/ibm/fan
      triple_beep
      logger "ACPI : TEMPERATURE TOO HIGHT > ${TRIP_POINT} (${TEMPERATURE}) - Safety Mode"
      triple_beep
      ;;
    00000000)
      logger "ACPI : CPU Temperature OK : ${TEMPERATURE}"
      single_beep
      ;;
    *)
      logger "ACPI : group='$group' action='$action' element='$2' param1='$3' param2='$4'"
      ;;
  esac
}

thermal_zone_thermal_zone()
{
  echo enable > /proc/acpi/ibm/fan
  # When Critical temperature reached, and go to S5 state : Forced Shutdown
  logger "ACPI : group='$group' action='$action' element='$2' param1='$3' param2='$4'"
  logger " TripPoints was : `cat /proc/acpi/thermal_zone/THM0/trip_points`"
  logger " Temperature was : `sed 's/.*: *//' /proc/acpi/thermal_zone/THM0/temperature`"
  logger "The shutdown is a protective procedure and can't STOP"
  logger " GoogBye, and put me in the refrigerator :-)"
}

swap_screen()
{
  status=`/bin/awk '/^(lcd|crt):/ { ORS=""; print $2 }' /proc/acpi/ibm/video`
  if [ "$status" == "enableddisabled" ]; then
    /bin/echo lcd_disable,crt_enable >/proc/acpi/ibm/video
    MSG="LCD OFF / CRT ON"
  elif [ "$status" == "disabledenabled" ]; then
    /bin/echo lcd_enable >/proc/acpi/ibm/video
    MSG="LCD ON / CRT ON"
  elif [ "$status" == "enabledenabled" ]; then
    /bin/echo crt_disable >/proc/acpi/ibm/video
    MSG="LCD ON / CRT OFF"
  fi
  logger "ACPI : Switching screen " $MSG
}

ibm_hotkey()
{
  case "$param2" in
    00001003)  # Fn + F3
	STATE_SCREEN=`radeontool light | awk '{print $5}'`
	if [ "$STATE_SCREEN" = "on" ]
	then
	  logger "ACPI : Turn OFF BackLight"
	  /usr/bin/radeontool light off
        else
          logger "ACPI : Turn ON BackLight"
          /usr/bin/radeontool light on
        fi
	;;
    00001004)  # Fn + F4
	logger "ACPI : Go to sleep state"
        button_sleep
	;;
    00001005)  # Fn + F5
	STATE_BLUETOOTH=`grep status /proc/acpi/ibm/bluetooth | sed 's/.*\t//'`
	if [ "$STATE_BLUETOOTH" = "disabled" ]
	then
	  logger "ACPI : Turn ON BlueTooth"
	  echo "enabled" > /proc/acpi/ibm/bluetooth
          single_beep
	else
	  logger "ACPI : Turn OFF BlueTooth"
	  echo "disabled" > /proc/acpi/ibm/bluetooth
          modprobe -r hci_usb
          modprobe -r bluetooth
          low_beep
	fi
	;;
    00001006)  # Fn + F6
	STATE_IPW2200=`lsmod | grep "^${WIFI_MODULE}" 2>/dev/null`
	if [ "$STATE_IPW2200" = "" ]
	then
	  logger "ACPI : Turn ON Wi-Fi (module+rf)"
	  modprobe -s ${WIFI_MODULE}
	  sleep 0.5
	  echo -n "0" > /sys/bus/pci/devices/0000:00:1e.0/0000:02:02.0/rf_kill
          single_beep
        else
	  STATE_RF_WIFI=`cat /sys/bus/pci/devices/0000:00:1e.0/0000:02:02.0/rf_kill`
	  if [ $STATE_RF_WIFI = 0 ]
	  then
	    logger "ACPI : Turn OFF Wi-Fi (module+rf)"
	    echo -n "1" > /sys/bus/pci/devices/0000:00:1e.0/0000:02:02.0/rf_kill
	    sleep 0.5
            modprobe -s -r ${WIFI_MODULE}
            low_beep
	  else
	    logger "ACPI : Turn ON Wi-Fi (rf)"
	    echo -n "0" > /sys/bus/pci/devices/0000:00:1e.0/0000:02:02.0/rf_kill
            single_beep
	  fi
	fi
	;;
    00001007)  # Fn + F7
        swap_screen
	;;
    0000100c)  # Fn + F12
	logger "ACPI : Switching to Hybernate state"
        button_hybernate
        ;;
    0000100d)  ;; # Fn + BackSpc
    0000100e)  ;; # Fn + Insert
    0000100f)  ;; # Fn + Suppr
    00001010)  ;; # Fn + End
    00005001)  ;; # Ecran Ferme
    00005002)  ;; # Ecran Ouvert
    *) logger "ACPI hotkey KEY $param2 is not configured";;
  esac
}

ibm_bay()
{
  case "$param1" in
    00000001)
      logger "BAY will be inserted"
      /bin/sleep 1
      /bin/sync
      /sbin/idectl 1 rescan
      ;;
    00000003)
      logger "BAY will be ejected"
      /bin/sync
      /sbin/idectl 1 off
      /bin/echo eject > /proc/acpi/ibm/bay
      ;;
    *) logger "ACPI ibm/bay $param1 is not configured";;
  esac
}

case "$group" in
	button)
	  case "$action" in
	    power) button_power;;
	    sleep) button_sleep;;
	    lid)   button_lid;;
	    *)     logger "ACPI action ${group}/${action} is not defined";;
	  esac
	  ;;
	battery)
	  case "$action" in
	    battery) battery_battery;;
	          *) logger "ACPI action ${group}/${action} is not defined";;
	  esac
	  ;;
	ac_adapter)
	  case "$action" in
	    ac_adapter) ac_adapter_ac_adapter;;
		     *) logger "ACPI action ${group}/${action} is not defined";;
	  esac
	  ;;
	ibm)
	  case "$action" in
	    hotkey) ibm_hotkey;;
            bay)    ibm_bay;;
	    *)      logger "ACPI action ${group}/${action} is not defined";;
	  esac
	  ;;
	processor)
	  case "$action" in
	    processor) processor_processor;;
            *)         logger "ACPI action ${group}/${action} is not defined";;
	  esac
	  ;;
        thermal_zone)
          case "$action" in
            thermal_zone) thermal_zone_thermal_zone;;
            *)         logger "ACPI action ${group}/${action} is not defined";;
	  esac
	  ;;
	*)
	  logger "ACPI group $group / action $action is not defined"
	  ;;
esac