HID Remotes

From MythTV Official Wiki
(Redirected from Generic HID "MCE" Remotes)
Jump to: navigation, search

Generic HID / MCE Remotes

An example of one of many of these remotes.

This is for any genuine MCE_Remote receiver after kernel 2.6.35 and for any generic remote that appears as a USB HID keyboard. HID keyboard remotes tend to be very popular on eBay, advertising themselves as MCE Remotes and originating from Asia. One popular model at the moment is the YAOCOO MCEY06. The HDPLEX internal remote is also a USB HID Device that can benefit from these techniques.

Description

These remotes act and look just like a USB keyboard (and sometime a mouse as well) to the system. There is no need for any LIRC drivers for this to work, provided a sufficiently recent kernel.

When plugging a HID keyboard remote receiver, dmesg should show something similar to the following:

usb 1-2: new low speed USB device using ohci_hcd and address 3
usb 1-2: configuration #1 chosen from 1 choice
input: USB HID v1.10 Keyboard [HOLTEK USB To PS2 Devic] on usb-0000:00:0b.0-2
input,hiddev96: USB HID v1.10 Mouse [HOLTEK USB To PS2 Devic] on usb-0000:00:0b.0-2

Unfortunately the keypresses simulated by these HID keyboard remotes may not all work with MythTV. For example, the remote linked above uses Ctrl+b, Ctrl+p, Ctrl+f for reverse skip, pause, and forward skip, while using Ctrl+B, Ctrl+P, Ctrl+F for rewind, play and ffwd. I don't believe MythTV keybindings are case sensitive so the Ctrl+b and Ctrl+Shift+b are indistinguishable from each other. In addition to this, there are a number of keys that generate unmapped keycodes which don't work in MythTV.

Similarly, some keypresses generated by genuine MCE remotes are by default mapped to scan codes higher than 255 in some distros. The most common problem is the "OK" button does not work out-of-the-box. This is because scancodes over 255 are not yet supported in X and probably won't be anytime soon.

Solutions

There are three ways to solve the problem created by the mapping of these devices. The first, ir-keytable, is recommended for genuine MCE remotes. For genuine and for HID keyboard remotes, you can use xmodmap or xkb. Unfortunately, using xmodmap means that if you connect a standard USB keyboard to your frontend it's keys will also be remapped. This will leave you unable to type a capital P, B, F, etc. Xkb is more complex, but permits remapping on a per device basis.

ir-keytable

To see if you can use ir-keytable, first run

 ir-keytable

This will show you a list of all detected remote receivers. A genuine MCE remote will look like this:

 # ir-keytable
 Found /sys/class/rc/rc0/ (/dev/input/event3) with:
       Driver mceusb, table rc-rc6-mce
       Supported protocols: NEC RC-5 RC-6 JVC SONY SANYO LIRC other
       Enabled protocols: NEC RC-5 RC-6 JVC SONY SANYO LIRC other
       Name: Media Center Ed. eHome Infrared
       bus: 3, vendor/product: 0609:031d, version: 0x0000
       Repeat delay = 500 ms, repeat period = 125 ms

Interestingly, although the Phillips RC5/RC6 protocol is used for most MCE remotes, the receiver is often able to receive other protocols as well, leaving the possibility that you can use your TV or other non-MCE remote to control Myth if you load the correct keymap (detailed later).

It is not necessary to set the device (-d) or protocol (-p) in ir-keymap if the ones you want are already enabled by default.

If ir-keytable does not list your remote receiver, you may need to 'modprobe' the correct module for your remote. Here are the drivers used for a genuine MCE remote on Debian Jessie:

 #lsmod | grep mce
 ir_mce_kbd_decoder     12574  0
 edac_mce_amd           21166  0
 rc_rc6_mce             12396  0
 mceusb                 17002  0
 rc_core                22331  12 lirc_dev,ir_lirc_codec,ir_rc5_decoder,ir_nec_decoder,ir_sony_decoder,mceusb,ir_mce_kbd_decoder,ir_jvc_decoder,ir_rc6_decoder,ir_sanyo_decoder,rc_rc6_mce
 usbcore               178937  7 usb_storage,ohci_hcd,ohci_pci,ehci_hcd,ehci_pci,mceusb,xhci_hcd

Once ir-keytable recognizes your remote, run

 ir-keytable -t

