md
ir-keytable on the Orange Pi Zero
Last update: February 11, 2019
First version: February 9, 2019
<-Using Bare Metal IR on the Orange Pi Zero --
<-LIRC on the Orange Pi Zero

While LIRC could be useful for some, many will just want to use an IR remote control with software designed for that purpose such as Kodi. In that case, LIRC will not be needed if the remote control uses one of the following IR protocols: rc-5, rc-5-sz, jvc, sony, nec, sanyo, mce_kbd, rc-6, sharp, and xmp. The ir-keytable utility contains over 130 remote control definitions and can be used to craft one if the IR remote is not among that list.

Table of Contents

  1. Media Centre Remote
  2. The ir-keytable utility.
  3. Managing Key Tables
  4. The Broken udev Rule
  5. The ir-keytable Configuration File rc_maps.cfg
  6. Automatic Configuration
  7. Conclusion

Media Centre Remote toc

HP RC6 Remote In a pile of old IR remote controls I found a Window Media Centre remote from HP along with a USB IR receiver. Of course there is no need for the latter given that the Orange Pi Zero has an IR receiver. Inside the battery compartment of the remote control, it says that it uses IR protocol RC6 which I believe is the case for all remotes used with WMC.

Time to test that it works after many years of disuse. First I checked that the input event is still event0. Then I set the protocol to RC-6, and checked for events as I pressed a key on the remote.

zero@opi:~$ cat /proc/bus/input/devices I: Bus=0019 Vendor=0001 Product=0001 Version=0100 N: Name="sunxi-ir" P: Phys=sunxi-ir/input0 S: Sysfs=/devices/platform/soc/1f02000.ir/rc/rc0/input0 U: Uniq= H: Handlers=kbd event0 B: PROP=0 B: EV=100013 B: KEY=1000000 0 0 0 0 B: MSC=10 zero@opi:~$ irp rc-6 IR protocols: rc-5 nec [rc-6] jvc sony rc-5-sz sanyo sharp mce_kbd xmp imon [lirc] zero@opi:~$ evtest /dev/input/event0 Input driver version is 1.0.1 Input device ID: bus 0x19 vendor 0x1 product 0x1 version 0x100 Input device name: "sunxi-ir" Supported events: Event type 0 (EV_SYN) Event type 1 (EV_KEY) Event code 152 (KEY_SCREENLOCK) Event type 4 (EV_MSC) Event code 4 (MSC_SCAN) Key repeat handling: Repeat type 20 (EV_REP) Repeat code 0 (REP_DELAY) Value 500 Repeat code 1 (REP_PERIOD) Value 125 Properties: Testing ... (interrupt to exit) Event: time 1549737697.890094, type 4 (EV_MSC), code 4 (MSC_SCAN), value 800f0401 Event: time 1549737697.890094, -------------- SYN_REPORT ------------ Event: time 1549737697.996195, type 4 (EV_MSC), code 4 (MSC_SCAN), value 800f0401 Event: time 1549737697.996195, -------------- SYN_REPORT ------------

So the scan code of button "1" is 0x800f0401. There are numerous buttons on that remote, I would not relish mapping all of them to key codes. Enter ir-keytable, "a swiss-knife tool to handle Remote Controllers" as its man page says.

Installation and Use of ir-keytable toc

The package is not present in the Armbian image but is easily added in the usual fashion since it is in the repository.

zero@opi:~$ sudo apt install -y ir-keytable ... Setting up ir-keytable (1.12.3-1) ... Processing triggers for man-db (2.7.6.1-2) ...

In addition to the program itself, numerous files were installed including remote definitions in /lib/udev/rc_keymaps, associated kernel objects in /lib/modules/4.19.17-sunxi/kernel/drivers/media/rc/keymaps/, a udevrule, a configuration file and an empty directory.

