Sunday 8 June 2014 by Bradley M. Kuhn
In keeping with my tendency to write a blog post about any technical issue I find that takes me more than five minutes to figure out when searching the Internet, I include below a resolution to a problem that took me, embarrassingly, nearly two and half hours across two different tries to figure out.
The problem appeared when I took Debian 7 (wheezy) laptop hard drive out of an Lenovo Thinkpad T61 that I was using that failed and into Lenovo Thinkpad T60. (I've been trying to switch fully to the T60 for everything because it is supported by Coreboot.)
When I switched, everything was working fine, except the volume buttons on
the Thinkpad T60 (those three buttons in the top left hand corner of the
keyboard, shown circled in purple in the image on the right) no longer did
what I expected. I expected they would ultimately control PulseAudio volume,
which does the equivalent of pactl set-sink-mute 0 0
and
appropriate pactl set-sink-volume 0
commands for my sound card.
I noticed this because when PulseAudio is running, and you type those
commands on the command line, all functions properly with the
volume, and, when running under X, I see the popup windows coming
from my desktop environment showing the volume changes. So, I knew nothing
was wrong with the sound configuration when I switched the hard drive to a
new machine, since the command line tools worked and did the right things.
Somehow, the buttons weren't sending the same commands in whatever manner
they were used to.
I assumed at first that the buttons simply generated X events. It turns
out they do, but the story there is a bit more complex. When I
ran xev
I saw those buttons did not, in fact, generate any X
events. So, that makes it clear that nothing from X windows
“up” (i.e, to the desktop software) had anything to do with the
situation.
So, I first proceed to research whether these volume keys were supposed to generate X events. I discovered that there were indeed XF86VolumeUp, XF86VolumeDown and XF86VolumeMute key events (I'd seen those before, in fact, doing similar research years ago). However, the advice online was highly conflicting whether or not the best way to solve this is to have them generate X events. Most of the discussions I found assumed the keys were already generating X events and had advice about how to bind those keys to scripts or to your desktop setup of choice0.
I found various old documentation about the thinkpad_acpi
daemon, which I quickly found quickly was out of date since long ago that
had been incorporated into Linux's ACPI directly and didn't require
additional daemons. This led me to just begin poking around about how the
ACPI subsystem for ACPI keys worked.
I quickly found the xev
equivalent for
acpi: acpi_listen
. This was the breakthrough I needed to
solve this problem. I ran acpi_listen
and discovered that
while other Thinkpad key sequences, such as Fn-Home
(to
increase brightness), generated output like:
video/brightnessup BRTUP 00000086 00000000 K
video/brightnessup BRTUP 00000086 00000000
That's when I started poking around in /proc
, and found
that /proc/acpi/ibm/volume
was changing each time I
hit a these keys. So, Linux clearly was receiving notice that these keys
were pressed. So, why wasn't the acpi subsystem notifying anything else,
including whatever interface acpi_listen
talks to?
Well, this was a hard one to find an answer to. I have to admit that I
found the answer through pure serendipity. I had already
loaded this
old bug report for an GNU/Linux distribution waning in popularity and
found that someone resolved the ticket with the command:
cp /sys/devices/platform/thinkpad_acpi/hotkey_all_mask /sys/devices/platform/thinkpad_acpi/hotkey_mask
# cat /sys/devices/platform/thinkpad_acpi/hotkey_all_mask /sys/devices/platform/thinkpad_acpi/hotkey_mask
0x00ffffff
0x008dffff
# cat /sys/devices/platform/thinkpad_acpi/hotkey_all_mask > /sys/devices/platform/thinkpad_acpi/hotkey_mask
Additional searching show this hotkey issue is documented in Linux, in its Thinkpad ACPI documentation, which states:
The hot key bit mask allows some control over which hot keys generate events. If a key is "masked" (bit set to 0 in the mask), the firmware will handle it. If it is "unmasked", it signals the firmware that thinkpad-acpi would prefer to handle it, if the firmware would be so kind to allow it (and it often doesn't!).
I note that on my system, running the command the document recommends to
reset to defaults yields me back to the wrong state:
# cat /proc/acpi/ibm/hotkey
status: enabled
mask: 0x00ffffff
commands: enable, disable, reset, <mask>
# echo reset > /proc/acpi/ibm/hotkey
# cat /proc/acpi/ibm/hotkey
status: enabled
mask: 0x008dffff
commands: enable, disable, reset, <mask>
# echo 0xffffffff > /proc/acpi/ibm/hotkey
So, I added that last command above to restore it to enabled Linux's control of all the ACPI hot keys, which I suspect is what I want. I'll update the post if doing that causes other problems that I hadn't seen before. I'll also update the post to note whether this setting is saved over reboots, as I haven't rebooted the machine since I did this. :)
0Interestingly, as has happened to me often recently, much of the most useful information that I find about any complex topic regarding how things work in modern GNU/Linux distributions is found on the Arch or Crunchbang online fora and wikis. It's quite interesting to me that these two distributions appear to be the primary place where the types of information that every distribution once needed to provide are kept. Their wikis are becoming the canonical references of how a distribution is constructed, since much of the information found therein applies to all distributions, but distributions like Fedora and Debian attempt to make it less complex for the users to change the configuration.
Posted on Sunday 8 June 2014 at 13:30 by Bradley M. Kuhn.
Comment on this post in this identi.ca conversation.
This website and all documents on it are licensed under a Creative Commons Attribution-Share Alike 3.0 United States License .
#include <std/disclaimer.h>
use Standard::Disclaimer;
from standard import disclaimer
SELECT full_text FROM standard WHERE type = 'disclaimer';
Both previously and presently, I have been employed by and/or done work for various organizations that also have views on Free, Libre, and Open Source Software. As should be blatantly obvious, this is my website, not theirs, so please do not assume views and opinions here belong to any such organization.
— bkuhn
ebb is a (currently) unregistered service mark of Bradley M. Kuhn.
Bradley M. Kuhn <bkuhn@ebb.org>