and press some buttons on your remote. Hopefully, your distro has already put the remote keymaps in the right place for you, and you should see things like:

 1411835328.484663: event type EV_MSC(0x04): scancode = 0x800f041f
 1411835328.484663: event type EV_KEY(0x01) key_down: KEY_DOWN(0x0001)
 1411835328.484663: event type EV_SYN(0x00).
 1411835328.734892: event type EV_KEY(0x01) key_up: KEY_DOWN(0x0001)
 1411835328.734892: event type EV_SYN(0x00).

If no output is generated, you will need to locate the keymap (in Debian Jessie the keymaps are found in /lib/udev/rc_keymaps/) and load it manually with

 ir-keytable -w rc6_mce

where rc6_mce is the keymap appropriate for your remote.

At this point, you can conduct a further test with

 evtest

Select your remote from the list:

 # evtest
 No device specified, trying to scan all of /dev/input/event*
 Available devices:
 /dev/input/event0:      Power Button
 /dev/input/event1:      Power Button
 /dev/input/event2:      Video Bus
 /dev/input/event3:      Media Center Ed. eHome Infrared Remote Transceiver (0609:031d)
 /dev/input/event4:      PC Speaker
 /dev/input/event5:      MCE IR Keyboard/Mouse (mceusb)
 /dev/input/event6:      HD-Audio Generic HDMI/DP,pcm=3
 /dev/input/event7:      HD-Audio Generic Line Out
 /dev/input/event8:      HD-Audio Generic Line
 /dev/input/event9:      HD-Audio Generic Rear Mic
 Select the device event number [0-9]: 3

In this case, the correct selection is 3, not 5! You may refer to the ir-keytable output above to see why this is the case. Your setup may differ, though, so try the likely suspects until pressing buttons on your remote generates output:

 Testing ... (interrupt to exit)
 Event: time 1411835779.916103, type 4 (EV_MSC), code 4 (MSC_SCAN), value 800f041f
 Event: time 1411835779.916103, type 1 (EV_KEY), code 108 (KEY_DOWN), value 1
 Event: time 1411835779.916103, -------------- EV_SYN ------------
 Event: time 1411835780.050097, type 4 (EV_MSC), code 4 (MSC_SCAN), value 800f041f
 Event: time 1411835780.050097, -------------- EV_SYN ------------
 Event: time 1411835780.298879, type 1 (EV_KEY), code 108 (KEY_DOWN), value 0
 Event: time 1411835780.298879, -------------- EV_SYN ------------

At this point, you should be able to use some of your remote buttons in Myth. However, you will likely find that a lot of them, like "OK", do not work. The solution is relatively simple -- we need to remap the non-working buttons to scancodes less than 255.

Editing the keytables directly has no effect in Debian. No problem -- we will just make our own keytable, modify it, and then load it. To make your own keytable, change to a convenient directory (such as /root/), and run

 ir-keytable -r > mykeytable

Now we can edit it:

 nano mykeytable

Right at the top you'll probably see something like

 scancode 0x800f0400 = KEY_NUMERIC_0 (0x200)

The scancode at the beginning is the remote's "input" scancode. The text symbol on the right is the kernel's keyboard "output" scancode. Don't touch the remote input scancodes -- we will only be altering the keyboard output codes.

So -- see that hex code at the end of the line? It's more than 0xFF, which means it's a scancode more than 255, which X (and therefore Myth) cannot see. Let's refer to the kernel's (dead url removed) input.h for a list of valid keyboard scancodes. We can see that the standard KEY_0 scancode makes sense and is less than 255, so let's use it. Also, let's document what the key originally was (just for future reference):

 scancode 0x800f0400 = KEY_0 (0x200) # NUMERIC_0

You'll see that it is not necessary to update the numeric scancode in parenthesis -- ir-keytable ignores them. You only need to change the text symbol.

A number of other keys need to be remapped. You'll probably want to remap KEY_OK to KEY_ENTER, for example. Some keys don't have a logical mapping; in such cases, you can pick pretty much whatever keyboard scancode you want from input.h that's unlikely to be used anywhere else. For example, the higher Function keys like F13 and up usually don't even exist on standard keyboards, so are usually pretty safe to use.

Also, there are some scancodes that are less than 255, such as KEY_EXIT, that Myth nevertheless does not recognize by default. You can use Myth's Keybindings feature to use them, but I prefer to remap KEY_EXIT to KEY_ESC so that I don't have to use a Myth Keybinding for that button.