zero@opi:~$ which ir-keytable /usr/bin/ir-keytable zero@opi:~$ ls /lib/udev/rc_keymaps a800 dibusb kworld_pc150u real_audio_220_32_keys adstech_dvb_t_pci digitalnow_tinytwin kworld_plus_tv_analog reddo ... dib0700_nec kaiomy pv951 dib0700_rc5 kworld_315u rc6_mce zero@opi:~$ ls /lib/modules/4.19.17-sunxi/kernel/drivers/media/rc/keymaps/ rc-adstech-dvb-t-pci.ko rc-encore-enltv.ko rc-pinnacle-pctv-hd.ko rc-alink-dtu-m.ko rc-evga-indtube.ko rc-pixelview-002t.ko ... rc-avermedia-a16d.ko rc-gotview7135.ko rc-rc6-mce.ko ... zero@opi:~$ ls /lib/udev/rules.d/60-ir-keytable.rules /lib/udev/rules.d/60-ir-keytable.rules zero@opi:~$ ls -l /etc/rc_* -rw-r--r-- 1 root root 6213 Feb 17 2017 /etc/rc_maps.cfg /etc/rc_keymaps: total 0

That is a bit overwhelming but it is manageable with the help of many documents found on the Web and the utility's man page. As an initiation, let us look at interactive use of the utility.

Running the program without any command line parameters displays information about the current drivers, devices, protocols and so on.

zero@opi:~$ ir-keytable Found /sys/class/rc/rc0/ (/dev/input/event0) with: Driver sunxi-ir, table rc-empty Supported protocols: other lirc rc-5 rc-5-sz jvc sony nec sanyo mce_kbd rc-6 sharp xmp Enabled protocols: lirc rc-6 Name: sunxi-ir bus: 25, vendor/product: 0001:0001, version: 0x0100 Repeat delay = 500 ms, repeat period = 125 ms

IR protocols can be set.

zero@opi:~$ sudo ir-keytable -p nec,rc-5 Protocols changed to rc-5 nec zero@opi:~$ sudo ir-keytable -p all Protocols changed to other lirc rc-5 rc-5-sz jvc sony nec sanyo mce_kbd rc-6 sharp xmp

Note the need for root privileges. The -p (long form: --protocol) does not have the flexibility of my irp bash script but it does have the ability to set all protocols at once which is good to test the compatibility of an unknown remote control.

While one would not want to do this for all the keys on a MCE remote, it is possible to set the key codes for scan codes with ir-keytable and then to display received scan codes and corresponding key codes if available.

zero@opi:~$ sudo ir-keytable -p rc-6 Protocols changed to rc-6 zero@opi:~$ ir-keytable -k 0x800f0401=KEY_1,0x800f0402=KEY_2 Wrote 2 keycode(s) to driver zero@opi:~$ ir-keytable -r scancode 0x800f0401 = KEY_1 (0x02) scancode 0x800f0402 = KEY_2 (0x03) Enabled protocols: lirc rc-6 zero@opi:~$ ir-keytable -t Testing events. Please, press CTRL-C to abort. 1549742350.561983: event type EV_MSC(0x04): scancode = 0x800f0401 1549742350.561983: event type EV_KEY(0x01) key_down: KEY_1(0x0002) 1549742350.561983: event type EV_SYN(0x00). 1549742350.668084: event type EV_MSC(0x04): scancode = 0x800f0401 1549742350.668084: event type EV_SYN(0x00). 1549742350.905202: event type EV_KEY(0x01) key_up: KEY_1(0x0002) 1549742350.905202: event type EV_SYN(0x00). 1549742351.312273: event type EV_MSC(0x04): scancode = 0x800f0402 1549742351.312273: event type EV_KEY(0x01) key_down: KEY_2(0x0003) 1549742351.312273: event type EV_SYN(0x00). 1549742351.418396: event type EV_MSC(0x04): scancode = 0x800f0402 1549742351.418396: event type EV_SYN(0x00). 1549742351.657185: event type EV_KEY(0x01) key_up: KEY_2(0x0003) 1549742351.657185: event type EV_SYN(0x00). 1549742352.129474: event type EV_MSC(0x04): scancode = 0x800f0403 1549742352.129474: event type EV_SYN(0x00). 1549742352.235631: event type EV_MSC(0x04): scancode = 0x800f0403 1549742352.235631: event type EV_SYN(0x00).

