Tuesday, May 28, 2013

Using a MCE remote control with mythtv / xbmc


No lircd please.

After five years of mythtv 0.19 / xbmc (no udates of any kind during that time) and numerous restarts of lirc I got myself a new remote with an usb reciever, "MCE remote". A remote that shows up directly in the /dev/input directory of ubuntu 12.04. In addition to some standard buttons it also got a built in mouse. If one presses and holds down one of the numeric buttons it first emit a digit and then, after a while, emit a backspace and a character. E.g: Holding down "2" gives "2", delay, "<bs>A", delay, <bs>B, etc.

All very handy, but in the end I will probably use the reciever with my learning remote control wich also controls the amplifier and other stuff. 



It was bought under the brand name "Fractal design", but as ubuntu concerns this is the important stuff:
(since ubuntu 12.04 lists this device in /dev/input/by-id it is easy to locate, otherwise one could plug/unplug and look in the /dev/input/ directory)

sudo udevadm info -a --name=/dev/input/by-id/usb-Cypress_Cypress_USB_Keyboard-event-mouse 

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/pci0000:00/0000:00:02.0/usb3/3-1/3-1:1.0/input/input2/event2':
    KERNEL=="event2"
    SUBSYSTEM=="input"
    DRIVER==""

  looking at parent device '/devices/pci0000:00/0000:00:02.0/usb3/3-1/3-1:1.0/input/input2':
    KERNELS=="input2"
    SUBSYSTEMS=="input"
    DRIVERS==""
    ATTRS{name}=="Cypress Cypress USB Keyboard"
    ATTRS{phys}=="usb-0000:00:02.0-1/input0"
    ATTRS{uniq}==""
    ATTRS{properties}=="0"

  looking at parent device '/devices/pci0000:00/0000:00:02.0/usb3/3-1/3-1:1.0':
    KERNELS=="3-1:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="usbhid"
    ATTRS{bInterfaceClass}=="03"
    ATTRS{bInterfaceSubClass}=="01"
    ATTRS{bInterfaceProtocol}=="01"
    ATTRS{bNumEndpoints}=="01"
    ATTRS{supports_autosuspend}=="1"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bInterfaceNumber}=="00"

  looking at parent device '/devices/pci0000:00/0000:00:02.0/usb3/3-1':
    KERNELS=="3-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{devpath}=="1"
    ATTRS{idVendor}=="04b4"
    ATTRS{speed}=="1.5"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{busnum}=="3"
    ATTRS{devnum}=="2"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}==" 98mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="a0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="0"
    ATTRS{bcdDevice}=="0100"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{version}==" 1.10"
    ATTRS{urbnum}=="12"
    ATTRS{manufacturer}=="Cypress"
    ATTRS{removable}=="unknown"
    ATTRS{idProduct}=="0100"
    ATTRS{bDeviceClass}=="00"
    ATTRS{product}=="Cypress USB Keyboard"

In order to remap the remote keys we have to write a keymaps file and run this when the usb reciever are plugged into the system. A great "howto" on this is in writing udev rules. As shown by the '/dev/by-id' contents, the remote control is two units; the mouse part and the rest. The difference between these are the 'KERNEL==' attribute. Since one can use info from the device itself and one of the parent devices I used this rule:

SUBSYSTEM=="input", KERNEL=="event*", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="0100",  RUN+="/bin/sh -c 'echo $name >> /tmp/test.udev"
SUBSYSTEM=="input", KERNEL=="event*", ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="0100",  RUN+="keymap $name cypressusb"

This is the method I use to convince myself that the udev rules are hit. Just check the '/tmp/test.udev' for which devices that match the rule. '/lib/udev/keymap device keymapfile' (where 'keymapfile' is located in /lib/udev/keymaps/ updates the keymap of the device). To simulate adding devices use

sudo udevadm trigger


'ir-keytable' may be used to check the keycodes emitted from the remote:

#From ir-keytable -t -d /dev/input/by-id/usb-Cypress_Cypress_USB_Keyboard-event-mouse

#Pressing buttons from top left across to the right and down

700e0 KEY_LEFTCTRL (0x001d) 
70015 KEY_R (0x0013)

c00b7 KEY_STOPCD (0x00a6)

700e2 KEY_LEFTALT (0x0038)
7003d KEY_F4 (0x003e)
**
700e0 KEY_LEFTCTRL (0x001d)
70005 KEY_LEFT (0x0069)

700e0 KEY_LEFTCTRL (0x001d)
700e1 KEY_LEFTSHIFT (0x002a)
70013 KEY_P (0x0019)

700e0 KEY_LEFTCTRL (0x001d)
700e1 KEY_LEFTSHIFT (0x002a)
70005 KEY_LEFT (0x0069)
**
700e0 KEY_LEFTCTRL (0x001d)
700e1 KEY_LEFTSHIFT (0x002a)
70005 KEY_LEFT (0x0069)

700e0 KEY_LEFTCTRL (0x001d)
70013 KEY_P (0x0019)

700e0 KEY_LEFTCTRL (0x001d)
700e1 KEY_LEFTSHIFT (0x002a)
70009 KEY_RIGHT (0x006a)
**

700e0 KEY_LEFTCTRL (0x001d)
700e1 KEY_LEFTSHIFT (0x002a)
70010 KEY_M (0x0032)

700e2 KEY_LEFTALT (0x0038)
700e3 KEY_LEFTMETA (0x007d)
70028 KEY_ENTER (0x001c)

700e0 KEY_LEFTCTRL (0x001d)
7000a KEY_G (0x0022)
**
70028 KEY_ENTER (0x001c)

7002a KEY_BACKSPACE (0x000e)

70050   KEY_LEFT
70052   KEY_UP
7004f   KEY_RIGHT
70051   KEY_DOWN

then the mouse buttons 

left mouse btn  90001  BTN_MOUSE (0x0110)
right mouse btn 90002  BTN_RIGHT (0x0111)

and joystick
and continuing...

RecTV
700e0   KEY_LEFTCTRL
70012   KEY_O

Vol+
70043   KEY_F10
Vol-
70042   KEY_F9

Ch/Pg+
7004b   KEY_PAGEUP
Ch/Pg-
7004e   KEY_PAGEDOWN

LiveTV
700e0   KEY_LEFTCTRL
70017   KEY_T
**

S1   c0223  KEY_HOMEPAGE
S2   c022a  KEY_BOOKMARKS
mute 70041  KEY_F8
S3   c0224  KEY_BACK
S4   c0225  KEY_FORWARD

red     700e0  KEY_LEFTCTRL
        700e1  KEY_LEFTSHIFT
        70017  KEY_T
green   700e0  KEY_LEFTCTRL
        70008  KEY_E
yellow  700e0  KEY_LEFTCTRL
        7000c  KEY_I
blue    700e0  KEY_LEFTCTRL
        70010  KEY_M

the numeric keys, and finally...;
clear   7002a  KEY_BACKSPACE (0x000e)
enter  70028 KEY_ENTER (0x001c)

The remote dublicates the keycodes sent from the "back" and "clear" buttons and also the "ok" and "enter" buttons.

Mythtv uses <ESC> as back key, but I don't want to reassign the 'back' key on the remote from backspace, it could be needed. Therefore the first iteration of the keymap would be to reassign left and right mouse button to OK and ESC.

/lib/udev/keymaps/cypressusb 
0x90001  OK     # left mouse btn -> OK
0x90002  ESC    # right mouse btn -> ESC