Here is my entire RC6 keytable for reference. This table minimizes the number of Keybindings required in Myth, though you are of course welcome to customize your own map as you see fit.

 scancode 0x800f0400 = KEY_0 (0x200) # NUMERIC_0
 scancode 0x800f0401 = KEY_1 (0x201) # (etc...)
 scancode 0x800f0402 = KEY_2 (0x202)
 scancode 0x800f0403 = KEY_3 (0x203)
 scancode 0x800f0404 = KEY_4 (0x204)
 scancode 0x800f0405 = KEY_5 (0x205)
 scancode 0x800f0406 = KEY_6 (0x206)
 scancode 0x800f0407 = KEY_7 (0x207)
 scancode 0x800f0408 = KEY_8 (0x208)
 scancode 0x800f0409 = KEY_9 (0x209)
 scancode 0x800f040a = KEY_DELETE (0x6f)
 scancode 0x800f040b = KEY_RESERVED (0x1c) # ENTER
 scancode 0x800f040c = KEY_SLEEP (0x8e)
 scancode 0x800f040d = KEY_M (0xe2) # MEDIA
 scancode 0x800f040e = KEY_MUTE (0x71)
 scancode 0x800f040f = KEY_I (0x166) # INFO
 scancode 0x800f0410 = KEY_VOLUMEUP (0x73)
 scancode 0x800f0411 = KEY_VOLUMEDOWN (0x72)
 scancode 0x800f0412 = KEY_PAGEUP (0x192) # CHANNELUP
 scancode 0x800f0413 = KEY_PAGEDOWN (0x193) # CHANNELDOWN
 scancode 0x800f0414 = KEY_DOT (0xd0) # FASTFORWARD
 scancode 0x800f0415 = KEY_COMMA (0xa8) # REWIND
 scancode 0x800f0416 = KEY_P (0xcf) # PLAY
 scancode 0x800f0417 = KEY_RECORD (0xa7)
 scancode 0x800f0418 = KEY_P (0x77) # PAUSE
 scancode 0x800f0419 = KEY_STOP (0x80)
 scancode 0x800f041a = KEY_F13 (0x197) # NEXT
 scancode 0x800f041b = KEY_F14 (0x19c) # PREVIOUS
 scancode 0x800f041c = KEY_W (0x20b) # NUMERIC_POUND
 scancode 0x800f041d = KEY_KPASTERISK (0x20a) # NUMERIC_STAR
 scancode 0x800f041e = KEY_UP (0x67)
 scancode 0x800f041f = KEY_DOWN (0x6c)
 scancode 0x800f0420 = KEY_LEFT (0x69)
 scancode 0x800f0421 = KEY_RIGHT (0x6a)
 scancode 0x800f0422 = KEY_ENTER (0x160) # OK
 scancode 0x800f0423 = KEY_ESC (0xae) # EXIT
 scancode 0x800f0424 = KEY_DVD (0x185)
 scancode 0x800f0425 = KEY_TUNER (0x182)
 scancode 0x800f0426 = KEY_EPG (0x16d)
 scancode 0x800f0427 = KEY_ZOOM (0x174)
 scancode 0x800f0432 = KEY_MODE (0x175)
 scancode 0x800f0433 = KEY_PRESENTATION (0x1a9)
 scancode 0x800f0434 = KEY_EJECTCD (0xa1)
 scancode 0x800f043a = KEY_BRIGHTNESSUP (0xe1)
 scancode 0x800f0446 = KEY_TV (0x179)
 scancode 0x800f0447 = KEY_AUDIO (0x188)
 scancode 0x800f0448 = KEY_PVR (0x16e)
 scancode 0x800f0449 = KEY_CAMERA (0xd4)
 scancode 0x800f044a = KEY_VIDEO (0x189)
 scancode 0x800f044c = KEY_LANGUAGE (0x170)
 scancode 0x800f044d = KEY_TITLE (0x171)
 scancode 0x800f044e = KEY_PRINT (0xd2)
 scancode 0x800f0450 = KEY_RADIO (0x181)
 scancode 0x800f045a = KEY_SUBTITLE (0x172)
 scancode 0x800f045b = KEY_RED (0x18e)
 scancode 0x800f045c = KEY_GREEN (0x18f)
 scancode 0x800f045d = KEY_YELLOW (0x190)
 scancode 0x800f045e = KEY_BLUE (0x191)
 scancode 0x800f0465 = KEY_POWER2 (0x164)
 scancode 0x800f046e = KEY_PLAYPAUSE (0xa4)
 scancode 0x800f046f = KEY_PLAYER (0x183)
 scancode 0x800f0480 = KEY_BRIGHTNESSDOWN (0xe0)
 scancode 0x800f0481 = KEY_PLAYPAUSE (0xa4)