The "1", "2" and "3" buttons were pressed in succession. The -k option was used to set key codes (strings such as "KEY_1"), for the first two buttons and these are echoed by the utility. Only the scan code is shown for the third button. Note also how key_down and key_up events of type EV_KEY are reported with the translated key codes.

In this mode, ir-keytable can be seen as the replacement of the LIRC irw program.

The HP remote control sends a scan code repeatedly if a button is held down for any length of time. The "3" button was held down for a relatively long period and as can be seen the scan code were repeated at a very steady frequency of 10 per second.

zero@opi:~$ ir-keytable -t Testing events. Please, press CTRL-C to abort. 1549900869.364917: event type EV_MSC(0x04): scancode = 0x800f0403 1549900869.364917: event type EV_SYN(0x00). 1549900869.471014: event type EV_MSC(0x04): scancode = 0x800f0403 delta: 0.106096982955933 1549900869.471014: event type EV_SYN(0x00). 1549900869.577187: event type EV_MSC(0x04): scancode = 0x800f0403 delta: 0.106173038482666 1549900869.577187: event type EV_SYN(0x00). 1549900869.683334: event type EV_MSC(0x04): scancode = 0x800f0403 delta: 0.106147050857544 1549900869.683334: event type EV_SYN(0x00). 1549900869.789506: event type EV_MSC(0x04): scancode = 0x800f0403 delta: 0.106171846389771 1549900869.789506: event type EV_SYN(0x00). 1549900869.895648: event type EV_MSC(0x04): scancode = 0x800f0403 delta: 0.106142044067383 1549900869.895648: event type EV_SYN(0x00). 1549900870.001833: event type EV_MSC(0x04): scancode = 0x800f0403 delta: 0.106184959411621 1549900870.001833: event type EV_SYN(0x00). 1549900870.107974: event type EV_MSC(0x04): scancode = 0x800f0403 delta: 0.106141090393066 1549900870.107974: event type EV_SYN(0x00). 1549900870.214139: event type EV_MSC(0x04): scancode = 0x800f0403 delta: 0.106164932250977 ...

Independently of the remote control repeat capabilities, the kernel repeats key codes if they are defined with ir-keytable. It does not repeat scan codes. The default values are a 1/2 second (500 ms) delay and a 1/8 second (125 ms) repeat period. These are typical keyboard delays. The following table shows the time intervals between scan codes and key codes when the "1" button was held down for 3 seconds. The synchronization events EV_SYN were removed to obtain a clearer picture. The first column is the ir-keytable time stamp. The fifth column EV_* delta is the time interval in milliseconds between successive events whether they are scan codes from the remote control or key codes. The last column, EV_KEY delta contains the time intervals between EV_KEY codes. Since the repeat period of the key codes is 125 ms and the repeat period of the remote control is 100 ms, most times there is only one scan code between two key codes, but occasionnaly there are two. The exception is at the start because of the 500 ms delay before the first time the key code is repeated.

Timestamp Event Type Code Delta EV_* Delta EV_KEY
1549903838.71569 EV_MSC(0x04) scancode 0x800f0401

1549903838.71569 EV_KEY(0x01) key_down KEY_1(0x0002)

