viernes, 25 de noviembre de 2011

Executing with a key/button (how to hibernate without the propper button) + ACPI bug workaround

Some time ago I found a problem with one of my desktops when remapping the acpi power button events to hibernate instead of power off the machine, the machine was sending two events on each button press which sadly meant that Linux would hibernate again when powering the machine on :-(
The solution I had to apply to this was to protect my hibernate acpi support script with a lock that avoids the double pm-hibernate call. This ended up being like something like this: if lockfile -r0 /etc/acpi/powerbtn.lock
then
...
pm-hibernate
( sleep 2 ; rm -f /etc/acpi/powerbtn.lock ) &
fi

Anyway, while I was waiting for the ACPI guys not to answer me I was exploring some things which are the ones I wanted to write down here.

First: The good old typical linux low level mapping with setkeycodes, in this case if you want to map scroll lock (0x46) to the sleep key (142) you'll do setkeycodes 46 142 You can use showkey -s to see the scancodes and look for key codes at /usr/include/linux/input.h and /usr/share/acpi-support/key-constants

Second: If you happen to have around a webcam with a button you can try to do something with it, if you are lucky enough that button may be mapped to the "XF86WebCam" key, this happened to me on a Logitech Quickcam 5500 (046d:09a1). It is easy on icewm to map this key writing on .icewm/keys something like this that execs your favourite command:key "XF86WebCam" favourite_command As usual the typical tools like xev, configs like ~/.Xmodmap and infos like /usr/share/X11/XKeysymDB apply here.
There is something you must be aware of, the webcam button may not work if the camera device is not opened, in this case you can launch on background on your startup sequence a little perl script like this one which sleeps forever once it opens the video device: perl -e "open(FILE, '/dev/v4l/by-id/usb-046d_09a1_76A5BF10-video-index0') || die 'Cannot open the device\n';sleep;" &
Third: There are some programs like esekeyd and triggerhappy that can map your events (like the ones from the webcam) to keys and things like that, esekeyd has some limitations I comment here and triggerhappy is supposed to be a bit more powerfull, but I don't know if triggerhappy can work without the perl script I commented earlier, esekeyd right now can't. The config for esekeyd on my machine was to set on /etc/defaults/esekeyd this: DAEMON_OPTS="/etc/esekeyd.conf /dev/input/by-id/usb-046d_09a1_76A5BF10-event-if00" and then I used acpi_fakekey from the acpi-fakekey package to fake the sleep key (142, see first comment on where to get the codes) when the camera button is pressed by setting on esekeyd.conf this: CAMERA(press): acpi_fakekey 142
Fourth: Userspace typically can't just signal hibernate but there I discovered the upower package that allows you to signal hibernate from userspace using a dbus signal and works great, with that my second example ended up with this sh oneliner (that locks my desktop and then sends the hibernate event wich acpi processes) on .icewm/keys: key "XF86WebCam" sh -c "xscreensaver-command -lock && dbus-send --print-reply --system --dest=org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower.Hibernate"