• 1(current)
  • 2
  • 3
  • 4
  • 5
  • 16
How to get a seamless remote experience
#1
Lightbulb 
Preface

There seems to be a lot of confusion about how Linux deals with IR receivers and remotes. Many people simply can't get anything to work at all, some are having problems with their remotes sending events twice and others can't get every button to work or get them mapped to XBMC the way they want it.

That's why I decided to try to write this guide to try and take away at least some confusion by outlining the options you have to get your remote to work. I will also to the best of my ability try to explain the procedure to get everything to work the way you want it, but I won't go into too much detail. So if you want or have to compile some silly (source wrapped) proprietary driver to get your receiver to work (e.g. nuvoton) or want to compile a newer version of LIRC or a custom kernel, you're on your own. I consider that to be outside the scope of this guide. I just want to sketch the landscape.

I also would like to make clear that, although I am pretty well versed in Linux, I am by no means an expert with regard to remotes or LIRC. So if I make any mistakes feel free to correct me. I will do my best to keep this guide as accurate as possible. Due to my proficiency with Linux I may get ahead of some of you, so please stop me if I do. Do note, however that this is not a tutorial. It's not a sequences of steps or commands that you have execute and all is well. I think that may work very well for particular configurations such as those Asrocks that come with only one type of receiver and one type of remote. But this more of a guide that attempts to be as generic as possible. I'm trying to make you understand how things work, so you should be able to get any configuration working.

Introduction

I think a big part of this confusion is caused by the migration of LIRC functionality to the Linux kernel (drivers). This change started in 2.6.33 with the inclusion of the ir-core module in the mainline kernel. Many older guides currently on the internet have of course not taken this into account, which is why those traditional guides won't work too well. Hence, a 'new' guide.

Somebody has written a good article about this change. Note that even though he talks about 2.6.35, the change started in 2.6.33. The author is simply talking about iMon specifically, which was indeed included in 2.6.35. This means that from 2.6.33 and onward you are risking conflicts between the new kernel interface and lirc. However, the fact that the core has been included does not mean it works for all devices, but it does mean potential conflicts start there. The 'new' drivers have been included in the following versions:

2.6.33: core
2.6.35: iMON
2.6.36: Lirc bridge
2.6.38: mceusb (MS/HP/Philips or other MCE compatible receivers)
2.6.39: Nuvoton CIR (w83667hg), Winbond Super I/O, ENE KB3926 CIR, Streamzap, ITE IT8712F/IT8512 CIR
3.0: Fintek LPC SuperIO Consumer IR Transceiver

