ACPI action script optimized for R51

From ThinkWiki
Jump to: navigation, search

This is a complete acpid and tpb script optimized for a Thinkpad. It is intended to be used by advanced users (as, for example, it gives control over the CPU frequency to the user instead of running a frequency daemon)

It's features include

  • screen blanking / screensaver
  • hibernate / suspend
  • (un)load wlan driver
  • enable/disable lcd/vga
  • change CPU frequency
  • ... See the beginning lines of the script for more detailled information.

<bash>

#!/bin/sh
#
# ACPI handler script default.sh
# Optimized for Thinkpad R51
#
# Copyright (c) Phillip Berndt, 2007
#

## Configuration #####################################################
# X11 access for osd_cat and xset dpms
USER="foo"					# Main user of this PC
export XAUTHORITY="/home/foo/.Xauthority"	# X authority file
export DISPLAY="auto"				# Default display

# Screen saver
LOCKAPP="/usr/bin/xlock"

# WLAN device driver
WLAN_MODULE="ipw2200"
WLAN_PARAMS=""
# or: WLAN_PARAMS="rtap_iface=1"

# Which application to run on "zoom" key
# In my case, start a network autoconfiguration tool AS ROOT!!
# You might want to use "su ${USER} -c <foo>" here
zoom_do() {
	xterm -title "Network autoconfiguration" -e /usr/local/lib/net/network &
}

# File for OSD disabling
OSD_DISABLE_FILE="/var/lib/misc/acpid_osd_disable"

## Help ##############################################################
# 
# Installation:
#  Copy to /etc/acpi/default.sh for acpid and symlink to tpb.sh to use it
#  as a callback script for tpb.
#  Run
#     echo enable,0xffff >/proc/acpi/ibm/hotkey
#     /usr/bin/tpb -d --callback="/etc/acpi/tpb/tpb.sh" -m on -x off
#  on startup.
#
# This script has the following configuration:
#  * F1: Change between performance and powersave govenor (CPU)
#  * F2: dpms force off (Blank screen)
#  * F3: Lock screen
#  * F4: Suspend to ram
#  * F5: Bluetooth on/off
#  * F7: VGA out on/off
#  * F8: LCD on/off
#  * F11: Deactivate OSD
#  * F12: Suspend to disk
#  * Change to performance on AC-plug-in
#  * Change to powersave on AC-unplug
#  * Hibernate on battery power < 5%
#  * Spindown HDD on lid close
#  * Poweroff after pressing the power button TWO times
#  * Load and unload wlan driver on "Access IBM" button
#
# You'll need the following tools to use all features:
#
#  * /usr/sbin/hibernate	Hibernate script
#  * /usr/sbin/radeontool	Radeon graphics settings
#  * /usr/bin/osd_cat		cat'like X11 tool
#  * /usr/bin/xset		Xset (Not installed by default with modular Xorg)
######################################################################

export PATH=/bin/mem:/bin:/usr/bin:/sbin

if [ "$(basename $0)" == "tpb.sh" ]; then
	ACTION="$1"
	PARAMETER="$2"
	logger "Got TPB Event: Action ${ACTION}, Parameter: ${PARAMETER}"
else
	GROUP="${1/\/*/}"
	ACTION="${1/*\//}"
	PARAMETER="$4"
	logger "Got ACPI Event: In Group ${GROUP} action ${ACTION}, Parameter: ${PARAMETER}"
fi

## Functions #########################################################
# OSD cat
if [ "${DISPLAY}" == "auto" ]; then
	X="$(ls /tmp/.X11-unix/X* | head -n1)";
	[ "${X}" != "" ] && export DISPLAY=":${X/\/tmp\/.X11-unix\/X/}"
fi

if [ "${DISPLAY}" != "auto" ] && which osd_cat &>/dev/null; then
	osd() {
		[ -f ${OSD_DISABLE_FILE} ] && return
		pkill osd_cat
		echo $@ | osd_cat -p bottom -A center -c green -O 1 -u black -f "-adobe-helvetica-bold-r-normal-*-*-320-*-*-p-*-iso8859-1" &
	}
else
	osd() {
		logger "OSD cat: $@"
	}
fi

# Suspend to ram
suspram() {
		# Prepare suspend (Power saving hacks)
		chvt 1
		echo -n eject > /proc/acpi/ibm/bay
		ethtool -s eth0 wol d
		
		# Suspend
		sleep 1
		echo mem > /sys/power/state
}