1549903838.82179 EV_MSC(0x04) scancode 0x800f0401 106
1549903838.92789 EV_MSC(0x04) scancode 0x800f0401 106
1549903839.03404 EV_MSC(0x04) scancode 0x800f0401 106
1549903839.14021 EV_MSC(0x04) scancode 0x800f0401 106
1549903839.24636 EV_MSC(0x04) scancode 0x800f0401 106
1549903839.24705 EV_KEY(0x01) key_down KEY_1(0x0002) 1 531
1549903839.35254 EV_MSC(0x04) scancode 0x800f0401 105
1549903839.37905 EV_KEY(0x01) key_down KEY_1(0x0002) 27 132
1549903839.45869 EV_MSC(0x04) scancode 0x800f0401 80
1549903839.51104 EV_KEY(0x01) key_down KEY_1(0x0002) 52 132
1549903839.56487 EV_MSC(0x04) scancode 0x800f0401 54
1549903839.64305 EV_KEY(0x01) key_down KEY_1(0x0002) 78 132
1549903839.67109 EV_MSC(0x04) scancode 0x800f0401 28
1549903839.77505 EV_KEY(0x01) key_down KEY_1(0x0002) 104 132
1549903839.77717 EV_MSC(0x04) scancode 0x800f0401 2
1549903839.88333 EV_MSC(0x04) scancode 0x800f0401 106
1549903839.90704 EV_KEY(0x01) key_down KEY_1(0x0002) 24 130
1549903839.98951 EV_MSC(0x04) scancode 0x800f0401 82
1549903840.03905 EV_KEY(0x01) key_down KEY_1(0x0002) 50 132
1549903840.09567 EV_MSC(0x04) scancode 0x800f0401 57
1549903840.17105 EV_KEY(0x01) key_down KEY_1(0x0002) 75 132
1549903840.20184 EV_MSC(0x04) scancode 0x800f0401 31
1549903840.30305 EV_KEY(0x01) key_down KEY_1(0x0002) 101 132
1549903840.30798 EV_MSC(0x04) scancode 0x800f0401 5
1549903840.41415 EV_MSC(0x04) scancode 0x800f0401 106
1549903840.43504 EV_KEY(0x01) key_down KEY_1(0x0002) 21 127
1549903840.52032 EV_MSC(0x04) scancode 0x800f0401 85
1549903840.56705 EV_KEY(0x01) key_down KEY_1(0x0002) 47 132
1549903840.62648 EV_MSC(0x04) scancode 0x800f0401 59
1549903840.69904 EV_KEY(0x01) key_down KEY_1(0x0002) 73 132
1549903840.73265 EV_MSC(0x04) scancode 0x800f0401 34
1549903840.83105 EV_KEY(0x01) key_down KEY_1(0x0002) 98 132
1549903840.83879 EV_MSC(0x04) scancode 0x800f0401 8
1549903840.94495 EV_MSC(0x04) scancode 0x800f0401 106
1549903840.96304 EV_KEY(0x01) key_down KEY_1(0x0002) 18 124
1549903841.05119 EV_MSC(0x04) scancode 0x800f0401 88
1549903841.09505 EV_KEY(0x01) key_down KEY_1(0x0002) 44 132
1549903841.15729 EV_MSC(0x04) scancode 0x800f0401 62
1549903841.22704 EV_KEY(0x01) key_down KEY_1(0x0002) 70 132
1549903841.26346 EV_MSC(0x04) scancode 0x800f0401 36
1549903841.35905 EV_KEY(0x01) key_down KEY_1(0x0002) 96 132
1549903841.3696 EV_MSC(0x04) scancode 0x800f0401 11
1549903841.47578 EV_MSC(0x04) scancode 0x800f0401 106
1549903841.49105 EV_KEY(0x01) key_down KEY_1(0x0002) 15 121
1549903841.58194 EV_MSC(0x04) scancode 0x800f0401 91
1549903841.62306 EV_KEY(0x01) key_down KEY_1(0x0002) 41 132
1549903841.75504 EV_KEY(0x01) key_down KEY_1(0x0002) 132 173
1549903841.81905 EV_KEY(0x01) key_up KEY_1(0x0002) 64

The key code delay and repeat period can be modified with the -D and -P options.

zero@opi:~$ ir-keytable -D 100 -P 25 Repeat delay = 100 ms, repeat period = 125 ms Changed Repeat delay to 100 ms and repeat period to 25 ms

Finally, evdev reports both scan codes and key codes when the latter are defined. In the session shown below, first the "3" button is pressed. Recall its key code has not been defined. Then the "2" and "1" button are pressed, and their key code is reported in addition to the scan code.

