Prev: Debugging XDMCP X-Windows Service | Next: Home Network Dies on Cable Due To Small MTU |
(Index) |
Starting with kernel 2.6.32 or thereabout, your infrared
remote control stops working. Some keys still work, like arrow keys,
VolumeUp or VolumeDown, and Enter
, but many others produce no
effect, such as Play
and numeric keys.
There's a new paradigm in the world of remote
controls: they have turned into keyboards, and feed their keycodes into the
event subsystem where the keycodes are interpreted just as if they had been
typed on the real
keyboard. In particular, in the very likely case
that the X Window System is in use, any software that has the keyboard focus
can receive the keysyms, without special configuration.
In particular, the LIRC daemon (Linux InfraRed Control) is now deprecated, although it can still be used if its configuration is adjusted.
There is a very small fly in the ointment though: there are two stages where the various drivers have to know which key means what, and if a key is missing or wrong it will not work, producing the symptom complained about.
This whole situation results in a lot of frustrated users posting in forums, with not a whole lot of documentation about what happened and what to do about it. Here is what I did to recover, as the WAF (Wife Acceptance Factor) of my home theater PC dwindled daily.
Naturally this is rather complicated, since the problem is nontrivial. My remote control is a Philips eHome Media Center Edition (MCE) Infrared Remote Control (and receiver), and I will be giving examples for this device, but the same principles apply to all remote control families.
The kernel drivers I have loaded are:
The source code for these drivers is found in /usr/src/linux/drivers/media/rc for kernel 3.2.10, or /usr/src/linux/drivers/media/IR for 2.6.37; I'm not sure when the containing directory was renamed.
First, you need a driver that interacts with USB to obtain infrared data from the receiver. For me this is mceusb. The most common arrangement, including for MCE, is for the driver to deliver a sequence of pulse widths, i.e. how long the signal LED was on, then how long off, and repeating for all the pulses in the signal. Some IR equipment can also transmit, for controlling a closed-source set top box, and it will be told a similar sequence of pulse widths.
Next, the sequence of pulse widths is passed to ir_rc6_decoder and turned bitwise into an integer called the scancode. This is analogous to the scancodes delivered by a normal keyboard. There are several protocols for interpreting the serial IR data, and there are similar decoder modules for rc5 (two variants), jvc, nec, and sony. In addition, LIRC has a codec for capturing raw data. You simplify your life if you blacklist the decoders that you aren't using; some decoders decode promiscuously and produce double keycodes per button press.
Here is how to blacklist a driver. Create a file in /etc/modprobe.d with
the form number-basename.conf, e.g. in my case /etc/modprobe.d/49-lirc.J.conf .
The content would normally be similar to blacklist ir_sony_decoder
,
but this only suppresses autoloading upon hardware detection, and we need to
really suppress the driver in all contexts. Here is what I use:
install ir_sony_decoder /bin/true
install ir_jvc_decoder /bin/true
install ir_rc5_decoder /bin/true
install ir_nec_decoder /bin/true
I'm leaving alone the ir_lirc_codec and ir_mce_kbd_decoder although I am not using LIRC any more, and ir_mce_kbd_decoder appears to be for a complete infrared keyboard that I don't have.
Next the scancode is interpreted using the default keymap in rc_rc6_mce
(source is in the keymaps subdirectory). This translates scancodes to
keycodes. All devices using the event subsystem are supposed to translate
their idiosyncratic scancodes into the same set of keycodes, which are defined
in /usr/src/linux/include/linux/input.h (which is similar but not identical
to /usr/include/linux/input.h). Both the scancodes and keycodes come out
on /dev/input/event${N} for some N. Look at /proc/bus/input/devices to find
out the event device: under N: find the name of the device, then under H:
find out its handlers
which include the event device's basename.
/lib/udev/rules.d/51-lirc.rules causes any device with IR
in its
name to receive a symlink /dev/input/ir , such as in my case the Microsoft
Wireless Laser Mouse 8000
, which is not very useful. This rule file could
be overridden (you add a file in /etc/udev/rules.d) to make sure the
real IR device gets the symlink.
If you install the v4l-utils package it gives you copies of the official keymaps that are hardwired in rc_rc6_mce and its numerous friends. These files end up in /etc/rc_keymaps . This is for OpenSuSE 11.4, and other distros (I think Ubuntu is one) may put them in another directory, and you have to copy the actually used keymap into /etc/rc_keymaps .
You also get (among others) the ir-keytable command. If you execute it without command line arguments it will report the number (here rc3) of the remote control, the /dev/input/event${N} device, and data about the device. In my case:
Found /sys/class/rc/rc3/ (/dev/input/event8) with: Driver mceusb, table rc-rc6-mce Supported protocols: RC-6 LIRC other Enabled protocols: RC-6 Repeat delay = 500 ms, repeat period = 125 ms
In a modern UNIX distro, the HAL daemon is aware when an input device is hotplugged, and it signals the X Window System to add any such devices as keyboards or mice. Unless overridden, the X-server uses the evdev driver with the standard keycodes from /usr/share/X11/xkb/keycodes/evdev . This file maps the standard event system keycodes into code names for the keys. Drivers other than evdev have their idiosyncratic mappings, generally from raw scancodes to keycode names.
Then the keycode names are interpreted according to
/usr/share/X11/xkb/symbols/us and /usr/share/X11/xkb/symbols/inet . This
maps keycode names to keysyms, which are semantic interpretations of the
keys such as parenright
or XF86AudioRewind
. The keysyms are
defined in /usr/include/X11/keysymdef.h (for standard keysyms) or
/usr/include/X11/XF86keysym.h (for multimedia keysyms). These keysyms are
what goes out to the applications.
Assuming of course that your key generates an event keycode that maps to a keycode name, and the keycode name is in the symbol table and maps to a useable keysym, which is not the case for quite a number of keys on the remote control.
First install the v4l-utils package, execute ir-keytable (no arguments),
and identify the keytable that you are using. Make sure the protocol is
appropriate for the keytable, e.g. in my case, protocol RC-6 for keytable
rc6_mce. Find the keytable in /etc/rc_keymaps. For me it is
/etc/rc_keymaps/rc6_mce. View this file. If there is a question which
keytable is being used, or whether the keytable has been trashed, do
ir-keytable -r
and compare what it prints with the contents of the
keytable file. The file has lines such as:
0x800f0414 KEY_FASTFORWARD 0x800f0415 KEY_REWIND 0x800f0416 KEY_PLAY 0x800f0417 KEY_RECORD 0x800f0418 KEY_PAUSE
To test the remote control, execute ir-keytable -t
. If you have
hotplugged your infrared receiver several times, ir-keytable may report that
the sysfs device is something other than /sys/class/rc/rc0, and ir-keytable
-t
will fail to find this device since the default is rc0. In my case it's
rc3, so I would do ir-keytable -s rc3 -t
.
Press each button on your remote control. ir-keytable will print out the
scancode in hex, and then the event keycode by name and number. If any button
produces a scancode but no keycode, verify that the scancode is missing from
the keytable. Later when you edit the keytable file, you can add this scancode
and create a keycode to go with it. In my case, /etc/rc_keymaps/rc6_mce had a
keycode with plausible semantics for every actually produced scancode, plus
more scancode-keycode combinations for what appears to be a complete keyboard,
which I don't have. By plausible
I mean for example that the keycode
for the record button is called KEY_RECORD and not something irrelevant.
Now go through /usr/share/X11/xkb/keycodes/evdev and find the key name that goes with the event keycode. This has lines like:
<AE10> = 19; (zero key) <I150> = 150; // #define KEY_SLEEP 142 <I175> = 175; // #define KEY_RECORD 167 <I171> = 171; // #define KEY_NEXTSONG 163 <I173> = 173; // #define KEY_PREVIOUSSONG 165
Generally the numeric value that goes with the key name is 8+event keycode. If any keycode lacks a key name, you will have to pick a different keycode that has a key name. For example, rc6_mce assigns KEY_NEXT to scancode 0x800f041a, but KEY_NEXT has no key name. Therefore I changed the assignment to KEY_NEXTSONG, which does have an assigned key.
Now that you have the key names, check in /usr/share/X11/xkb/symbols/us (or whichever one your X-server is using) and /usr/share/X11/xkb/symbols/inet. If a key name does not appear in the symbol tables, you will have to pick a key that does appear, and assign its event keycode to the remote control's scancode. Or you can create your own symbol table fragment and arrange for it to be loaded.
These are the changes I had to make in /etc/rc_keymaps/rc6_mce so that every button produces a keysym.
Label | Scancode | Keycode | Formerly | Key Name | Keysym |
---|---|---|---|---|---|
0 | 0x800f0400 | KEY_0 | KEY_NUMERIC_0 | <AE10> | ASCII zero |
--And similarly for all the numeric keys | |||||
(i) | 0x800f040f | KEY_MENU | KEY_INFO | <I147> | XF86MenuKB |
ch+ | 0x800f0412 | KEY_SCROLLUP | KEY_CHANNELUP | <I185> | XF86ScrollUp |
ch- | 0x800f0412 | KEY_SCROLLDOWN | KEY_CHANNELDOWN | <I185> | XF86ScrollDown |
>| | 0x800f041a | KEY_NEXTSONG | KEY_NEXT | <I171> | XF86AudioNext |
|< | 0x800f041b | KEY_PREVIOUSSONG | KEY_PREVIOUS | <I172> | XF86AudioPrev |
# | 0x800f041c | KEY_KPCOMMA | KEY_NUMERIC_POUND | <I126> | plusminus |
--It's not clear why it comes out as key I126 rather than the nonexistent I129, but it does. | |||||
* | 0x800f041d | KEY_KPPLUSMINUS | KEY_NUMERIC_STAR | <KPDL> | KP_Decimal |
--It's not clear why it comes out as key KPDL rather than I126, but it does. | |||||
OK | 0x800f0422 | KEY_SEND | KEY_OK | <I239> | XF86Send |
O | 0x800f0424 | KEY_MSDOS | KEY_DVD | <I159> | XF86DOS |
-> TV | 0x800f0425 | KEY_CALC | KEY_TUNER | <I148> | XF86Calculator |
--Label looks like a TV with a play button, so it's the PVR. | |||||
Guide | 0x800f0426 | KEY_FILE | KEY_EPG | <I152> | XF86Explorer |
Red TV | 0x800f0448 | KEY_CAMERA | KEY_PVR | <I220> | XF86WebCam |
--Label looks like on-air capture, so it's the live TV button. |
As a next step, not covered here, you will need to train
the
application(s) to recognize the keysyms that they will be given.
Download links for fixed files:
At least in kernel 3.2.10, if you plug my IR receiver into a USB-3.0 (xhci) port, or a hub connected to USB-3.0, it will deliver no data. Workaround: use a USB-2.0 port. This is on a Zotac ZBOX AD03BR.
Prev: Debugging XDMCP X-Windows Service | Next: Home Network Dies on Cable Due To Small MTU |
(Index) |