CORRECT SYSTEM DESIGN GROUP
Uni Fk. II Informatik theoretica CSD ~eagle myACPId

My Configuration for acpid

On this page:

 

go next top of page

1 Intro

Using the acpid daemon to perform some powersaving steps might be a good idea for most notebooks. But many default configurations for the daemon are not very smart (all I have seen were not). So I wrote my own configuration.

 

go next top of page go back

2 What should it do?

There are two power states I want to be able to trigger: power off and suspend to RAM (unfortunatly ACPI hibernate (suspend to disk) was not supported in the versions of my linux kernel until now). The easy way to do this is to use the two buttons (power and lid button) and this is what the configurations I have seen did.

But when I want to access my notebook from remote I would not be able to close the lid because that would suspend the computer. The same problem occures if my machine is shutting down and I close the lid before the acpid was stopped. In that case the computer will suspend in the shutting down process - not very nice.

So here is what I want:
If the notebook is on AC power I will be able to close the lid. I want to be able to suspend it and to shut it down but in a failsave manner. So this is guarteed by requiring that the power button was pressed at most 4 seconds before the button was pressed that will trigger the event. If the computer runs on battery it should save power and therefore suspend immediatly when closing the lid. And finally when the sustem is shutting down there will be no suspend possible.

power buttonlid button
on AC powershut down if power button was pressed the second time within 4 seconds, else ignoredsuspend if power button was pressed at most 4 seconds before, else ignored
on batteryshut downsuspend
shutting downignoreignore

 

go next top of page go back

3 The Script

Here you will find the main shell script that performs the steps for the above operations. The action is taken either from the name that was used to call the script or from the first parameter.

go next top of page go back

3.1 Variables

We use variables to set up the locations of lock files and the ACPI files.


#!/bin/sh -e
# /etc/acpi/lidbtn.sh
# Initiates a sleep S1 if the display lid is closed.
# Wake up by pressing on/off button.

LOCKDIR=/var/lock
SUSPEND_LOCK=$LOCKDIR/suspend
POWER_LOCK=$LOCKDIR/power

LID_STATE_FILE="/proc/acpi/button/lid/LID/state"
AC_STATE_FILE="/proc/acpi/ac_adapter/AC/state"

go next top of page go back

3.2 Getting the State

Here are the functions we use to access the states of the lid, the AC adapter and the current runlevel.


get_lid_state() {
	local TEMP STATE
	# there shoud only be one directory in /proc/acpi/button/lid/ 
	read TEMP STATE < $LID_STATE_FILE
	case $STATE in
		clo*|CLO*) echo CLOSE ;;
		*)         echo OPEN  ;;
	esac
}

get_ac_adapter_state() {
	local TEMP STATE
	read TEMP STATE < $AC_STATE_FILE
	case $STATE in
		off*|OFF*) echo OFF ;;
		*)         echo ON  ;;
	esac
}

get_runlevel() {
	local STATE
	STATE=`/sbin/runlevel | cut -c3`
	case $STATE in
		0|6)       echo OFF ;;
		1|2|3|4|5) echo ON  ;;
	esac
}

go next top of page go back

3.3 Enter/Leave Standby

Perhaps some care must be taken for suspend. E.g., my notebook will not wake up correctly if USB was still running, so I will shut down the hotplug system before suspend and restart it after the system wakes up from suspend. And saving the system clock to the hardware clock is always a good idea. ;o)


enter_standby() {
#	create lock file
	touch $SUSPEND_LOCK
	echo enter_standby
#	work around bug in USB re-initialization after sleep
	/etc/init.d/hotplug stop
#       reset the hardware clock to the system clock
        hwclock --systohc
#	put the notebook to sleep
	echo -n 1 > /proc/acpi/sleep
}

leave_standby() {
        echo leave_standby 
#	work around bug in USB re-initialization after sleep
	/etc/init.d/hotplug start
#	reset the system clock to the hardware clock
	hwclock --hctosys
#	rm lock files
	rm -f $SUSPEND_LOCK $POWER_LOCK
}

go next top of page go back

3.4 The Main Actions


if [ "`get_runlevel`" == "OFF" ]; then
    # shutting down: ignore any action
    exit 0
fi

# get the action
if [ -z $1 ]; then 
    ACTION=$0
else
    ACTION=$1
fi