zero@opi:~$ evtest /dev/input/event0 ... Testing ... (interrupt to exit) Event: time 1549910796.882484, type 4 (EV_MSC), code 4 (MSC_SCAN), value 800f0403 Event: time 1549910796.882484, -------------- SYN_REPORT ------------ Event: time 1549910796.988600, type 4 (EV_MSC), code 4 (MSC_SCAN), value 800f0403 Event: time 1549910796.988600, -------------- SYN_REPORT ------------ Event: time 1549910798.566182, type 4 (EV_MSC), code 4 (MSC_SCAN), value 800f0402 Event: time 1549910798.566182, type 1 (EV_KEY), code 3 (KEY_2), value 1 Event: time 1549910798.566182, -------------- SYN_REPORT ------------ Event: time 1549910798.672285, type 4 (EV_MSC), code 4 (MSC_SCAN), value 800f0402 Event: time 1549910798.672285, -------------- SYN_REPORT ------------ Event: time 1549910798.911059, type 1 (EV_KEY), code 3 (KEY_2), value 0 Event: time 1549910798.911059, -------------- SYN_REPORT ------------ Event: time 1549910803.375355, type 4 (EV_MSC), code 4 (MSC_SCAN), value 800f0401 Event: time 1549910803.375355, type 1 (EV_KEY), code 2 (KEY_1), value 1 Event: time 1549910803.375355, -------------- SYN_REPORT ------------ Event: time 1549910803.481489, type 4 (EV_MSC), code 4 (MSC_SCAN), value 800f0401 Event: time 1549910803.481489, -------------- SYN_REPORT ------------ Event: time 1549910803.719065, type 1 (EV_KEY), code 2 (KEY_1), value 0 Event: time 1549910803.719065, -------------- SYN_REPORT ------------ Event: time 1549910858.372743, type 4 (EV_MSC), code 4 (MSC_SCAN), value 800f0401 Event: time 1549910858.372743, type 1 (EV_KEY), code 2 (KEY_1), value 1 ...

Managing Key Tables toc

Perhaps the main function of ir-keytable is its ability to manage translations from scan code to key codes stored in files.

As stated above, quite a few IR remote definitions were included in the ir-keytable package. They are found in the /lib/udev/rc_keymaps directory. Among them there is one for RC6 remotes: rc6-mce. The command to load that scan to key code translation file is simple.

michel@hp:~$ sudo ir-keytable -w /lib/udev/rc_keymaps/rc6_mce Read rc6_mce table Wrote 63 keycode(s) to driver Protocols changed to rc-6

The key codes contained in the file were added to those already used by the kernel. To see the current entries use the -r (long form: --read) option.

zero@opi:~$ ir-keytable -r Enabled protocols: lirc rc-6 scancode 0x002a = KEY_COFFEE (0x98) scancode 0x800f0400 = KEY_NUMERIC_0 (0x200) scancode 0x800f0401 = KEY_NUMERIC_1 (0x201) scancode 0x800f0402 = KEY_NUMERIC_2 (0x202) scancode 0x800f0403 = KEY_NUMERIC_3 (0x203) ...

The KEY_COFFEE entry is not part of the rc6_mce definition. There is a clear option (-c or --clear) which can be used alone for the obvious purpose of removing all current scan to key code entries from the kernel module. In combination with the write option (-w or --write) we have an replace operation.

zero@opi:~$ sudo ir-keytable -c -w /lib/udev/rc_keymaps/rc6_mce Read rc6_mce table Old keytable cleared Wrote 63 keycode(s) to driver Protocols changed to rc-6 zero@opi:~$ ir-keytable -r Enabled protocols: lirc rc-6 scancode 0x800f0400 = KEY_NUMERIC_0 (0x200) scancode 0x800f0401 = KEY_NUMERIC_1 (0x201) scancode 0x800f0402 = KEY_NUMERIC_2 (0x202) scancode 0x800f0403 = KEY_NUMERIC_3 (0x203) scancode 0x800f0404 = KEY_NUMERIC_4 (0x204) ...

The utility knows which IR protocol to set because it is specified in the first line of remote definition file.

zero@opi:~$ head -n 5 /lib/udev/rc_keymaps/rc6_mce # table rc6_mce, type: RC6 0x800f0400 KEY_NUMERIC_0 0x800f0401 KEY_NUMERIC_1 0x800f0402 KEY_NUMERIC_2 0x800f0403 KEY_NUMERIC_3