You'll see that I left a bunch of >0xFF codes in there, mainly because my remote doesn't even have those buttons. Extraneous entries are harmless.

You'll also see that I set the remote's Enter button to RESERVED. That's because I don't ever use that remote button and don't want anything to happen when I accidentally bump it.

You'll also note that keystrokes with modifiers (Ctrl/Alt/Shift) are not possible in a keymap. This means that you cannot use Myth's default Ctrl-P for Play. For Play, this isn't a big deal because I prefer my Play button to toggle Play/Pause anyway, so just assigning KEY_P suits me fine. In other cases, you'll need to assign some other arbitrary keyboard scancode (like F13) and use Myth's Keybinding to make that button do what you want.

When you are done, save your file. To actually apply your changes, run

 ir-keytable -w mykeytable

This done, you can then use 'ir-keytable -t' and 'evtest' to verify that your buttons now generate the newly assigned keyboard scancodes. However, please note that you must restart X before Myth can see all of your changes!

If you reboot, you'll notice that your keymappings have all gone away. To make them stick after a reboot, you'll need to add ir-keytable to your distro's startup script. For example, I just added this line /etc/rc.local on Debian Jessie:

 /usr/bin/ir-keytable -w /root/mykeytable &

(Typically, full paths must be used in startup scripts)

xmodmap

Ctrl+Shift keys
In order to make those Ctrl+Shift keys work we need to remap the shifted keys to a different character. First, using xev, run through all the buttons on your remote making a note of which buttons generate which keys. Second, choose some unused shifted characters for use in the remap. For example, if not used we can make Shift+b = '<', Shift+p = '?' and Shift+f = '>' using xmodmap.

In your .xinitrc place the following:

xmodmap -e "keycode 56 = b less"
xmodmap -e "keycode 33 = p question"
xmodmap -e "keycode 41 = f greater" 

Now in your MythTV keybinds, you can use Ctrl+< for the skip back button, Ctrl+? for the play button, and Ctrl+> for the skip forward button.

Restart X and mythfrontend then verify that the keys work as expected. You can go ahead and add more lines into your .xinitrc for the remaining double keys

Unknown keys
If you have buttons on your remote that generate no valid keys but valid keycodes, you can assign some keys to those buttons and set them in your mythtv keybindings.

xmodmap -e "keycode 167 = F1"
xmodmap -e "keycode 223 = F2"
...


Other buttons
If you still have buttons on your remote that do nothing in xev and are NOT for the mouse component (if exists), then you may have a remote that created two /dev/input/ entries, one for the USB HID Keyboard and another for a USB HID Consumer device. The consumer device can likely be used with LIRC to get the remaining keys functions. Please have a look at the Snapstream firefly mini article for more information on this configuration.

XKB Remapping

This solution is pretty much the same as the one proposed for xmodmap, however it allows the remapping to occur on a per device basis. This allows you to remap your remote while leaving other input devices, such as USB keyboards, functioning normally. This example is based on the Internal IR remote in the HDPLEX system, running on an installation of ubuntu 11.04 with openbox as the window manager, but the principles and some specifics should apply in to any USB HID remote device, OS and window manager.

This work is heavily based on this page on XKB remapping, I also found this other page helpful in understanding what goes into a keyboard layout.

The first requirement is ensuring that you have a version of xbcomp > 1.2.0 with per device support. This was added in this commit, unfortunately this version is not included in ubuntu 11.04. To build a version with support use the following diff file against the apt-get source of x11-xkb-utils. You can and then you can build an updated version of the package with per device support.

Here is a complete log showing the commands in the build process.