## Handlers ##########################################################
if [ "${ACTION}" == "thinkpad" ]; then
	# Load wlan driver
	if [ -d /sys/module/${WLAN_MODULE} ]; then
		modprobe -r ${WLAN_MODULE}
		osd "${WLAN_MODULE} unloaded"
	else
		modprobe ${WLAN_MODULE} ${WLAN_PARAMS}
		osd "${WLAN_MODULE} loaded"
	fi
fi

if [ "${ACTION}" == "zoom" ]; then
	zoom_do
fi

# Closing the laptop (Or opening it ;))
if [ "${ACTION}" == "lid" ]; then
	if [ "$(cat /proc/acpi/button/lid/LID/state | grep open)" != "" ]; then
		# Enable the LCD
		xset dpms force on
	else
		# Immerdiately spindown the harddrive to prevent loosing data
		# due to drive problems. I'd prefer to power it down, but it
		# needs a very long time to power on again.
		xset dpms force off
		sync
		hdparm -y /dev/hda
	fi
fi

# Special IBM hotkeys
if [ "${ACTION}" == "hotkey" ]; then
	# Change speed
	if [ "${PARAMETER}" == "00001001" ]; then
		DO="performance"
		grep "performance" "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" &>/dev/null && DO="powersave"
		echo ${DO} > "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
		osd "Governor is now ${DO}"
	fi

	# Blank screen
	if [ "${PARAMETER}" == "00001002" ]; then
		xset dpms force off
	fi

	# Blank screen buton (Sleep instead)
	if [ "${PARAMETER}" == "00001003" ]; then
		chvt 1
		xset dpms force off
		su ${USER} -c "${LOCKAPP}" &
	fi

	# Suspend-To-Ram on sleep
	if [ "${PARAMETER}" == "00001004" ]; then
		suspram
	fi

	# Bluetooth
	if [ "${PARAMETER}" == "00001005" ]; then
		DO="disable"
		grep -q "disabled" "/proc/acpi/ibm/bluetooth" && DO="enable"
		echo ${DO} > "/proc/acpi/ibm/bluetooth"
		osd "Bluetooth ${DO}d"
	fi

	# Display (External)
	if [ "${PARAMETER}" == "00001007" ]; then
		if /usr/sbin/radeontool dac | grep -q "looks on"; then
			/usr/sbin/radeontool dac off
			echo "crt_disable" > /proc/acpi/ibm/video
			osd "Video switch (off)"
		else
			/usr/sbin/radeontool dac on
			echo "crt_enable" > /proc/acpi/ibm/video
			osd "Video switch (on)"
		fi
	fi

	# Display (Internal)
	if [ "${PARAMETER}" == "00001008" ]; then
		if /usr/sbin/radeontool light | grep -q "looks on"; then
			/usr/sbin/radeontool light off
			osd "Internal video switch (off)"
		else
			/usr/sbin/radeontool light on
			osd "Internal video switch (on)"
		fi

	fi

	# (De)activate OSD
	if [ "${PARAMETER}" == "0000100b" ]; then
		if [ -f ${OSD_DISABLE_FILE} ]; then
			rm ${OSD_DISABLE_FILE}
			osd "OSD activated"
		else
			osd "OSD deactivated"
			touch ${OSD_DISABLE_FILE}
		fi
	fi

	# Hibernate button
	if [ "${PARAMETER}" == "0000100c" ]; then
		/usr/sbin/hibernate
	fi
fi


# Battery actions
if [ "${GROUP}" == "battery" ]; then
	# $ACTION is the battery i.e. BAT0
	# Get remaining capacity
	capacityPercent=$(/usr/bin/acpitool -b | grep \#$[${ACTION/*[A-Z]/} + 1] | egrep -o [0-9.]+% | egrep -o ^[0-9]+)

	# OSD info
	osd "Battery Event: ${capacityPercent}%"

	# Hibernate on low battery
	if [ "${capacityPercent}" -lt 5 ]; then
		/usr/sbin/hibernate -f
	fi
fi

# Power button
if [ "${ACTION}" == "power" ]; then
	if [ ! -e /var/run/poweroff ]; then
		date "+%s" > /var/run/poweroff
	else
		DIFF=$[ $(date "+%s") - $(cat "/var/run/poweroff") ]
		date "+%s" > /var/run/poweroff

		if [ ${DIFF} -lt 5 ]; then
			/sbin/poweroff
		fi
	fi
fi

# AC Control
if [ "${ACTION}" == "ac_adapter" ]; then
	if [ "`cat /proc/acpi/ac_adapter/AC/state | grep on-line`" != "" ]; then
		echo -n "performance" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
		osd "Powering from AC"
	else
		echo -n "powersave" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
		osd "Powering from Battery"
	fi
fi

</bash>