It is possible to override the protocol definition with the -p (long form: --protocol) command line parameter. We shall see that this is quite useful later on. The sudo prefix must be used when the -w or -p option is used since the protocol is being set.

It is bad form to load the remote definition file directly from the /lib/udev/rc_keymaps/ directory. Instead, for good reasons, it should be done from the /etc/rc_keymaps directory. If the file included in the ir-keytable package contains a correct definition, create a symbolic link in the /etc/rc_keymaps directory.

zero@opi:~$ sudo ln -s /lib/udev/rc_keymaps/rc6_mce /etc/rc_keymaps/rc6_mce zero@opi:~$ ls -l /etc/rc_keymaps/ total 0 lrwxrwxrwx 1 root root 28 Feb 10 12:39 rc6_mce -> /lib/udev/rc_keymaps/rc6_mce zero@opi:~$ sudo ir-keytable -c -w /etc/rc_keymaps/rc6_mce Read rc6_mce table Old keytable cleared Wrote 63 keycode(s) to driver Protocols changed to rc-6

If the original keymap needs to be changed, copy the file to the /etc/rc_keymaps directory, modify it as needed and load its modified content with the same command as above. If a new keymap file is to be created for an IR remote, place it in the /etc/rc_keymaps directory. That is precisely what I did to use the KEYES remote.

michel@hp:~$ sudo nano /etc/rc_keymaps/keyes
# table keyes, type: nec 0x46 KEY_UP 0x40 KEY_OK 0x15 KEY_DOWN 0x43 KEY_RIGHT 0x44 KEY_LEFT 0x52 KEY_NUMERIC_0 0x16 KEY_NUMERIC_1 0x19 KEY_NUMERIC_2 0x0d KEY_NUMERIC_3 0x0c KEY_NUMERIC_4 0x18 KEY_NUMERIC_5 0x5e KEY_NUMERIC_6 0x08 KEY_NUMERIC_7 0x1c KEY_NUMERIC_8 0x5a KEY_NUMERIC_9 0x42 KEY_NUMERIC_STAR 0x4a KEY_NUMERIC_POUND

The following command adds that definition so that both remotes can be used. Note how two IR protocols were specified on the command line. That was necessary because without the -p option, ir-keytable would have set the protocol to nec only based on the first line of the keyes file.

michel@hp:~$ sudo ir-keytable -p nec,rc6 -w /etc/rc_keymaps/keyes Read keyes table Wrote 17 keycode(s) to driver Protocols changed to nec rc-6 zero@opi:~$ ir-keytable -t Testing events. Please, press CTRL-C to abort. 1549818188.628176: event type EV_MSC(0x04): scancode = 0x800f0401 1549818188.628176: event type EV_KEY(0x01) key_down: KEY_NUMERIC_1(0x0201) 1549818188.628176: event type EV_SYN(0x00). 1549818188.734319: event type EV_MSC(0x04): scancode = 0x800f0401 1549818188.734319: event type EV_SYN(0x00). 1549818188.971971: event type EV_KEY(0x01) key_up: KEY_NUMERIC_1(0x0201) 1549818188.971971: event type EV_SYN(0x00). 1549818214.729052: event type EV_MSC(0x04): scancode = 0x16 1549818214.729052: event type EV_KEY(0x01) key_down: KEY_NUMERIC_1(0x0201) 1549818214.729052: event type EV_SYN(0x00). 1549818214.780128: event type EV_MSC(0x04): scancode = 0x16 1549818214.780128: event type EV_SYN(0x00). 1549818215.015970: event type EV_KEY(0x01) key_up: KEY_NUMERIC_1(0x0201) 1549818215.015970: event type EV_SYN(0x00).

As can be seen, key code KEY_NUMERIC_1 is transmitted by the kernel, first in response to the scan code 0x800f0401 from the HP remote using the RC-6 protocol and again after receiving the 0x16 scan code via the NEC protocol from the KEYES remote.

The Broken udev Rule toc

