Fixing multiple button presses being detected on IR remote on Linux when using evdev

Or: make your MCE remote work properly again on Kodi after upgrading to Ubuntu 18.04. No LIRC required.

Ever since I upgraded my Kodi box to Ubuntu 18.04, I’ve been having issues with my beloved remote control, the MCE remote from Microsoft. (I’ve had it for years, I have perfect muscle memory for all the buttons. All the most important buttons are within thumb reach.)

My remote, an MCE type 2

First, it wouldn’t work at all, and after some frustrating hours of problem shooting I got it sort-of, kind-of working, but it started repeating button presses, ignoring some buttons and generally being pretty useless. I eventually gave up on using the original IR receiver, and found that if I used a third party IR receiver acting like a HID device, I could tweak the keyboard bindings in Kodi to make it more or less feature complete.

That only left me with one annoyance: some buttons would register double presses. Worse, the all important «OK» button was one of them. Whenever I was navigating through my media, the double click would randomly start a movie I didn’t mean to, go to a season I didn’t intend etc. Changing options was also a big hassle, whenever I tried to toggle subtitles, they would generally un-toggle immediately.

I’ve been living with this for more than a year now, when I finally snapped and started looking into it again. I found I’m not the only one with this issue, as this blog post and this forum thread can attest. To summarize, my setup is currently this:

  • I have an MCE remote, as pictured
  • I’m not using the USB IR-receiver that came with the remote, I’m using a third party receiver that is being recognized by evdev as a HOLTEK sensor, and by lsusb as a Belkin device (1241:e000)
  • I’m not using LIRC at all

So, let’s get to the solution.

The Solution

The solution is deceptively simple, even trivial, once you know how.

First of all, you a couple of tools:

$ sudo apt-get install evtest ir-keytable

Using evtest, try to figure out which input device is the one that corresponds to your IR receiver. Some trial and error may be needed, but some devices are obviously not the correct one, such as «HDA Intel PCH Line Out», «Logitech BT Mini-Receiver» etc. Pick a device that looks promising, then start pressing some buttons on the remote. You know you have the right device when you see lots of lines getting printed.

Here’s a transcript of a successful run (with a bunch of irrelevant lines snipped out):

Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x1241 product 0xe000 version 0x110
Input device name: "HOLTEK"
Supported events:
  Event type 0 (EV_SYN)
*SNIP*
Key repeat handling:
  Repeat type 20 (EV_REP)
    Repeat code 0 (REP_DELAY)
      Value    250
    Repeat code 1 (REP_PERIOD)
      Value     33
Properties:
Testing … (interrupt to exit)
Event: time 1564611021.168933, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70028
Event: time 1564611021.168933, type 1 (EV_KEY), code 28 (KEY_ENTER), value 1
Event: time 1564611021.168933, -------------- SYN_REPORT ------------
Event: time 1564611021.428026, type 1 (EV_KEY), code 28 (KEY_ENTER), value 2
Event: time 1564611021.428026, -------------- SYN_REPORT ------------
Event: time 1564611021.468030, type 1 (EV_KEY), code 28 (KEY_ENTER), value 2
Event: time 1564611021.468030, -------------- SYN_REPORT ------------
Event: time 1564611021.508025, type 1 (EV_KEY), code 28 (KEY_ENTER), value 2
Event: time 1564611021.508025, -------------- SYN_REPORT ------------
Event: time 1564611021.548028, type 1 (EV_KEY), code 28 (KEY_ENTER), value 2
Event: time 1564611021.548028, -------------- SYN_REPORT ------------
Event: time 1564611021.588024, type 1 (EV_KEY), code 28 (KEY_ENTER), value 2
Event: time 1564611021.588024, -------------- SYN_REPORT ------------
Event: time 1564611021.608926, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70028
Event: time 1564611021.608926, type 1 (EV_KEY), code 28 (KEY_ENTER), value 0
Event: time 1564611021.608926, -------------- SYN_REPORT ------------

A few things to note: REP_DELAY is set to 250, REP_PERIOD is set to 33. Also, we get multiple lines of the event type 1 (EV_KEY), code 28 (KEY_ENTER), value 2, this is all from the «OK» button being pressed briefly once. We can see that they all got fired within roughly 0.04 seconds of each other, or 40 milliseconds. That’s awfully close to the value of 33 for the period. The first event, with value 1, is fired 259 ms before the events with value 2. Again, that corresponds to the delay value of 250. This all happened within roughly 440 ms, less than half a second.

So how can we tweak the values for REP_DELAY and REP_PERIOD? I found the answer over on the MythTV wiki. The wiki also explains why we’re having issues: IR baud rates are slower than a typical keyboard, wired or wireless. It also suggests the values 500 and 250, so let’s apply that.

In my example, I found the receiver on device 3, so the command ends up looking like this:

$ sudo ir-keytable -D 500 -P 250 -d /dev/input/event3

Now, when I re-run the evtest command on my device, I get the following result when pressing the OK button:

Event: time 1564612895.905914, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70028
Event: time 1564612895.905914, type 1 (EV_KEY), code 28 (KEY_ENTER), value 1
Event: time 1564612895.905914, -------------- SYN_REPORT ------------
Event: time 1564612896.409903, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70028
Event: time 1564612896.409903, type 1 (EV_KEY), code 28 (KEY_ENTER), value 0
Event: time 1564612896.409903, -------------- SYN_REPORT ------------

That’s more like it! We get one instance of value 1 (key down), no instances of value 2 (key still down, repeating the key), and one instance of value 0 (key up). This time, the key press even lasted slightly more than 500 ms without issue. Success!

Side note: this is kinda, sorta, maybe a form of key debouncing. Just throwing that into this blog post for the search engines out there. I know I tried to use that as a keyword while researching this issue.

Making it stick

The tweaked values will get lost upon the next reboot, so how can we make the fix permanent? In the old days, you would put it in /etc/rc.local, but this is 2019, let’s use systemd! This is what the oneshot service was made for.

I created the file /etc/systemd/system/ir-keytable.service with the following contents (remember to tweak the command on the ExecStart line to suit your setup):

[Unit]
Description=Adjust delay and period for IR remote

[Service]
Type=oneshot
ExecStart=/usr/bin/ir-keytable -D 500 -P 250 -d /dev/input/event3
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Then reload systemd and enable the service:

$ sudo systemctl daemon-reload
$ sudo systemctl enable ir-keytable.service

Phew. I hope all that can come in handy for someone else out there.

Én kommentar til «Fixing multiple button presses being detected on IR remote on Linux when using evdev»

Legg igjen en kommentar til Pierre Avbryt svar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *

Dette nettstedet bruker Akismet for å redusere spam. Lær om hvordan dine kommentar-data prosesseres.