So it depends on your Linux version and IR receiver whether you can follow my guide. Here the overview:
<=2.6.32 all receivers: you can NOT follow this guide, but there will also be no conflicts. Just use a lirc tutorial and you'll be fine
>=2.6.33 all combinations (or better) not (white)listed above: you can NOT follow this guide, because your receiver is not supported (yet). However, there can be conflicts, so disable the new interface by blacklisting all ir-* and rc-* modules. Then you can just use lirc regularly. Or if you can download, compile and install the drivers separately for your kernel, you can of course follow this guide.
All other cases: you can choose to follow my guide OR use the lirc bridge (>=2.6.36) (see section 2.1 in post #2) or do rc-* ir-* mceusb/imon/in-kernel-driver-for-your-receiver blacklisting to just use lirc.

You can find out which version you are running by executing
Code:
uname -r

Note: Ubuntu "Lucid" 10.04 LTS runs 2.6.32 or 2.6.35 (both are included in the official APT repository), so it falls into the first (2.6.32) or second (2.6.35) category, except if you have an iMON receiver. Why you would want to run Lucid on a bleeding edge multimedia system such as an HTPC is beyond me, but I thought I should explicitly mention Lucid a lot of people still run it.

Executive Summary

After reading this guide I hope you are able to:
  • understand how IR signals are processed by Linux;
  • emulate a keyboard with your remote;
  • map almost every button on your remote to the appropriate key press or media centre event; or
  • assign various actions to the same button on your remote in XBMC, depending on the context

Anyway, to the guide it is.

The guide

There are roughly three stages that all have to worked out to get a seamless experience. Depending on your hardware, software, configuration and certain choices you make, these stage may require anything from almost no configuration to a lot of compiling and configuring.

0. Table of Contents
  1. IR receiver (post #1)
  2. The remote (posts #2 and #3)
  3. Mapping buttons to XBMC (post #4)

Since the posts are restricted to 10000 chars, this will be a three part guide, corresponding to the abovementioned list. Stage 1 will be included in this post and stage 2 and 3 will get their own posts.

1. IR Receiver
The focus will be on the second and third stage, since the first stage isn't radically different from what it used to be in the past. Like with any device it's about finding the right driver (kernel module), optionally compiling it and installing and using it. It's the way it's always been. Like I said, if you want to know about DKMS or something have a look at DKMS guide or tutorial and then come back here. So that I'm not going to pay too much attention to right now.

All I can do if that if you are still planning to buy an IR receiver, make sure it is compatible with Linux out-of-the-box, meaning that the driver should be included in the vanilla Linux kernel. This will make life a lot easier for you.

If you already have a receiver, plug it in and enter

Code:
dmesg

You should see something similar to this:

Code:
[   13.200050] Registered IR keymap rc-rc6-mce
[   13.200159] input: Media Center Ed. eHome Infrared Remote Transceiver (0471:0815) as /devices/pci0000:00/0000:00:12.0/usb3/3-3/3-3:1.0/rc/rc0/input2
[   13.200218] rc0: Media Center Ed. eHome Infrared Remote Transceiver (0471:0815) as /devices/pci0000:00/0000:00:12.0/usb3/3-3/3-3:1.0/rc/rc0
[   13.200267] mceusb 3-3:1.0: Registered Philips eHome Infrared Transceiver on usb3:2
[   13.200288] usbcore: registered new interface driver mceusb

Also check

Code:
lsusb

At the very least your receiver should be detected and not be listed as "unknown device" or something.

Code:
Bus 003 Device 002: ID 0471:0815 Philips (or NXP) eHome Infrared Receiver

Just so you know, my receiver worked out of the box. I hand picked it Wink.

Anyway, this is nothing new. Like I said it's something you may have to do for every device: look if it works by default, if not, search for and install the appropriate driver(s).

What has changed is the testing procedure. Many traditional guides will start by using

Code:
irw

to verify if your receiver can receive IR signals and thus if the driver works well. This however, is no longer a reliable method, due to the changes in Linux 2.6.33 and onward. I will get back to this in stage two, but for the purpose of simply testing your IR receiver, stop lirc and execute

Code:
ir-keytable -c -p NEC,RC-5,RC-6,JVC,SONY -t

It should be generating events now. I will dissect this command and its output in section 2.2, but for now it suffices to see if it works at all. Remember, this is just about the receiver. If you don't have this command, install the package that provides it. In Ubuntu this is ir-keytable, but I think it varies per distribution.

Also try all your other remotes if it didn't work: from your TV, DVD, BR, Xbox, A/V receiver and your dog. Some remotes simply are not compatible, but one of them definitely will be.

If all of this has failed, it's pretty safe to say your driver probably hasn't been installed correctly. Go back to start and do not receive €20000.
Reply
#2
2. Remote

So you have established that the receiver works. Now you have to have software that receives and interprets those IR signals. In the past, there was only LIRC. But as of Linux 2.6.36, functionality is being moved into the kernel (Kernel Newbies).

While this can potentially be very useful, it does seem to be at the root of the confusion of many people. This is perfectly understandable, as official documentation is very sparse.

The problem seems to be that the kernel now 'catches' all the events and does not let them through to LIRC. And sometimes LIRC also seems to get in the way of the kernel, especially when you've already configured lirc.

So basically LIRC and the in-kernel drivers interfere with each other. Note that I'm using LIRC 0.8.7 (Ubuntu Natty default) and according to the LIRC FAQ you need 0.9.0 with in-kernel drivers. So upgrading will most likely solve this problem, but if you don't feel like upgrading LIRC you can also do what I said before, which was to disable lirc entirely or let the kernel pass through all commands to LIRC.

I think it would also be possible to simply disable the kernel drivers by blacklisting all ir-* and rc-* modules, but I see no reason to do that instead of using passthrough.

In short, there seem to be three possible 'paths' that an incoming IR signal can go through:

  1. Let the kernel pass the signal through to LIRC
  2. Do everything completely in-kernel
  3. Let the kernel cooperate with LIRC

2.1 Let the kernel pass the signal through to LIRC
The first one will allow you to follow the traditional LIRC guides. All you have to do is execute

Code:
modprobe ir-lirc-codec
ir-keytable -p LIRC

You can add 'ir-lirc-codec' to /etc/modules and the ir-keytable command to /etc/rc.local (or equivalent) if you want to make it persistent.

This should allow irw to function as it has always done, so you can now use hardware.conf, lircd.conf and irrecord as described in the traditional lirc howtos.

If you choose this path, you probably won't be able to emulate keypresses and assign different actions to the same button (I think). You will have to use Lircmap.xml instead of keyboard.xml and the latter looks much more versatile (at least the vanilla ones).

So then the guide stops here and I suggest you follow a good guide about LIRC. I do however, recommend you to switch to the kernel drivers.

2.2 Do everything completely in-kernel
If you use the in-kernel functionality you will be able to easily emulate keyboard presses.

First, start by disabling LIRC. You can disable lirc semi-permanently by changing the START_LIRCD config value to false in /etc/lirc/hardware.conf. Or by simply uninstalling it. We're not going to need it any way. But first stop lirc, because when that variable is set to false, you can't stop or start lirc. Also stop XBMC for the time being, because you don't want your remote to do funny things with XBMC when it starts working.

Then, if you haven't got it-keytable installed yet, do it now and execute

Code:
ir-keytable

You should see something like this:

Code:
Found /sys/class/rc/rc0/ (/dev/input/event2) with:
        Driver mceusb, table rc-rc6-mce
        Supported protocols: NEC RC-5 RC-6 JVC SONY LIRC
        Enabled protocols: NEC RC-5 RC-6
        Repeat delay = 500 ms, repeat period = 33 ms

The important line is the line "Supported protocols". Like the name says, it indicates which protocols are supported by your receiver. This is important, because your remote and your receiver will have to 'speak' the same protocol.

Based on the very little experience I have, I have found that RC5 (you can ommit the dash) is mainly used by TVs, RC6 by MCE remotes and NEC by most other remotes that are not Sony or JVC based. Apparently there can also be overlap between protocols. For instance, my Sony Bravia TV remote generates events for both RC5 and SONY.

So you may have to find out what protocol your remote 'speaks'. You could probably just select all of them and you'll most likely be fine, but it is also possible that you really have to pick the correct one.

In any case, execute

Code:
ir-keytable -c -p $protocols -t

-c clears your mapping table if you already programmed one.
-p defines which protocols your IR receiver should listen to. Replace $protocols with a comma separated list of all your supported protocols. In my case that would be NEC,RC-5,RC-6,JVC,SONY,LIRC.
-t initiates the test mode. Think of it as the kernel version of irw.

Press some keys. You should now see something like this:

Code:
1309368621.558360: event MSC: scancode = 45b580
1309368622.010326: event MSC: scancode = 45b581
1309368622.465330: event MSC: scancode = 45b551
1309368622.966319: event MSC: scancode = 45b54d
1309368623.814289: event MSC: scancode = 45b522
1309368624.285272: event MSC: scancode = 45b584
1309368625.009254: event MSC: scancode = 45b5de
1309368625.569238: event MSC: scancode = 45b520
1309368626.643231: event MSC: scancode = 45b501
1309368627.080215: event MSC: scancode = 45b502
1309368627.483210: event MSC: scancode = 45b503

If one button generates two events with entirely different scancodes, your remote probably speaks two protocols, like my Bravia does. It looks like this:

Code:
1309368864.058322: event MSC: scancode = 1f3f
1309368864.058344: event MSC: scancode = 97008a
1309368864.109318: event MSC: scancode = 1f3f
1309368864.109340: event MSC: scancode = 97008a
1309368864.159316: event MSC: scancode = 1f3f
1309368864.159337: event MSC: scancode = 97008a
1309368866.089281: event MSC: scancode = 1f3f
1309368866.089305: event MSC: scancode = 97008f
1309368866.145265: event MSC: scancode = 1f3f
1309368866.145287: event MSC: scancode = 97008f
1309368866.178268: event MSC: scancode = 1f3f
1309368866.178288: event MSC: scancode = 97008f
1309368866.682269: event MSC: scancode = 1f3f
1309368866.682293: event MSC: scancode = 970090
1309368866.733263: event MSC: scancode = 1f3f
1309368866.733286: event MSC: scancode = 970090
1309368866.783262: event MSC: scancode = 1f3f
1309368866.783288: event MSC: scancode = 970090

The 1f3f scancode is useless, because it's always the same, no matter which button I press. You can test which protocol is the truly correct one by using ir-keytable again:

Code:
ir-keytable -c -p $proto -t

One by one you can test each protocol. In my case, when I set the protocol to RC5, it generates the 1f3f codes and when I set it to SONY, it generates the right ones. All the other protocols do not generate anything. So now I know that my Bravia remote uses SONY (duhh).

But like I said you can probably get away with just using all supported protocols at once. The 1f3f scancodes are harmful when left unconfigured.

By the way, once you've set the protocol(s) you wish to use you don't have to enter them again. At least not until you reboot. So from hereon you can simply use `ir-keyable -t` to test. The -c flag you'll only need when you want to reset the table.

So enter `ir-keyable -t` again and see if all your buttons are functional. It's possible not all of them are, but there's little you can do about that I'm afraid.

Now the part that MAY require the most work. You are now capable of generating events, but they have yet to be connected to a certain key press. If you have a common remote, such as the famous MCE remote, it could be as simple as using the right config file (let's say a lircd.conf for ir-keytable). Execute the following command to see the included config files:

Code:
ls /lib/udev/rc_keymaps/

If you see anything resembling the remote your wish to use with XBMC, you may be lucky. But let's find out for sure. You could be browsing through all these files manually, but this is *NIX, so there's a command for that. Enter `ir-keyable -t` again and press a standard button, such as the ok, up or down. Then copy the resulting scan code and execute the following command:

Code:
grep -iH $scancode /lib/udev/rc_keymaps/*

For instance, if you get "1309375577.020898: event MSC: scancode = 1e14", execute
Code:
grep -iH 1e14 /lib/udev/rc_keymaps/*
The result could be something like:
Code:
/lib/udev/rc_keymaps/dib0700_rc5:0x1e14 KEY_UP
/lib/udev/rc_keymaps/haupp:0x1e14 KEY_UP

So that means either file could be appropriate. Compare this file against more scancodes to be sure. If you're lucky, your remote has a preconfigured config file and you can largely skip the next few steps about creating a custom config file. However, in order to map different XBMC actions to one button depending on the context in which this button is pressed, you will have to make modifications. For that, read through part III & IV first. After the section about creating a custom config file you will be able to find how to load this config file into the memory. And do not modify the files in /lib/udev/rc_keymaps, but copy the appropriate file to /etc/rc_keymaps/.
Reply
#3
2. Remote (continued)

Creating a custom config file
If the grep command did not return any output, however, you will have to create your custom config file. Let's look at a snippet of stock config file (rc6_mce, for MCE remotes) for the general syntax of such a config file:
Code:
0x800f041e KEY_UP
0x800f041f KEY_DOWN
0x800f0420 KEY_LEFT
0x800f0421 KEY_RIGHT
0x800f0422 KEY_OK
So on the left we have a code (which should correspond to the scan code) starting with '0x'. On the right we have the key that has to be pressed. This key can be any 'normal' key on a keyboard (e.g. KEY_A) or any more or less standardized MCE 'key' such as KEY_PLAY, KEY_STOP, KEY_MENU, KEY_RED/GREEN/YELLOW/BLUE or KEY_NUMERIC_x. I'm not sure though how or where those MCE keys are mapped, but many of them work in XBMC. Regardless, all we really need are regular keys anyway, since we can simply map those in the keyboard.xml file (section 3) and many of them are already mapped by default. After all, XBMC can already be controlled using a regular keyboard and we are emulating a keyboard. For instance, XBMC doesn't seem to pickup KEY_INFO, but the 'I' in the keyboard is (also) mapped to this action, we can just use 0x123abc KEY_I, with 123abc being the scancode for the button with which you want to trigger the video info in XBMC.

So what you have to do know if have a good look at your remote and start thinking about which button you want to link to which keyboard button and/or action. I suggest you start defining the default actions that are always the same anyway, such as play, pause, left, right, etc. So open one terminal window with the `ir-keytable -t` command running and one text editor with your config file. Now, for every unambiguous key press it once on your remote, copy the scancode to your config file and connect it to the appropriate action. All in the format depicted above. So if your scancode is 44222a when you press your play button, the line in your config file should look like this: "0x44222a KEY_PLAY". At the end of this process you will have a config file with which your remote can at least control the basic functions.

Before you load your config file I suggest you put the following line/comment on line 1:

Code:
# table some-name, type: $proto

Loading your config file
Whether you have created your own config file or used a stock one, you have to load it in order for it to be used. The config file goes into the /etc/rc_keymaps/ folder. The name doesn't really matter. Just keep it brief and concise. By the way, do not overwrite the standard config files in /lib/udev/rc_keymaps/. If you want to use one, copy it to /etc/rc_keymaps/ and modify it there.

Anyway, to load your config file, use ir-keytable again:

Code:
ir-keytable -c -p $proto -w /etc/rc_keymaps/$file

If you've defined the correct protocol in the comment in the file, you can ommit the -p $proto part. Here I use:
Code:
ir-keytable -c -w /etc/rc_keymaps/onkyo-dvd

For the record, I'm using a universal remote that came with my TX-NR509 AV receiver. It can control a lot of devices (I have a good 10 pages of remote control codes) and I've set it up as a DVD player remote. This is my config file:
Code:
# table onkyo-dvd, type: NEC

0x45b512 KEY_S                  # Source On/Off

0x45b521 KEY_ENTER
0x45b580 KEY_UP
0x45b581 KEY_DOWN
0x45b551 KEY_LEFT
0x45b54d KEY_RIGHT

0x45b520 KEY_MENU               # Setup
0x45b522 KEY_BACK               # Return
0x45b584 KEY_I                  # Video
0x45b5de KEY_C                  # Guide/Top Menu

0x45b527 KEY_H                  # Home
0x45b516 KEY_Z                  # Display

0x45b515 KEY_PLAY
0x45b500 KEY_PLAYPAUSE
0x45b514 KEY_STOP

#0x2d2d32 KEY_REWIND
#0x2d2d33 KEY_FASTFORWARD

0x45b535 KEY_RED
0x45b536 KEY_GREEN
0x45b537 KEY_YELLOW
0x45b533 KEY_BLUE

0x45b50a KEY_NUMERIC_0
0x45b501 KEY_NUMERIC_1
0x45b502 KEY_NUMERIC_2
0x45b503 KEY_NUMERIC_3
0x45b504 KEY_NUMERIC_4
0x45b505 KEY_NUMERIC_5
0x45b506 KEY_NUMERIC_6
0x45b507 KEY_NUMERIC_7
0x45b508 KEY_NUMERIC_8
0x45b509 KEY_NUMERIC_9

#
# Onkyo Remote Code: 33504
#

But like I said, for now, just pay attention to the standard functionality. Also note that ir-keytable will segfault if it finds any comments prior to the first definition. Took me a while to figure out what the hell was wrong with my config file (not that that is a valid reason to segfault but ok). Anyway, the command should output something like this:

Code:
Read onkyo-dvd table
Old keytable cleared
Wrote 29 keycode(s) to driver
Protocols changed to NEC

If you open `ir-keytable -t` again the output for the configured buttons should be similar to this:
Code:
1309389537.706840: event MSC: scancode = 45b521
1309389537.706868: event key down: KEY_ENTER (0x001c)
1309389537.706878: event sync
1309389537.738835: event MSC: scancode = 45b521
1309389537.738859: event MSC: scancode = 45b521
1309389537.986104: event key up: KEY_ENTER (0x001c)
1309389537.986119: event sync
1309389543.267687: event MSC: scancode = 45b581
1309389543.267713: event key down: KEY_DOWN (0x006c)
1309389543.267714: event sync
1309389543.516097: event key up: KEY_DOWN (0x006c)
1309389543.516112: event sync
1309389547.808589: event MSC: scancode = 45b551
1309389547.808612: event key down: KEY_LEFT (0x0069)
1309389547.808613: event sync
1309389548.056101: event key up: KEY_LEFT (0x0069)
1309389548.056117: event sync
1309389549.183552: event MSC: scancode = 45b54d
1309389549.183579: event key down: KEY_RIGHT (0x006a)
1309389549.183581: event sync
1309389549.426105: event key up: KEY_RIGHT (0x006a)
1309389549.426120: event sync
1309389552.252585: event MSC: scancode = 45b522
1309389552.252610: event key down: KEY_BACK (0x009e)
1309389552.252611: event sync
1309389552.496098: event key up: KEY_BACK (0x009e)
1309389552.496118: event sync

So it should recognize the keys you entered. Now start XBMC and see if the buttons you configured actually do something there as well!

If you want to load the config file at boot time you can use /etc/rc_maps.cfg, but I haven't quite figured out how yet. Since my HTPC is also my server, uptime is of some significance to me, so I can't just reboot whenever I want. But in the meantime you can copy the ir-keytable command to /etc/rc.local.

2.3 Let the kernel cooperate with LIRC

Apparently you can also combine the strengths of both the in-kernel mapping and keyboard emulation with LIRC, which does seem to have some capabilities that the kernel drivers don't, such a connecting certain scripts to certain buttons, through irexec. You'll only need to do this though if you need this sort of advanced functionality. According to the LIRC website you need at least 0.9.0, but I also got it working with LIRC 0.8.7. YMMV though. I also didn't really test it very thoroughly, as I don't have any use for LIRC at this moment. For this section you will need to have done everything from section 2.2. You can skip section 2.1.

First, start with installing lirc if you've deinstalled it or never installed it in the first place. If you're asked what remote you want to use, choose "Linux input layer (/dev/input/eventX)". Generally you won't need a transmitter device for XBMC, so select "none". For the device, pick the one with the name in it. In my case, this is the resulting hardware.conf. If your package manager doesn't generate it, just use mine and adapt it:

Code:
#Chosen Remote Control
REMOTE="Linux input layer (/dev/input/eventX)"
REMOTE_MODULES=""
REMOTE_DRIVER="devinput"
REMOTE_DEVICE="/dev/input/by-id/usb-Philips_eHome_Infrared_Transceiver_PH00OXFk-event-if00" ### Change this one!!!! ###
REMOTE_SOCKET=""
REMOTE_LIRCD_CONF="devinput/lircd.conf.devinput"
REMOTE_LIRCD_ARGS=""

#Chosen IR Transmitter
TRANSMITTER="None"
TRANSMITTER_MODULES=""
TRANSMITTER_DRIVER=""
TRANSMITTER_DEVICE=""
TRANSMITTER_SOCKET=""
TRANSMITTER_LIRCD_CONF=""
TRANSMITTER_LIRCD_ARGS=""

#Enable lircd
START_LIRCD="true"

#Don't start lircmd even if there seems to be a good config file
#START_LIRCMD="false"

#Try to load appropriate kernel modules
LOAD_MODULES="true"

# Default configuration files for your hardware if any
LIRCMD_CONF=""

FORCE_NONINTERACTIVE_RECONFIGURATION="false"
START_LIRCMD=""

Then, modprobe the module that provides support for the LIRC protocol to ir-keytable:

Code:
modprobe ir-lirc-codec

If you want to automatically load this module at boot time, add it to /etc/modules. Next, execute the same ir-keytable command again, but add LIRC to your comma separated (list of) protcol(s), e.g.:

Code:
ir-keytable -c -w /etc/rc_keymaps/myconfig -p NEC,LIRC

If you want to make this persistent, change the command in your /etc/rc.local (or equivalent) as well. Note that if you run a Debian based distro, you wil have to (re)issue this command after you reinstall or dpkg-reconfigure lirc, because it will reset the protocol to LIRC only.

Then, again if your package manager didn't generate a correct hardware.conf, you'll most likely also need to modify your lircd.conf. For now, just add

Code:
include "/usr/share/lirc/remotes/devinput/lircd.conf.devinput"

So now the chain looks like this:
Code:
events -> kernel (ir-keytable) -> LIRC -> mappings from your ir-keytable config file chained through to LIRC (through the include line in lircd.conf)
                                       -> custom mappings from lircd.conf (through custom directives in lircd.conf)
Now you can do all the LIRC-only stuff in lircd.conf, while retaining the advantage of kernel drivers. If all is well you should be able to see events in irw:

Code:
000000008001001c 00 KEY_ENTER devinput
0000000080010067 00 KEY_UP devinput
0000000080010069 00 KEY_LEFT devinput
000000008001006a 00 KEY_RIGHT devinput
000000008001006c 00 KEY_DOWN devinput

Up next: multi-purpose buttons with keyboard.xml.
Reply
#4
If all went well, you have now mapped all the basic functionality and you know how to emulate keyboard presses. There is one slight problem, though, which you will probably find out if you start mapping all the functionality onto your remote. It's kind of obvious when you think about it. The solution however, can be bit more complicated. But let's start with the problem. The problem is that your remote probably has much fewer keys than your remote has.

When using a keyboard, you have the luxury of having a large number of keys available and the standard XBMC keyboard.xml to at least some extent uses this space. Practically, this means that you have a lot of keys that do have some function, but that are simply unavailable in many parts of the program. For instance, there's the 'O' key, which displays codec information while playing a movie. But in the rest of the program, it doesn't seem to do one bit. Or the 'C' button. It displays the context menu when browsing through the files or library, but in other parts is doesn't seem to have any function.

When using a keyboard, it doesn't really matter. Like I said, there are more than enough keys. But when using a regular remote you do NOT have this luxury. Having buttons that are useless 70% of the time is a waste of buttons. If you want to map all functionality, you will have to come up with a creative solution, especially when you don't have a lot of buttons.

In this part I will try to outline one solution that could solve this problem. I will show you how you can create multifunctional remote buttons that have a different function depending on the context in which this button is used. This means that you can 'recycle' a button in different environments in different parts of the program. I had gotten used to this efficient behaviour before I had my 'real' remote and used the Android XBMC App:

Image

For instance, the title button not only triggers the context menu, the same button also shows the codec info when playing a video. And the "menu" button of course triggers the menu, but it also returns you to your Home Screen instantly when your are not playing a video. I found this to be very efficient use of (virtual) buttons and wanted to copy this behaviour with my real remote.

After all, if you don't and you have a limited number of buttons on your remote, you're going to have to settle for a limited subset of the functionality. Or you would have to start working with rather illogical button mappings, such as mapping certain actions to the numeric section of the remote. It'd be like an automated phone call: press 1 for codec info, press 2 for ...

Fortunately, the framework to make this happen already exists and is already being used, even on a keyboard (take for example the "up" key). This magic is all contained in, or at least exposed to the user via keyboard.xml and any user-specific or system wide overrides. And that's exactly what you have to do: create overrides for the vanilla keyboard.xml to map your buttons exactly the way you want to. After all, remember we are emulating a keyboard, so we can configure it as such.

First it's important that you understand how the keyboard.xml file works. Have a good look at the vanilla keyboard.xml. The structure of this file is pretty simple, although maybe a bit too verbose due to being XML and all. The general structure is like this:

Code:
<keymap>
  
  <global>
    <keyboard>
      <key1>Action1</key1>
      <key2>Action2</key2>
      ...
    </keyboard>
  </global>

  <section1>
    <keyboard>
      <key1>Action2</key1>
      ...
    </keyboard>
  </section1>

  <section2>
    <keyboard>
      <key1>Action3</key1>
      ...
    </keyboard>
  </section2>

  ...

</keymap>

So there a different sections. The most important one is "global". Other examples include Home, MyVideoLibrary, FullscreenVideo and lots of others. Just have a look at the default keyboard.xml. The important thing is that you realize there are different sections that can each have different keymappings.

Knowing this, mapping the right actions to exactly the right keys should be relatively easy. However, do NOT change the default keyboard.xml. Rather, create a file of which the contents will automatically override the respective mapping from the central keyboard.xml. The location of this file or these files is ~/.xbmc/userdata/keymaps/. All the files there that have the .xml extension will be processed automatically by XBMC. All you have to do is create a file there (e.g. custom.xml) and you're good to go.

Also important are the actions. You can see most of them in the keyboard.xml file, but there's an exhaustive list here. Those are the actions/command that XBMC will understand. Most them are pretty much self-explanatory, but there's always the description.

So now the actual mapping. To smoothen this process, make sure that in one tab/windows you have the default keyboard.xml and in another the available actions.

Let's go back to the example where we want to map the ContextMenu and CodecInfo to one button on our remote. First, you have to look how they are mapped now. The Context Menu can be triggered with the "C" key as you can see. The Codec Info overlay can be triggered using the "O" button. Now you can do two things: map the Codec Info to the C button or the Context Menu to the O in the appropriate sections. Technically it doesn't matter which route you take, but it's smart to check how many overrides you need and take the one that requires the least overrides. Both actions have been defined globally, so we can simply count the sections in which we would need overrides. Say we wanted to map ContextMenu to "O". We would have to create overrides in MyVideoLibrary, MyVideoFiles, MyMusicLibrary, ... MyFiles, etc, etc. Basically everywhere where you can browse files or database entries. Those are a lot of sections. However, if we chose to map CodecInfo to "C" it would be less work. With <FullscreenVideo> the most important mapping would already be fixed.

Now, make sure your custom.xml has the proper structure to begin with, which is basically a <keymap> tag to open and a </keymap> tag to close. Between those tags you can map your keys (within sections). So we wanted to map the CodecInfo action the the C button. The first question is in which sections. Global? No, because then the content menu wouldn't function anymore. So, where do we need CodecInfo? Only when a video is playing of course. The most prominent section is <FullscreenVideo>, but there are also other. If we make this map, everytime you press the button that is mapped to KEY_C in ir-keytable, you get the codec info overlay, while in other parts of XBMC the default behaviour of the C button remains (open/close a context menu).

Another, slightly simpler example, is this: normally, the backspace key goes to the parent directory (i.e. back). But when playing a video I wanted to use my "back" button to go back 7 secs. This way I have a good control over the video: up/down for a big step (10 minutes or one chapter) forward/backward, left/right for 30 second steps and back for a 7 second step back (in case I missed something someone just said or something that just happened and I don't want to rewatch 30 seconds).

And you can also add 'new' functionality. For instance, I have a "Home" button, with which I would like to go back to the Home Screen whenever I press it. There's no mapping to a normal key, so we have to create one. The "H" is not in use so let's take that one. We can just define it in the 'global' section. The action is XBMC.ActivateWindow(Home).

Also, I would like the "menu" button ("M" on the keyboard) to open the Settings. In the video sections this button has already been mapped to opening the OSD Menu, so all we have to do is create a 'global' override (which is not valid for the sections where "M" has already been defined explicitly). The resulting file looks like this:

Code:
<keymap>

    <global>
        <keyboard>
            <h>XBMC.ActivateWindow(Home)</h>
            <m>XBMC.ActivateWindow(Settings)</m>
        </keyboard>
    </global>

    <FullscreenVideo>
        <keyboard>
            <c>CodecInfo</c> <!-- Default: ContextMenu -->
            <backspace>SmallStepBack</backspace> <!-- Default: ParentDir -->
        </keyboard>
    </FullscreenVideo>

    <FullscreenInfo>
        <keyboard>
            <c>CodecInfo</c>
        </keyboard>
    </FullscreenInfo>

    <VideoOSD>
        <keyboard>
            <c>CodecInfo</c>
        </keyboard>
    </VideoOSD>

    <OSDVideoSettings>
        <keyboard>
            <c>CodecInfo</c>
        </keyboard>
    </OSDVideoSettings>

    <OSDAudioSettings>
        <keyboard>
            <c>CodecInfo</c>
        </keyboard>
    </OSDAudioSettings>

</keymap>

In the comments I documented the default behaviour for KEY_C, but it's not necessary of course. Note the repetitive pattern with just different section tags. I hope it's pretty self-explanatory.

So know you know how to 'add' functionality/actions and override currently mapped functionality. Note that the examples I just gave you are just that: examples. Like I said, I was basically inspired by the way the XBMC Android Remote App mapped its buttons. When mapping your own keys you will have to use your own preferences and creativity.
Reply
#5
Q: What are the advantages and disadvantages of using kernel drivers with ir-keytable instead of LIRC?
A: The advantages basically are that you are able to emulate a keyboard, that it's much more in line with the way Linux handles other input devices and that it's simpler to configure, but that one is just my opinion. Disadvantages are that LIRC probably has support for more receivers and a bigger userbase, meaning much more lircd.conf files available that might apply to your remote. Also, at this moment LIRC seems to have somewhat more extensive functionality and is more mature.

Q: Are there any known quirks?
The most important concern I have at the moment is that ir-keytable doesn't play nicely on the i386 architecture.

Q: How can I make the receiver work again after waking up from standby or hibernation?
A: See this post
Reply
#6
So, something like this:
http://ubuntuforums.org/showthread.php?t=1754719
http://forum.xbmc.org/showthread.php?tid=101151
Code:
GRANT ALL PRIVILEGES ON `xbmc_%`.* TO 'xbmc'@'%';
IF you have a mysql problem, find one of the 4 dozen threads already open.
Reply
#7
darkscout Wrote:So, something like this:
http://ubuntuforums.org/showthread.php?t=1754719
http://forum.xbmc.org/showthread.php?tid=101151
Ah yes it saw it on the Ubuntu forums, but I didn't know you also posted it here (or that you were the author, for that matter). Any way, I intend to make my guide a bit more generic, extensive and with more (background) information, but yes the cornerstone is the same. Still, I hope people find my guide useful.
Reply
#8
Looking forward to part 3 and 4 Smile
Been pulling my hair out trying to get this to work. Option 1 does not work for me, so hopefully the kernel drivers will. I get a response back from ir-keytable but nothing happens in XBMC.

Look forward to the next part
Reply
#9
dude! o/ (high five!)
Reply
#10
Ok, this all seems to be making sense to me so far (thank again for doing this, best explanation I've found so far on what is happening)

I've modified my keymap to correspond to the response I get when running ir-keytable -t
Loading it seems to work as well

However, I stil don't see the keys listed now when doing a new test

Quote:root@Gaia:~# ir-keytable -c -p RC-6 -w /etc/rc_keymaps/mce_mod
Read mce_mod table
Old keytable cleared
Wrote 61 keycode(s) to driver
Protocols changed to RC-6

root@Gaia:~# ir-keytable
Found /sys/class/rc/rc0/ (/dev/input/event4) with:
Driver mceusb, table rc-rc6-mce
Supported protocols: NEC RC-5 RC-6 JVC SONY LIRC
Enabled protocols: RC-6
Repeat delay = 500 ms, repeat period = 33 ms

root@Gaia:~# ir-keytable -t
Testing events. Please, press CTRL-C to abort.
1309463200.960765: event MSC: scancode = 800f7422
1309463201.079789: event MSC: scancode = 800f7422
1309463201.173804: event MSC: scancode = 800f7422
1309463202.187839: event MSC: scancode = 800f741e
1309463202.306843: event MSC: scancode = 800f741e
1309463202.400827: event MSC: scancode = 800f741e
1309463202.519847: event MSC: scancode = 800f741e

Any idea what I'm missing ? It seems so close to being right !
Reply
#11
gazrat Wrote:Looking forward to part 3 and 4 Smile
Been pulling my hair out trying to get this to work. Option 1 does not work for me, so hopefully the kernel drivers will. I get a response back from ir-keytable but nothing happens in XBMC.

Look forward to the next part
I think you need to modprobe ir-lirc-codec. I forgot that one yesterday. Then restart lirc and reissue the ir-keytable command.

gazrat Wrote:Ok, this all seems to be making sense to me so far (thank again for doing this, best explanation I've found so far on what is happening)

I've modified my keymap to correspond to the response I get when running ir-keytable -t
Loading it seems to work as well

However, I stil don't see the keys listed now when doing a new test



Any idea what I'm missing ? It seems so close to being right !
Did you use the vanilla rc6_copy (or a verbatim copy thereof)? Because it looks like you've got an Xbox 360 Universal Remote, or one that uses the same codes. I recognized the codes, because I also have an Xbox 360 with that remote Smile.

The vanilla rc6_mce file contains codes that are almost the same, but one digit is different. If I'm not mistaken you pressed OK and then UP, right? Look at the difference:

Code:
root@sonata:~# ir-keytable -c -p RC6 -t
Old keytable cleared
Protocols changed to RC-6
Testing events. Please, press CTRL-C to abort.
1309465964.748507: event MSC: scancode = 800f7422
1309465965.593485: event MSC: scancode = 800f741e

Same as yours. I'm using the Xbox 360 remote here. Now look at the codes from the default rc6:

Code:
0x800f0422 KEY_OK
0x800f041e KEY_UP

Notice any difference?
800f7422
800f0422

So you probably have to modify all of them. If you already did that, please give me your config file so I can see what's wrong Smile

edit: it's also possible you forgot to prefix the codes with '0x'?
Reply
#12
Hi, thanks for the help. Sorry about late reply, weekend got in the way Smile

So, tried it with modprobe and restart. Still nothing...

Quote:root@Gaia:~# modprobe ir-lirc-codec
root@Gaia:~# /etc/init.d/lirc restart
* Stopping remote control daemon(s): LIRC
...done.
* Loading LIRC modules
...done.
* Starting remote control daemon(s) : LIRC
...done.
root@Gaia:~# ir-keytable -c -p RC-6 -w /etc/rc_keymaps/mce_mod -t
Read mce_mod table
Old keytable cleared
Wrote 61 keycode(s) to driver
Protocols changed to RC-6
Testing events. Please, press CTRL-C to abort.
1309796446.387901: event MSC: scancode = 800f741f
1309796446.494901: event MSC: scancode = 800f741f
1309796446.600969: event MSC: scancode = 800f741f
1309796447.497919: event MSC: scancode = 800f7422
1309796447.603962: event MSC: scancode = 800f7422
1309796447.709968: event MSC: scancode = 800f7422
1309796447.816934: event MSC: scancode = 800f7422
1309796450.688026: event MSC: scancode = 800f741e
1309796450.794049: event MSC: scancode = 800f741e
1309796450.901019: event MSC: scancode = 800f741e

That's pressing the DOWN, OK and UP buttons which seem to be mapped correctly.


Heres the config file
Quote:root@Gaia:~# cat /etc/rc_keymaps/mce_mod
# table mce_mod, type: RC6
0x800f7400 KEY_NUMERIC_0
0x800f7401 KEY_NUMERIC_1
0x800f7402 KEY_NUMERIC_2
0x800f7403 KEY_NUMERIC_3
0x800f7404 KEY_NUMERIC_4
0x800f7405 KEY_NUMERIC_5
0x800f7406 KEY_NUMERIC_6
0x800f7407 KEY_NUMERIC_7
0x800f7408 KEY_NUMERIC_8
0x800f7409 KEY_NUMERIC_9
0x800f740a KEY_DELETE
0x800f740b KEY_ENTER
0x800f740c KEY_POWER
0x800f740d KEY_LEFTMETA
0x800f740e KEY_MUTE
0x800f740f KEY_INFO
0x800f7410 KEY_VOLUMEUP
0x800f7411 KEY_VOLUMEDOWN
0x800f7412 KEY_CHANNELUP
0x800f7413 KEY_CHANNELDOWN
0x800f7414 KEY_FASTFORWARD
0x800f7415 KEY_REWIND
0x800f7416 KEY_PLAY
0x800f7417 KEY_RECORD
0x800f7418 KEY_PAUSE
0x800f746e KEY_PLAYPAUSE
0x800f7419 KEY_STOP
0x800f741a KEY_NEXT
0x800f741b KEY_PREVIOUS
0x800f741c KEY_NUMERIC_POUND
0x800f741d KEY_NUMERIC_STAR
0x800f741e KEY_UP
0x800f741f KEY_DOWN
0x800f7420 KEY_LEFT
0x800f7421 KEY_RIGHT
0x800f7422 KEY_OK
0x800f7423 KEY_EXIT
0x800f7424 KEY_DVD
0x800f7425 KEY_TUNER
0x800f7426 KEY_EPG
0x800f7427 KEY_ZOOM
0x800f743a KEY_BRIGHTNESSUP
0x800f7446 KEY_TV
0x800f7447 KEY_AUDIO
0x800f7448 KEY_PVR
0x800f7449 KEY_CAMERA
0x800f744a KEY_VIDEO
0x800f744c KEY_LANGUAGE
0x800f744d KEY_TITLE
0x800f744e KEY_PRINT
0x800f7450 KEY_RADIO
0x800f745a KEY_SUBTITLE
0x800f745b KEY_RED
0x800f745c KEY_GREEN
0x800f745d KEY_YELLOW
0x800f745e KEY_BLUE
0x800f7465 KEY_POWER2
0x800f746e KEY_PLAYPAUSE
0x800f746f KEY_MEDIA
0x800f7480 KEY_BRIGHTNESSDOWN
0x800f7481 KEY_PLAYPAUSE

I'd copied the vanilla rc6 file and then changed the codes from f0 to f7

I'm at a loss here... Thanks for your help....
Reply
#13
First try to get it to work without lirc, so disable lirc.

It's very strange because I copied your file, executed the same command and here it does work:

Code:
ir-keytable -c -p RC-6 -w /etc/rc_keymaps/xb2 -t
Read mce_mod table
Old keytable cleared
Wrote 61 keycode(s) to driver
Protocols changed to RC-6
Testing events. Please, press CTRL-C to abort.
1309798260.825637: event MSC: scancode = 800f740b
1309798260.825666: event key down: KEY_ENTER (0x001c)
1309798260.825677: event sync
1309798260.945630: event MSC: scancode = 800f740b
1309798261.186223: event key up: KEY_ENTER (0x001c)
1309798261.186240: event sync
1309798263.669557: event MSC: scancode = 800f7421
1309798263.669577: event key down: KEY_RIGHT (0x006a)
1309798263.669579: event sync
1309798263.776563: event MSC: scancode = 800f7421
1309798264.026235: event key up: KEY_RIGHT (0x006a)
1309798264.026252: event sync
1309798264.569536: event MSC: scancode = 800f7420
1309798264.569564: event key down: KEY_LEFT (0x0069)
1309798264.569566: event sync
1309798264.675542: event MSC: scancode = 800f7420
1309798264.916249: event key up: KEY_LEFT (0x0069)
1309798264.916269: event sync
1309798265.299526: event MSC: scancode = 800f741e
1309798265.299554: event key down: KEY_UP (0x0067)
1309798265.299556: event sync
1309798265.418498: event MSC: scancode = 800f741e
1309798265.666220: event key up: KEY_UP (0x0067)
1309798265.666240: event sync

Can you post your lsmod and your ir-keytable (without params)?

You should also try it with another remote. Try to use your TV's or STU's or that of your DVD player and load all protocols:

Code:
ir-keytable -c -p RC5,RC6,NEC,SONY,JVC -t

Then press a few buttons that work and create a custom config file based on those keys. Then load the config and test again:

Code:
ir-keytable -c -p RC5,RC6,NEC,SONY,JVC -w /etc/rc_keymaps/test -t
Reply
#14
Removed lirc completely using apt-get
Same problem.

Created a new config file from scratch using UP, OK and DOWN buttons. No luck there either

Quote: cat /etc/rc_keymaps/test
# table mce-mod
0x800f741e KEY_UP
0x800f7422 KEY_OK
0x800f741f KEY_DOWN
root@Gaia:~# ir-keytable -c -p RC5,RC6,NEC,SONY,JVC -w /etc/rc_keymaps/test -t
Read mce-mod table
Old keytable cleared
Wrote 3 keycode(s) to driver
Protocols changed to NEC RC-5 RC-6 JVC SONY
Testing events. Please, press CTRL-C to abort.
1309815835.952686: event MSC: scancode = 800f741e
1309815836.058697: event MSC: scancode = 800f741e
1309815836.165740: event MSC: scancode = 800f741e
1309815838.431833: event MSC: scancode = 800f7422
1309815838.538822: event MSC: scancode = 800f7422
1309815838.644787: event MSC: scancode = 800f7422
1309815839.401847: event MSC: scancode = 800f741f
1309815839.507843: event MSC: scancode = 800f741f
1309815839.614805: event MSC: scancode = 800f741f
^C

Here's my ir-keytable

Quote:ir-keytable
Found /sys/class/rc/rc0/ (/dev/input/event7) with:
Driver mceusb, table rc-rc6-mce
Supported protocols: NEC RC-5 RC-6 JVC SONY LIRC
Enabled protocols: NEC RC-5 RC-6 JVC SONY
Repeat delay = 500 ms, repeat period = 33 ms

and my lsmod

Quote:lsmod
Module Size Used by
binfmt_misc 13213 1
parport_pc 32111 0
ppdev 12849 0
snd_hda_codec_realtek 255820 1
rt2860sta 494649 0
snd_hda_intel 24140 3
snd_hda_codec 90901 2 snd_hda_codec_realtek,snd_hda_intel
arc4 12473 2
snd_hwdep 13274 1 snd_hda_codec
snd_pcm 80244 3 snd_hda_intel,snd_hda_codec
ir_lirc_codec 12770 0
lirc_dev 18720 1 ir_lirc_codec
snd_seq_midi 13132 0
ir_sony_decoder 12493 0
snd_rawmidi 25269 1 snd_seq_midi
rt2800pci 18159 0
ir_jvc_decoder 12490 0
ir_rc6_decoder 12490 0
snd_seq_midi_event 14475 1 snd_seq_midi
rt2800lib 43824 1 rt2800pci
crc_ccitt 12595 2 rt2860sta,rt2800lib
rt2x00pci 13986 1 rt2800pci
rc_rc6_mce 12454 0
rt2x00lib 39075 3 rt2800pci,rt2800lib,rt2x00pci
ir_rc5_decoder 12490 0
snd_seq 51291 2 snd_seq_midi,snd_seq_midi_event
i915 450944 5
drm_kms_helper 40745 1 i915
mceusb 17579 0
ir_nec_decoder 12490 0
snd_timer 28659 2 snd_pcm,snd_seq
snd_seq_device 14110 3 snd_seq_midi,snd_rawmidi,snd_seq
mac80211 257001 3 rt2800lib,rt2x00pci,rt2x00lib
cfg80211 156212 2 rt2x00lib,mac80211
eeprom_93cx6 12653 1 rt2800pci
psmouse 73312 0
drm 180037 6 i915,drm_kms_helper
rc_core 25760 9 ir_lirc_codec,ir_sony_decoder,ir_jvc_decoder,ir_rc6_decoder,rc_rc6_mce,ir_rc5_decoder,ir_nec_decoder,mceusb
eeepc_laptop 19417 0
serio_raw 12990 0
snd 55295 14 snd_hda_codec_realtek,snd_hda_intel,snd_hda_codec,snd_hwdep,snd_pcm,snd_rawmidi,snd_seq,snd_timer,snd_seq_device
usbhid 41704 0
i2c_algo_bit 13184 1 i915
lp 13349 0
sparse_keymap 13666 1 eeepc_laptop
soundcore 12600 1 snd
snd_page_alloc 14073 2 snd_hda_intel,snd_pcm
hid 77084 1 usbhid
video 18951 1 i915
parport 36746 3 parport_pc,ppdev,lp
usb_storage 43946 0
uas 17676 0
r8169 42534 0

Any ideas ? I unfortunately don't have another remote to try this with right now. Will try to borrow one...
Reply
#15
Strange. You seem to have load all the right kernel modules (well, it's supposed to happen automatically anyway but you never know) and your config file looks just fine. After you've loaded a config file, does `ir-keytable -r` return the proper table you just loaded?
Reply
  • 1(current)
  • 2
  • 3
  • 4
  • 5
  • 16

Logout Mark Read Team Forum Stats Members Help
How to get a seamless remote experience9