The installation of ir-keytable included a udev rule. If like me you are not familiar with udev, I recommend the Debian documentation udev - the Linux dynamic device management module which I found surprisingly understandable. Kudos to the author. Here is the rule which in effect loads a configuration file.

michel@hp:~$ cat /lib/udev/rules.d/60-ir-keytable.rules # Automatically load the proper keymaps after the Remote Controller device # creation. # The keycode tables rules should be at /etc/rc_maps.cfg ACTION=="add", SUBSYSTEM=="rc", RUN+="/usr/bin/ir-keytable -a /etc/rc_maps.cfg -s $name"

The rule is broken at least on the Orange Pi Zero.

zero@opi:~$ journalctl | grep udevd ... Feb 09 16:46:35 opi systemd-udevd[358]: Process '/usr/bin/ir-keytable -a /etc/rc_maps.cfg -s rc0' terminated by signal SEGV.

I take this to mean that the IR receiver is recognized by udev but ir-keytable raises a segmentation error which is sometimes indicative of a missing file. This can be checked by modifying the rule.

# Automatically load the proper keymaps after the Remote Controller device # creation. # The keycode tables rules should be at /etc/rc_maps.cfg #ACTION=="add", SUBSYSTEM=="rc", RUN+="/usr/bin/ir-keytable -a /etc/rc_maps.cfg -s $name" ACTION=="add", SUBSYSTEM=="rc", RUN+="/bin/ls -l /sys/class/rc &> /tmp/ls.txt"

After rebooting

zero@opi:~$ journalctl | grep udevd ... Feb 10 16:47:31 opi systemd-udevd[517]: Process '/bin/ls -l /sys/class/rc &> /tmp/ls.txt' failed with exit code 2. zero@opi:~$ cat /tmp/ls.txt cat: /tmp/ls.txt: No such file or directory zero@opi:~$ ls -l /sys/class/rc total 0 lrwxrwxrwx 1 root root 0 Feb 10 16:47 rc0 -> ../../devices/platform/soc/1f02000.ir/rc/rc0

It looks like the symbolic link rc0 is not yet created when the rule is executed. Perhaps the directory /sys/devices/platform/soc/1f02000.ir/rc/rc0 does exist, so I renamed the rule so that it be the last to be executed and changed it slightly.

zero@opi:~$ cat /lib/udev/rules.d/99-xir-keytable.rules # Automatically load the proper keymaps after the Remote Controller device # creation. # The keycode tables rules should be at /etc/rc_maps.cfg #ACTION=="add", SUBSYSTEM=="rc", RUN+="/usr/bin/ir-keytable -a /etc/rc_maps.cfg -s $name" ACTION=="add", SUBSYSTEM=="rc", RUN+="/bin/ls -l /sys/devices/platform/soc/1f02000.ir/rc &> /tmp/ls.txt"

The result was just as disappointing. It looks like it will be necessary to resort to a task at boot time to initialize the IR driver properly.

The ir-keytable Configuration File rc_maps.cfg toc

The -a option is used to load a configuration file, rc_maps.cfg as found in the udev rule. Just how the configuration file is supposed to work is mysterious for some including me. Here is part of it.

# Keymaps table # # This table creates an association between a keycode file and a kernel # driver. It can be used to automatically override a keycode definition. # # Although not yet tested, it is meant to be added at udev. # # To use, you just need to run: # ./ir-keytable -a # # Or, if the remote is not the first device: # ./ir-keytable -a -s rc1 # for RC at rc1 # # Format: # driver - name of the driver provided via uevent - use * for any driver # table - RC keymap table, provided via uevent - use * for any table # file - file name. If directory is not specified, it will default to # /etc/rc_keymaps. # For example: # driver table file # cx8800 * ./keycodes/rc5_hauppauge_new # * rc-avermedia-m135a-rm-jx ./keycodes/kworld_315u # saa7134 rc-avermedia-m135a-rm-jx ./keycodes/keycodes/nec_terratec_cinergy_xs # em28xx * ./keycodes/kworld_315u # * * ./keycodes/rc5_hauppauge_new # Table to automatically load the rc maps for the bundled IR's provided with the # devices supported by the linux kernel #driver table file ... a long list with this line in particular * rc-rc6-mce rc6_mce ..