johnf@argon:~/src/custom_xkb$ apt-get source x11-xkb-utils
Reading package lists... Done
Building dependency tree
Reading state information... Done
[...]
dpkg-source: info: extracting x11-xkb-utils in x11-xkb-utils-7.6+2
dpkg-source: info: unpacking x11-xkb-utils_7.6+2.tar.gz
johnf@argon:~/src/custom_xkb$ wget http://zioncluster.ca/mythtv/ubuntu_xkb_diff_file
[...]
2011-08-22 22:02:16 (264 MB/s) - `ubuntu_xkb_diff_file' saved [2575/2575]
johnf@argon:~/src/custom_xkb$ patch -p0 < ubuntu_xkb_diff_file
patching file x11-xkb-utils-7.6+2/debian/changelog
patching file x11-xkb-utils-7.6+2/debian/patches/12_per_device_xkbcomp
patching file x11-xkb-utils-7.6+2/debian/patches/series
patching file x11-xkb-utils-7.6+2/xkbcomp/xkbcomp.c
johnf@argon:~/src/custom_xkb$ cd x11-xkb-utils-7.6+2
johnf@argon:~/src/custom_xkb/x11-xkb-utils-7.6+2$ dpkg-buildpackage -rfakeroot -uc -b
dpkg-deb: building package `x11-xkb-utils' in `../x11-xkb-utils_7.6+2-johnf1_amd64.deb'.
dpkg-deb: building package `x11-xkb-utils-udeb' in `../x11-xkb-utils-udeb_7.6+2-johnf1_amd64.udeb'.
 dpkg-genchanges -b >../x11-xkb-utils_7.6+2-johnf1_amd64.changes
dpkg-genchanges: binary-only upload - not including any source code
 dpkg-source --after-build x11-xkb-utils-7.6+2
dpkg-buildpackage: binary only upload (no source included)
[...]
johnf@argon:~/src/custom_xkb/x11-xkb-utils-7.6+2$ cd ..
johnf@argon:~/src/custom_xkb$ sudo dpkg -i x11-xkb-utils-udeb_7.6+2-johnf1_amd64.udeb

Now that we have xkbcomp with per device support we can put it to use.

We will need to locate the unique string that will allow you to identify your remote. We will use the command xinput list to view input devices.

mythtv@argon:~$ xinput list
⎡ Virtual core pointer                    	id=2	[master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer              	id=4	[slave  pointer  (2)]
⎜   ↳ HOLTEK                                  	id=9	[slave  pointer  (2)]
⎜   ↳ Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint	id=11	[slave  pointer  (2)]
⎣ Virtual core keyboard                   	id=3	[master keyboard (2)]
    ↳ Virtual core XTEST keyboard             	id=5	[slave  keyboard (3)]
    ↳ Power Button                            	id=6	[slave  keyboard (3)]
    ↳ Power Button                            	id=7	[slave  keyboard (3)]
    ↳ HOLTEK                                  	id=8	[slave  keyboard (3)]
    ↳ Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint	id=10	[slave  keyboard (3)]

My remote is identified by the string HOLTEK.

Knowing the string for the remote, we can now create a script to remap the HOLTEK HID input specifically. This script is adapted from a very usful article on the subject of XKB remapping. I have placed this script in /home/mythtv/scripts/remap_remote, it is called from the .xinitrc file I use when starting X.

remote_id=$(
  xinput list |
  sed -n 's/.*HOLTEK.*id=\([0-9]*\).*keyboard.*/\1/p'
)
[ "$remote_id" ] || exit

mkdir -p /tmp/xkb/symbols
cat >/tmp/xkb/symbols/custom <<\EOF
xkb_symbols "remote" {
    key <I166>   {      [ Escape ]       };
    key <AD10> {        [ p,    question ]       };
    key <MENU> {	[ I ]	};
    key <FK04> { [ XF86Sleep, XF86Sleep]        };
};
EOF

setxkbmap -device $remote_id -print | sed 's/\(xkb_symbols.*\)"/\1+custom(remote)"/' | xkbcomp -I/tmp/xkb -i $remote_id -synch - $DISPLAY 2>/dev/null

This command remaps the buttons that I am concerned with. In order, they are the exit button (remapped to escape), the play/pause button (upper case P remapped to question mark), the MENU button (remapped to I) and the power button (remapped to XF86Sleep). I don't use the fast forward / rewind buttons, but they could be remapped as described in the xmodmap section.

You will need to update your remote configuration using mythweb, and tell it to use Ctrl+? as the play button. The other remappings shouldn't require mythtv configuration changes.

By default the remote generated alt+shift+F4 when you press the power button. I remapped this to XF86Sleep, however the Alt keypress remained and/or openbox didn't handle it properly. To have the box suspend with the power button I edited my openbox configuration (.config/openbox/rc.xml) and added the following in the <keyboard> section:

 
    <keybind key="A-XF86Sleep">
      <action name="Execute">
        <command>sh -c 'sudo /etc/acpi/sleep.sh'</command>
      </action>
    </keybind>

This should have your remote fully functional, while allowing other input devices to be used normally.