echo "action=$ACTION"
case $ACTION in
    *lidbtn.sh)
	if [ ! -e $SUSPEND_LOCK -a "`get_lid_state`" == "CLOSE" ]; then
	    # we are not suspending...
	    if [ -e $POWER_LOCK -o "`get_ac_adapter_state`" == "OFF" ]; 
	    then
	        # ...and the power button was pressed before or we run 
		# on battery
		enter_standby
	    fi
	fi
	;;
    *powerbtn.sh)
	if [ -e $SUSPEND_LOCK ]; then
	    # we were suspended, so this is the wake up event
	    leave_standby
	elif [ -e $POWER_LOCK -o "`get_ac_adapter_state`" == "OFF" ]; 
	then
	    # the power button was pressed before or we run on battery
	    # so we will shut down the system
	    echo shutting down 
	    rm -f $SUSPEND_LOCK $POWER_LOCK
	    /sbin/init 0
	else
	    # the power button is pressed the first time and we are  
	    # not running on battery. We will remember the power 
	    # button event by creating the lock file and removing it 
	    # (in a new shell) after 4 seconds.
	    echo prepare shut down   or  standby
	    touch $POWER_LOCK
	    ( sleep 4 ; rm $POWER_LOCK ) &
	fi
	;;
    *ac_adapter.sh)
	if [ ! -e $SUSPEND_LOCK -a "`get_ac_adapter_state`" == "OFF" ]; 
	then
	    if [ "`get_lid_state`" == "CLOSE" ]; then
	        # we switch to from AC power to battery. Therfore if 
		# the lid is closed we will suspend the machine.
		enter_standby
	    else
		echo ac ignore
	    fi
	fi
	;;
    *standby)
	if [ ! -e $SUSPEND_LOCK ]; then
	    enter_standby
	fi
	;;
esac

 

go next top of page go back

4 acpid Event Triggers

Store the above script in e.g. /etc/acpi/lidbtn.sh and create /etc/acpi/ac_adapter.sh and /etc/acpi/powerbtn.sh as (symbolic or hard) links to the file.

Now we have to disable the default events. The simple way to do so is to rename the /etc/acpi/events directory and create a new one.

/etc/acpi/events/ac_adapter

event=ac_adapter
action=/etc/acpi/ac_adapter.sh
/etc/acpi/events/lidbtn

event=button/lid
action=/etc/acpi/lidbtn.sh
/etc/acpi/events/powerbtn

event=button[ /]power
action=/etc/acpi/powerbtn.sh

 

go next top of page go back

5 Download

You can download this configuration as a tar file. Please let me know if it was useful for you and if you could improve the script.

You can also download my new configuration for SuSE 9.2/kernel 2.6.8 (see below for a description of changes). Please let me know if it works for you.

 

go next top of page go back

6 Update for SuSE 9.2 / Kernel 2.6.8

With SuSE 9.1 it was no longer possible to use my script(s) if you were also using the powersaved - and since that tool provides some nice features I recommend to use it. But powersaved read the /proc/acpi/events, so that it was impossible to start acpid.

In SuSE 9.2 the powersaved was changed to get its events from acpid and thus using my scripts with acpid is possible, again.

Along with this change the new Linux kernel that comes with SuSE 9.2 (kernel 2.6.8) provides software suspend to disk that works with my notebook (the first time). Sleep and suspend-to-disk seem to work without shutting down hotplug.

So what actually changed? The acpid that is started from the powersaved init script uses the configuration in /etc/acpi/events.ignore. So the trigger there (events.ignore) has to be moved (or removed) and my own triggers go there.

Next there is a change in ACPI event handling: any ACPI event seems to wake up the notebook from sleep and that event is not reported (any more). So deleting the suspend lock triggered by the power button will not work (well). Instead I added a sleep 1 and a call to leave_standby in enter_standby, to get the lock removed.

Instead of shutting down the system (on power button pressed twice) I now perform a suspend to disk. To do so I copied the code from enter_standby and replaced the sleep-command (echo -n 1 > /proc/acpi/sleep) with the suspend-to-disk command (echo -n disk > /sys/power/state)

There seem to be a problem with button events dissapearing in the 2.6.x series of the kernel (Thanks to Andrew Waldram for reporting this). Reloading the kernel module "button" will prevent the events from disappearing.

You can also download my new configuration for SuSE 9.2/kernel 2.6.8.

 

go next top of page go back

7 Disclaimer

No warranty! All information I'm giving here is provided without any guarantee. I hope it is useful (please let me know if so), but I will not be responsible for any harm happening to someone or something due to this description.

 top of page go back

 

Univ. | Univ. - News | Univ. - Study | Univ. - International Office | Univ. - Imprint | Univ. - Search
HTML-coding powered by htp