A simple try will show that, contrary what is written in the header, ir-keytable -a will not run. The full path to the configuration file must be specified. And ir-keytable -a /etc/rc_maps.cfg (with or without the sudo prefix) does nothing.

To experiment, I removed all entries in the driver table except for the one for the RC6 remote. Trying ir-keytable -a /etc/rc_maps.cfg did nothing with that single entry, but changing the entry to

#driver table file * * rc6_mce

or

#driver table file sunxi-ir * rc6_mce

does work.

zero@opi:~$ sudo ir-keytable -a /etc/rc_maps.cfg Old keytable cleared Wrote 63 keycode(s) to driver Protocols changed to rc-6

That is progress. Note that anything where a kernel object, with or without the .ko extension and with or without a full path does not work. However it does not seem to be possible to load two remote control definitions with the configuration file. I tried listing the desired translation files (with or without sunxi-ir driver specified).

... #driver table file * * rc6_mce * * keyes

This does not work, ir-keytable stops as soon as it has loaded the first file.

Automatic Configuration toc

Given the last two sections, here is how the IR stack is initialized when the Orange Pi Zero is booted if only one remote control is used. First add the name of the definition file in /etc/rc_keymaps to the /etc/rc_maps.cfg file as shown below.

... #driver table file * * rc6_mce

Then create a task to be performed at boot time by cron.

zero@opi:~$ crontab -e
... # m h dom mon dow command @reboot sudo ir-keytable -a /etc/rc_maps.cfg &> /tmp/ir-keytable.log

That should work!

If two or more IR remote definitions are to used then it will be necessary to forego the rc_maps.cfg file all together. The task to perform at boot time will be a bit more complex.

zero@opi:~$ crontab -e
# m h dom mon dow command @reboot sudo ir-keytable -p nec,rc6 -w /etc/rc_keymaps/rc6_mce &>> /tmp/ir-keytable.log @reboot sudo ir-keytable -w /etc/rc_keymaps/keyes &> /tmp/ir-keytable.log

This might seem like a strange thing, but it appears that the commands are executed in reverse order. The second line adds the keyes table and writes any output or error to the temporary log file. After, the command in the first line is executed. It adds the rc6_mce table, sets both needed IR protocols and appends any output or error message to the log file.

I am a bit uncomfortable with that situation, so I prefer creating a simple bash script where the order of execution is clear.

zero@opi:~$ mkdir bin zero@opi:~$ nano bin/ir-setup

The .profile configuration file will add the ~/bin directory to the search path, so bash will find the script file. Here is its content.

#!/bin/bash # Setup key tables and IR protocols for the KEYES and HP MCE IR remote controls sudo ir-keytable -w /etc/rc_keymaps/keyes &> /tmp/ir-keytable.log sudo ir-keytable -p nec,rc6 -w /etc/rc_keymaps/rc6_mce &>> /tmp/ir-keytable.log

Do not forget the "shebang" (the first comment) is mandatory if the file is to be self executing. But it is also necessary to mark it as an executable.

zero@opi:~$ chmod +x bin/ir-setup

Now all that needs to be done is to add it to the crontab file.

zero@opi:~$ crontab -e
# m h dom mon dow command @reboot bin/ir-setup

Conclusion toc

I am sorry that these three notes on IR remotes with the Orange Pi Zero are a bit of a mess. This one should really have been the second, as many will never have to use LIRC.

Hopefully, when I translate these posts into French, I will clean up the mess. And then I can translate back something more coherent into English.

Here are some of the documents consulted to get here.

Infrared Remotes
LibreELEC, last modified 5 weeks ago
MythTV: Use All Buttons of Your Remote Control - Without LIRC
Richard Atterer, 2013-04-21
ir-keytable or: How I Learned to Stop Worrying about the LIRC Kernel
dakscout on Ubuntu forums, May 2009
3.3. Remote Control
in yaVDR Documentation, Marcus Zurhost, October 2012
<-Using Bare Metal IR on the Orange Pi Zero --
<-LIRC on the Orange Pi Zero