Twinhan USB HID Remote

From MythTV Official Wiki
Jump to: navigation, search

Remote Control

The bundled remote control has a USB reciever that acts as a HID keyboard device and send keycodes. This has been a problem for some people because there was no easy way to change the keycodes that it sends.

This can be done in kernel see Changing Remote Control Key in the Kernel at the bottom of the page.

Apparently is it possible to use LIRC to intercept the incoming keycodes and handle them as any other lirc device. Here is an extract from the MythTV Users mailing list:

 To get this (or any) USB IR HID device to work with mythtv:
   1) Compiled lirc with devinput as the driver (under Other)
   2) Faffed about trying cat /dev/input/eventX until I found one that was
      the remote (or just "cat /proc/bus/input/devices" to determine it)
   3) Used irremote --device /dev/input/eventX to configure lircd.conf for
      the keypresses on the remote. It's quite (almost) able to figure it out
      itself.
 This also required some hand editing as some of the buttons were
 multiple key presses (eg, Ctrl+Alt+F6 for power) and not all the keys
 were unique in the file. I just dumped some output from irremote to a
 file and picked out unique ones for each key.

Link to the full email: [Re: TwinHan IR remote and receiver problem - SOLVED]

Thought I'd just add a bit here, I wrote that thread about the remote but it's not very helpfull.

The problem with the TwinHan remote is that certain keys on the remote (Power, Volume) send more that one key to the keyboard buffer. This confuses the lirc.conf configurator "irremote".

Example: Power sends Ctrl+Alt+F6.

irremote seems to have a fair chance of mapping ctrl, alt OR F6 to Power in the conf file. Now, if another key on the remote (say, Pause) sends something like Alt+F4 (Pause doesn't send that btw) you run the chance of Power and Pause being mapped to the Alt key. Which means that Power does Power and Pause and vice versa.

The only solution to this that I found was saving the output from irremote to a file after pressing the offending keys. Then, pick a unique keykode from each buttons presses (in our example, F4 and F6) and put those after your entries in lirc.conf.

Here is my lirc.conf:

begin remote
  name  TwinHanRemote
  bits           32
  eps            30
  aeps          100
  one             0     0
  zero            0     0
  gap          115899
  toggle_bit      0
      begin codes
          fullscreen               0x8001002C
          Power                    0x8001001D
          1                        0x80010002
          2                        0x80010003
          3                        0x80010004
          4                        0x80010005
          5                        0x80010006
          6                        0x80010007
          7                        0x80010008
          8                        0x80010009
          9                        0x8001000A
          0                        0x8001000B
          rec                      0x80010066
          favorite                 0x8001002F
          rewind                   0x80010017
          forward                  0x80010031
          ch+                      0x80010068
          ch-                      0x8001006D
          vol-                     0x8001006C
          vol+                     0x80010067
          recall                   0x8001002E
          play                     0x8001001C
          stop                     0x8001006B
          pause                    0x80010014
          mute                     0x80010032
          cancel                   0x80010001
          capture                  0x80010019
          preview                  0x80010025
          epg                      0x80010012
          recordlist               0x80010026
          tab                      0x8001000F
          teletext                 0x8001001E
      end codes
end remote

RobM - Adding to the above. To get lirc working on ubuntu with this remote.

I got the device to always map to /dev/input/irremote. It seemed a bit tricky because udevinfo seemed to report two different IR devices, and there wasn't an easy way to tell which was "device 0" rather than "device 1". In the end I created a file /etc/udev/rules.d/10-local.rules that contained the values below, though this might be decide specific.

KERNEL=="event*",ATTRS{bInterfaceNumber}=="00",ATTRS{modalias}=="usb:v6253p0100d0100dc00dsc00dp00ic03isc01ip01",SYMLINK="input/irremote"
  • Edit your /etc/lirc/hardware.conf so that it looks something like
#Try to load appropriate kernel modules
LOAD_MODULES=true

# Run "lircd --driver=help" for a list of supported drivers.
DRIVER="dev/input"
# If DEVICE is set to /dev/lirc and devfs is in use /dev/lirc/0 will be
# automatically used instead
DEVICE="/dev/input/irremote"
MODULES=""
  • Ensure you restart lirc via "/etc/init.d/lirc restart"
  • Create a ~/.mythtv/lircrc file. A starting point is:
begin
    prog = mythtv
    button = ch+
    repeat = 3
    config = Up
end

begin
    prog = mythtv
    button = ch-
    repeat = 3
    config = Down
end

begin
    prog = mythtv
    button = vol+
    repeat = 3
    config = Right
end

begin
    prog = mythtv
    button = vol-
    repeat = 3
    config = Left
end

begin
    prog = mythtv
    button = play
    config = Return
end

begin
    prog = mythtv
    button = stop
    config = Esc
end

begin
    prog = mythtv
    button = pause
    repeat = 3
    config = P
end

The remove control has 4 buttons in the middle, with left and right being "volume up" and "volume down". I found it better to map these to just left/right keys, it makes navigating the mythtv interface feel more naturual

Changing Remote Control Key in the Kernel

The example below is for the kernel 2.6.14.3 on a slackware box. The Twinham remote appears as a USB keyboard and is handled by the driver drivers/usb/input/hid-input.c. The file includes a key mapping for USB keyboards and but only handles a single keyboard mapping. The changes required were to add a new mapping for the remote control but adding the following array.

static unsigned char hid_keyboardrc[256] = {
        0,  0,  0,  0,109, 48, 23, 32, 31, 33, 34, 35,102, 36, 30, 50,
        67,107, 24, 17, 16, 19, 31, 25, 22, 53, 17, 45, 21, 44,  2,  3,
        4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14,104, 57, 12, 13, 26,
        27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
        65, 66, 67, 68, 87, 88, 99, 70,119,110, 19,103,111, 32,108,106,
        105,105,106, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
        72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
        191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
        115,114,unk,unk,unk,121,unk, 89, 93,124, 92, 94, 95,unk,unk,unk,
        122,123, 90, 91, 85,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
        unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
        unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
        unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
        unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
        29,  0, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
        150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
        };

This is located next to the standard keyboard mapping hid_keyboard decalration. The other change is to differentiate between the Twinhan remote and a normal usb keyboard (assuming you may connect one to your PC). The code for this is:

       // check for ir remote
       if (!strncmp(hidinput->input.uniq,"11111",5)) {
          printk(KERN_DEBUG "use IRKEYS\n");
          if (!hid_keyboardrc[usage->hid & HID_USAGE]) goto ignore;
          map_key_clear(hid_keyboardrc[usage->hid & HID_USAGE]);
       } else {
          if (!hid_keyboard[usage->hid & HID_USAGE]) goto ignore;
          map_key_clear(hid_keyboard[usage->hid & HID_USAGE]);
       }

This replaces then two lines of code for handling USB keyboards. To determine the unique hidinput value of "11111" I put some simple debugging statements in the kernel but there is probably an easier way to do this.

        printk(KERN_DEBUG "hidname: %s\n",hidinput->input.name);
        printk(KERN_DEBUG "hiduniq: %s\n",hidinput->input.uniq);

With this configuration built into the kernel there is no need for lirc in myth. The remote keys appear as simple keystrokes and can be easily determined by, for example, pressing keys at the login prompt.

A similar appraoch can be found in [usbhid-twinhan.c] and kaymapping is pretty much the same to the above example. This approach directly modifies the keymap in the compiled kernel module and does not include the code as differentiate between a normal USB keyboard and the remote control.