Introduction
Recently I bought a shiny new Intel NUC8i7HNK, equipped with 16 GB of RAM and a 500 GB SSD and I installed Ubuntu 18.04 LTS. I have to say that it works smoothly and my overall experience with it is really positive this far. I don’t really miss the MAC or Windows at all.
The Intel NUC8i7HNK comes with many different expansion options and among these, there is a front consumer infrared (CIR) sensor, so I asked myself if it was possible to control the NUC with a standard TV remote control.
Turns out that it’s possible and it’s also really easy, once you get to know how everyting works under the hood. This is my attempt to clarify the steps that I made to make it all work. They may be different for your cases, but they can be taken as a good starting point.
Warning: some of these information are quite technical and require some level of expertise. Proceed at your own risk.
First steps
First thing you need to check that the IR sensor is enabled in the BIOS. After turning on the computer press F2 (or any other key that you use to enter the BIOS) and check the menu to find the status of the IR sensor. Save your changes and exit.
Most of the guides available on the Internet suggest to install LIRC (Linux Infrared remote control), which is an open source package that allows users to receive and send infrared signals with a Linux-based computer system. That was also my first attempt, but I was unable to make it work following the documentation.
“LIRC is an old style linux application which can be tweaked to do almost anything, but is tricky to setup.”
Yeah I noticed! Thank you very much.
For reference, these were my steps:
- Check if the IR sensor is enabled and active by inspecting the kernel messages using dmesg utility
$ dmesg | grep -i cir
[ 34.095165] ite_cir: Auto-detected model: ITE8708 CIR transceiver
[ 34.095167] ite_cir: Using model: ITE8708 CIR transceiver
[ 34.095167] ite_cir: TX-capable: 1
[ 34.095168] ite_cir: Sample period (ns): 8680
[ 34.095168] ite_cir: TX carrier frequency (Hz): 38000
[ 34.095169] ite_cir: TX duty cycle (%): 33
[ 34.095169] ite_cir: RX low carrier frequency (Hz): 0
[ 34.095170] ite_cir: RX high carrier frequency (Hz): 0
[ 34.172171] rc rc0: ITE8708 CIR transceiver as /devices/virtual/rc/rc0
[ 34.172206] input: ITE8708 CIR transceiver as /devices/virtual/rc/rc0/input17
[ 34.172298] rc rc0: lirc_dev: driver ite-cir registered at minor = 0, raw IR receiver, raw IR transmitter
[ 34.172890] ite_cir: driver has been successfully loaded
As you can see the sensor is working and it’s registered with the kernel.
- Check the number of supported devices. This should list a single entry
rc0
.
$ ls /sys/class/rc
rc0
- Invoke ir-keytable to see what receiver it recognizes and what protocols it supports
# Install ir-keytable if you don't have it already
$ sudo apt-get install ir-keytable
$ ir-keytable
Found /sys/class/rc/rc0/ (/dev/input/event9) with:
Name: ITE8708 CIR transceiver
Driver: ite-cir, table: rc-rc6-mce
lirc device: /dev/lirc0
Supported protocols: other lirc rc-5 rc-5-sz jvc sony nec sanyo mce_kbd rc-6 sharp xmp
Enabled protocols: lirc rc-6
Extra capabilities: <access denied>
Quoting the lirc documentation:
“If you get this kind of output you know the event device (
/dev/input/event9
) and the kernel module loaded (ite-cir
). Furthermore, since ir-keytable finds the device you know that the driver is part of the rc subsystem.”
For what concernes the protocols, we can see that the receiver supports most of them:
- RC5 and RC6 are the IR protocols defined by Philips
- Sharp use in VCRs that are produced by Sharp
- NEC, or “Japanese Format”
- Sony
- JVC
- XMP
Most remotes use the NEC protocol, including my old United LCD TV remote control.
- Install lirc using the Ubuntu-specific package
$ sudo apt-get install lirc
During the install process I should have seen a configuration window, but that was not the case. Even running the command
$ sudo dpkg-reconfigure lirc
didn’t work out. Following the documentation I tried to manually configure the device and the driver using variations of the following command, to get the kernel output available for lirc drivers
$ mode2 --driver default --device auto
But it didn’t show anything. I also tried to cat
into the device
$ cat /dev/input/event9
and pressing buttons on the remote should have printed something, but this was not the case.
Further discoveries
Later I discovered that there is an annoying bug on Ubuntu 18.04 that prevents lirc configuration during the installation process. A workaround is explained on this blog, but basically involves installing a previous version of lirc from Ubuntu 16.04 packages. It worked for me and I was able to see the configuration screen, but in the end the outcome was the same: I couldn’t see the signals from the IR sensor.
The revelation
In the end I should have read the lirc documentation more carefully, as it states clearly
Recent Linux kernels have built-in support for IR remotes. Using that, pressing an up-arrow on the remote works the same way as pressing the up-arrow on a keyboard.
So basically it should be possible to make IR work also without lirc, using kernel-specific drivers.
Second attempt
The following are the steps that lead me to successfully configure the remote controller on Ubuntu 18.04 LTS:
- Remove lirc entirely from your system
$ sudo apt-get purge lirc
# If the /etc/lirc folder exists on your system, remove that as well
$ sudo rm -rf /etc/lirc
- List supported remotes
$ ls /lib/udev/rc_keymaps/
If your remote control appears in this list, great! You can immediately use it. Otherwise you will have to test out which protocol uses the remote control, by enabling all of them and testing out.
$ sudo ir-keytable -v -t -p rc-5,rc-5-sz,jvc,sony,nec,sanyo,mce_kbd,rc-6,sharp,xmp
Found device /sys/class/rc/rc0/
Parsing uevent /sys/class/rc/rc0/lirc0/uevent
/sys/class/rc/rc0/lirc0/uevent uevent MAJOR=237
/sys/class/rc/rc0/lirc0/uevent uevent MINOR=0
/sys/class/rc/rc0/lirc0/uevent uevent DEVNAME=lirc0
Input sysfs node is /sys/class/rc/rc0/input17/
Event sysfs node is /sys/class/rc/rc0/input17/event9/
Parsing uevent /sys/class/rc/rc0/input17/event9/uevent
/sys/class/rc/rc0/input17/event9/uevent uevent MAJOR=13
/sys/class/rc/rc0/input17/event9/uevent uevent MINOR=73
/sys/class/rc/rc0/input17/event9/uevent uevent DEVNAME=input/event9
Parsing uevent /sys/class/rc/rc0/uevent
/sys/class/rc/rc0/uevent uevent NAME=rc-rc6-mce
/sys/class/rc/rc0/uevent uevent DRV_NAME=ite-cir
/sys/class/rc/rc0/uevent uevent DEV_NAME=ITE8708 CIR transceiver
input device is /dev/input/event9
/sys/class/rc/rc0/protocols protocol rc-5 (disabled)
/sys/class/rc/rc0/protocols protocol nec (disabled)
/sys/class/rc/rc0/protocols protocol rc-6 (enabled)
/sys/class/rc/rc0/protocols protocol jvc (disabled)
/sys/class/rc/rc0/protocols protocol sony (disabled)
/sys/class/rc/rc0/protocols protocol rc-5-sz (disabled)
/sys/class/rc/rc0/protocols protocol sanyo (disabled)
/sys/class/rc/rc0/protocols protocol sharp (disabled)
/sys/class/rc/rc0/protocols protocol mce_kbd (disabled)
/sys/class/rc/rc0/protocols protocol xmp (disabled)
/sys/class/rc/rc0/protocols protocol imon (disabled)
/sys/class/rc/rc0/protocols protocol lirc (enabled)
Opening /dev/input/event9
Input Protocol version: 0x00010001
Protocols changed to rc-5 rc-5-sz jvc sony nec sanyo mce_kbd rc-6 sharp xmp
Testing events. Please, press CTRL-C to abort.
By pressing the buttons on your remote you should see the received codes (scancode
) and the protocol supported (nec
)
20025.663892: lirc protocol(nec): scancode = 0x4001
20025.663912: event type EV_MSC(0x04): scancode = 0x4001
20025.663912: event type EV_SYN(0x00).
If you cannot see the name of the button (the usually are prefixed with KEY_
, like KEY_1
, KEY_VULUMEUP
, etc.) the decode table doesn’t support the remote control. In this case you can easily check if one of the available remotes has the scancode:
$ grep -iH '0x4001' /lib/udev/rc_keymaps/*
If the search doesn’t return any results you should manually create the mapping between the scan code and the key. This will be as easy as writing a txt
file with two columns. First you need to write down all the scan codes of your remote control, by pressing the buttons in order. Then you will need to map them to the available keys. The list is visible by using the following command:
$ irrecord -l
You probably don’t have this command, as it is a lirc dependency. You can still check the list online, for example at this link.
Go ahead and create a mapping by creating a new text file. Mine looks like this (make sure to include also the first line, by writing your protocol after type
)
# table united, type: nec
0x4012 KEY_POWER
0x4016 KEY_INFO
0x4010 KEY_MUTE
0x4001 KEY_1
0x4002 KEY_2
0x4003 KEY_3
0x4004 KEY_4
0x4005 KEY_5
0x4006 KEY_6
0x4007 KEY_7
0x4008 KEY_8
0x4009 KEY_9
0x4000 KEY_0
0x4014 KEY_AUX
0x4052 KEY_AUDIO
0x405b KEY_CONTROLPANEL
0x4044 KEY_EXIT
0x4019 KEY_UP
0x4047 KEY_RIGHT
0x401d KEY_DOWN
0x4046 KEY_LEFT
0x400a KEY_ENTER
0x401b KEY_CHANNELUP
0x401f KEY_CHANNELDOWN
0x405e KEY_HOME
0x4018 KEY_COMPUTER
0x401a KEY_VOLUMEUP
0x401e KEY_VOLUMEDOWN
0x4042 KEY_WAKEUP
0x400d KEY_SLEEP
0x4049 KEY_SEARCH
0x4040 KEY_REFRESH
0x4048 KEY_RED
0x404f KEY_GREEN
0x4050 KEY_YELLOW
0x404b KEY_BLUE
You can save the file wherever you want, but I suggest you to use the /etc/rc_keymaps
location. Finally instruct ir-keytable
to use the new mapping:
- Delete the existing table
$ ir-keytable -c
- load the new table from local file
$ sudo ir-keytable -c -p nec -w /etc/rc_keymaps/united
Read united table
Old keytable cleared
Wrote 36 keycode(s) to driver
Protocols changed to nec
- check if the table is really there
$ ir-keytable -r
scancode 0x4000 = KEY_0 (0x0b)
scancode 0x4001 = KEY_1 (0x02)
scancode 0x4002 = KEY_2 (0x03)
scancode 0x4003 = KEY_3 (0x04)
scancode 0x4004 = KEY_4 (0x05)
scancode 0x4005 = KEY_5 (0x06)
scancode 0x4006 = KEY_6 (0x07)
scancode 0x4007 = KEY_7 (0x08)
scancode 0x4008 = KEY_8 (0x09)
scancode 0x4009 = KEY_9 (0x0a)
[...]
Enabled protocols: lirc nec
- test the file
$ sudo ir-keytable -v -t -p nec
Found device /sys/class/rc/rc0/
Parsing uevent /sys/class/rc/rc0/lirc0/uevent
/sys/class/rc/rc0/lirc0/uevent uevent MAJOR=237
/sys/class/rc/rc0/lirc0/uevent uevent MINOR=0
/sys/class/rc/rc0/lirc0/uevent uevent DEVNAME=lirc0
Input sysfs node is /sys/class/rc/rc0/input17/
Event sysfs node is /sys/class/rc/rc0/input17/event9/
Parsing uevent /sys/class/rc/rc0/input17/event9/uevent
/sys/class/rc/rc0/input17/event9/uevent uevent MAJOR=13
/sys/class/rc/rc0/input17/event9/uevent uevent MINOR=73
/sys/class/rc/rc0/input17/event9/uevent uevent DEVNAME=input/event9
Parsing uevent /sys/class/rc/rc0/uevent
/sys/class/rc/rc0/uevent uevent NAME=rc-rc6-mce
/sys/class/rc/rc0/uevent uevent DRV_NAME=ite-cir
/sys/class/rc/rc0/uevent uevent DEV_NAME=ITE8708 CIR transceiver
input device is /dev/input/event9
/sys/class/rc/rc0/protocols protocol rc-5 (disabled)
/sys/class/rc/rc0/protocols protocol nec (enabled)
/sys/class/rc/rc0/protocols protocol rc-6 (disabled)
/sys/class/rc/rc0/protocols protocol jvc (disabled)
/sys/class/rc/rc0/protocols protocol sony (disabled)
/sys/class/rc/rc0/protocols protocol rc-5-sz (disabled)
/sys/class/rc/rc0/protocols protocol sanyo (disabled)
/sys/class/rc/rc0/protocols protocol sharp (disabled)
/sys/class/rc/rc0/protocols protocol mce_kbd (disabled)
/sys/class/rc/rc0/protocols protocol xmp (disabled)
/sys/class/rc/rc0/protocols protocol imon (disabled)
/sys/class/rc/rc0/protocols protocol lirc (enabled)
Opening /dev/input/event9
Input Protocol version: 0x00010001
Protocols changed to nec
Testing events. Please, press CTRL-C to abort.
21169.480721: lirc protocol(nec): scancode = 0x4012
21169.480738: event type EV_MSC(0x04): scancode = 0x4012
21169.480738: event type EV_KEY(0x01) key_down: KEY_POWER(0x0074)
21169.480738: event type EV_SYN(0x00).
21169.533056: lirc protocol(nec): scancode = 0x4012 repeat
21169.533078: event type EV_MSC(0x04): scancode = 0x4012
21169.533078: event type EV_SYN(0x00).
21169.660143: event type EV_KEY(0x01) key_up: KEY_POWER(0x0074)
21169.660143: event type EV_SYN(0x00).
21171.387732: lirc protocol(nec): scancode = 0x4001
21171.387754: event type EV_MSC(0x04): scancode = 0x4001
21171.387754: event type EV_KEY(0x01) key_down: KEY_1(0x0002)
21171.387754: event type EV_SYN(0x00).
That’s it! Now you should be able to control your desktop environment with the remote control.
If after rebooting the computer the keymapping is back to the original one, you can add a script to /etc/rc.local
file to set the mapping when the OS starts:
#!/bin/sh -e
ir-keytable -c -p nec -w /etc/rc_keymaps/united
exit 0
Save the file and make it executable with this command:
$ sudo chmod +x /etc/rc.local