Lirc Event Driver
Freevo support the kernel's event driver directly by EVENT_DEVS and using Lirc. This page is describes the set up of the Hauppauge PVR-350 remote using Lirc in detail but it also applied to any remote uses the kernels event driver for input events. I prefer to use Lirc because of the additional tools that it contains. Two very useful commands are irw and ircat.
irw simply shows the events and the remote that the driver sees and ircat shows the events that Freevo sees. Here is an example of running these commands and pressing the play, stop and record buttons:
irw 00000000800100cf 00 Play hauppauge_pvr350 0000000080010080 00 Stop hauppauge_pvr350 00000000800100a7 00 Record hauppauge_pvr350 ctrl+C ircat --config=/etc/freevo/lircrc freevo PLAY STOP REC ctrl+C
As of kernel-2.6.19 the Hauppauge remote uses the Lirc's devinput driver and not hauppauge driver. From various mailing lists the following is a description of the problem and a solution.
Problem
I'm running Gentoo. I just upgraded my kernel from 2.6.15 to 2.6.19, upgraded ivtv drivers from something quite old to 0.10.1, upgraded lirc to 0.8.1, and upgraded a number of other things including Xorg. Everything works smoothly, except for only getting proper responses to ~25% of the presses on my remote control; many "unknown key" errors reported by dmesg.
Was there any progress on this issue?
Excerpt from dmesg
ivtv: ==================== START INIT IVTV ==================== ivtv: version 0.10.1 (tagged release) loading ivtv: Linux version: 2.6.19-gentoo-r5 SMP preempt mod_unload K7 REGPARM ivtv: In case of problems please include the debug info between ivtv: the START INIT IVTV and END INIT IVTV lines, along with ivtv: any module options, when mailing the ivtv-users mailinglist. ivtv0: Autodetected Hauppauge card (cx23415 based) ACPI: PCI Interrupt 0000:00:0f.0[A] -> Link [LNKD] -> GSI 10 (level, low) -> IRQ 10 ivtv0: Unreasonably low latency timer, setting to 64 (was 32) ivtv0: loaded v4l-cx2341x-enc.fw firmware (376836 bytes) ivtv0: loaded v4l-cx2341x-dec.fw firmware (262144 bytes) ivtv0: Encoder revision: 0x02060039 ivtv0: Decoder revision: 0x02020023 input: i2c IR (Hauppauge) as /class/input/input2 ir-kbd-i2c: i2c IR (Hauppauge) detected at i2c-0/0-0018/ir0 [ivtv i2c driver #0] saa7115 0-0021: saa7115 found (1f7115d0e100000) @ 0x42 (ivtv i2c driver #0) saa7127 0-0044: saa7127 found @ 0x88 (ivtv i2c driver #0) msp3400 0-0040: MSP4448G-A2 found @ 0x80 (ivtv i2c driver #0) msp3400 0-0040: MSP4448G-A2 supports radio, mode is autodetect and autoselect tuner 0-0061: chip found @ 0xc2 (ivtv i2c driver #0) tveeprom 0-0050: Hauppauge model 48132, rev J333, serial# 6825606 tveeprom 0-0050: tuner model is Temic 4039FR5 (idx 33, type 21) tveeprom 0-0050: TV standards NTSC(M) (eeprom 0x08) tveeprom 0-0050: audio processor is MSP4448 (idx 27) tveeprom 0-0050: decoder processor is SAA7115 (idx 19) tveeprom 0-0050: has radio, has IR remote ivtv0: Autodetected Hauppauge WinTV PVR-350 ivtv0: Registered device video0 for encoder MPEG (4 MB) ivtv0: Registered device video32 for encoder YUV (2 MB) ivtv0: Registered device vbi0 for encoder VBI (1 MB) ivtv0: Registered device video24 for encoder PCM audio (1 MB) ivtv0: Registered device radio0 for encoder radio ivtv0: Registered device video16 for decoder MPEG (1 MB) ivtv0: Registered device vbi8 for decoder VBI (1 MB) ivtv0: Registered device vbi16 for decoder VOUT ivtv0: Registered device video48 for decoder YUV (1 MB) ivtv0: loaded v4l-cx2341x-init.mpg firmware (155648 bytes) tuner 0-0061: type set to 21 (Temic NTSC (4039 FR5)) ivtv0: Initialized Hauppauge WinTV PVR-350, card #0 ivtv: ==================== END INIT IVTV ==================== ACPI: PCI Interrupt 0000:01:05.0[A] -> Link [LNKA] -> GSI 11 (level, low) -> IRQ 11 nvidiafb: Device ID: 10de0182 nvidiafb: CRTC0 analog not found nvidiafb: CRTC1 analog not found nvidiafb: Unable to detect display type... ...Using default of CRT nvidiafb: Unable to detect which CRTCNumber... ...Defaulting to CRTCNumber 0 nvidiafb: Using CRT on CRTC 0 nvidiafb: MTRR set to ON Console: switching to colour frame buffer device 80x30 nvidiafb: PCI nVidia NV18 framebuffer (64MB @ 0xD4000000) EXT3 FS on hda3, internal journal ivtv0-fb: Framebuffer at 0xdd510000, mapped to 0xe1710000, size 1665k ivtv0-fb: === Validated display mode === ivtv0-fb: Display size 720x480 (720x480 Virtual) @ 32bpp ivtv0-fb: Display position 1,1 ivtv0-fb: Display filter : on ivtv0-fb: Color space : RGB ivtv0-fb: Running in compatibility mode. Display resize & mode change disabled ivtv0-fb: Framebuffer registered on ivtv card id 0 lirc_dev: IR Remote Control driver registered, at major 61 lirc_i2c: chip found @ 0x18 (Hauppauge IR) lirc_dev: lirc_register_plugin: sample_rate: 10 Adding 506036k swap on /dev/hda2. Priority:-1 extents:1 across:506036k ivtv0-fb: === Validated display mode === ivtv0-fb: Display size 720x480 (720x480 Virtual) @ 32bpp ivtv0-fb: Display position 1,1 ivtv0-fb: Display filter : on ivtv0-fb: Color space : RGB eth0: DSPCFG accepted after 0 usec. eth0: link up. eth0: Setting full-duplex based on negotiated link capability. ivtv0-fb: === Validated display mode === ivtv0-fb: Display size 720x480 (720x480 Virtual) @ 32bpp ivtv0-fb: Display position 1,1 ivtv0-fb: Display filter : on ivtv0-fb: Color space : RGB ivtv0-fb: === Display mode change === ivtv0-fb: Display size 720x480 (720x480 Virtual) @ 32bpp ivtv0-fb: Display position 1,1 ivtv0-fb: Display filter : on ivtv0-fb: Color space : RGB eth0: no IPv6 routers present i2c IR (Hauppauge): unknown key: key=0x25 raw=0x17e5 down=1 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x17e5 down=0 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x1fe5 down=1 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x1fe5 down=0 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x17e5 down=1 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x17e5 down=0 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x1fe5 down=1 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x1fe5 down=0 i2c IR (Hauppauge): unknown key: key=0x1f raw=0x1fdf down=1 i2c IR (Hauppauge): unknown key: key=0x1f raw=0x1fdf down=0 i2c IR (Hauppauge): unknown key: key=0x1f raw=0x17df down=1 i2c IR (Hauppauge): unknown key: key=0x1f raw=0x17df down=0 i2c IR (Hauppauge): unknown key: key=0x1f raw=0x1fdf down=1 i2c IR (Hauppauge): unknown key: key=0x1f raw=0x1fdf down=0 i2c IR (Hauppauge): unknown key: key=0x1f raw=0x17df down=1 i2c IR (Hauppauge): unknown key: key=0x1f raw=0x17df down=0 i2c IR (Hauppauge): unknown key: key=0x1f raw=0x1fdf down=1 i2c IR (Hauppauge): unknown key: key=0x1f raw=0x1fdf down=0 i2c IR (Hauppauge): unknown key: key=0x1f raw=0x17df down=1 i2c IR (Hauppauge): unknown key: key=0x1f raw=0x17df down=0 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x1fe5 down=1 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x1fe5 down=0 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x17e5 down=1 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x17e5 down=0 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x1fe5 down=1 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x1fe5 down=0 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x1fe5 down=1 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x1fe5 down=0 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x17e5 down=1 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x17e5 down=0 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x1fe5 down=1 i2c IR (Hauppauge): unknown key: key=0x25 raw=0x1fe5 down=0
Downgrading back to my 2.6.18.7 kernel resolved the lirc problem. I was using the 2.6.19.7 kernel when the problems started occurring. I also experienced system freezing issues as well with 2.6.19.7 + ivtv-0.10.1. So I'm currently running the 2.6.18 kernel with 0.10.1 to see if that problem is resolved as well.
The source of these errors is a bad interaction between ir_kbd_i2c and lirc_i2c. Unfortunately, ir_kbd_i2c is being built into my kernel somehow, and I don't know how to disable it. (saa7134 is known to include ir_kbd_i2c, but CONFIG_VIDEO_SAA7134=n for me). Therefore, the only solution is to avoid avoid lirc_i2c. Fortunately, this is not too difficult -- we just need to use the linux event interface instead.
Solution
This solutions is based on information from: Using with lircd and Remotes
- Use lsmod to make sure lirc_i2c is not loaded.
- Gentoo: remove lirc_i2c from /etc/modules.autoload.d/kernel-2.6 to stop loading on reboot.
- Make sure lircd is not running
Gentoo: /etc/init.d/lircd stop
- Install v4l input utils
Gentoo: {{{echo sys-apps/input-utils ~x86 >> /etc/portage/package.keywords
emerge sys-apps/input-utils}}}
Find your tuner card in the event interfaces, run lsinput. Mine says:
... /dev/input/event4 bustype : BUS_I2C vendor : 0x0 product : 0x0 version : 0 name : "i2c IR (Hauppauge)" phys : "i2c-4/4-0018/ir0" bits ev : EV_SYN EV_KEY EV_REP ...
So my remote is on event4.The default map for events won't handle all the keys on your remote. Useful things like the "OK" button and the "Back" button won't work, and other buttons will be mapped to odd things. We can fix this by updating the mapping for the device. I modified the method given in one of the reference links above. To use my modifications:
cd /etc mkdir ivtv cd ivtv # get applykeymap, a small scrip to remove comments from the pvr350 input event mapping file wget web.mit.edu/bonawitz/www/ivtv/applykeymap # get ir_kbd_i2c.pvr350.conf the PVR-350 imput mapping file wget web.mit.edu/bonawitz/www/ivtv/ir_kbd_i2c.pvr350.conf chmod +x applykeymap # set the mappings ./applykeymap ir_kbd_i2c.pvr350.conf 4
(in the last line, replace the final 4 with your device's event number)- Lirc needs to be built for devinput rather than hauppauge support.
- Gentoo: edit /etc/make.conf: {{{LIRC_DEVICES="devinput"
emerge --newuse lirc}}}
You'll need a new lirc.conf. The easy solution is to get a copy of the one I made (which is designed to match the hauppauge_pvr device in the standard lirc configuration at lircd.conf.hauppauge. To do so:
cd /etc mv lircd.conf lircd.conf.hauppauge_ivtv wget web.mit.edu/bonawitz/www/ivtv/lircd.conf.hauppauge_devinput ln -s lircd.conf.hauppauge_devinput lircd.conf
Alternately, you can make your own:
cd /etc mv lircd.conf lircd.conf.hauppauge_ivtv irrecord -H dev/input -d /dev/input/event4 lircd.conf.hauppauge_devinput ln -s lircd.conf.hauppauge_devinput lircd.conf
Remember to use your device's event number in the irrecord command. If you make your own configuration, you'll either need to make sure your button names match what is currently in your /etc/lircd.conf, or you'll need to customize the lircrc file used by Freevo. My lircd.conf is listed below- Point lircd to the appropriate event device (Remember to use your device's event number) edit /etc/conf.d/lirc: LIRCD_OPTS="-H dev/input -d /dev/input/event2"
- Restart lircd
Gentoo: /etc/init.d/lircd start
At this point, you should have a fully functioning remote control again. The one last thing to do is to make sure that the key mappings get applied every time you boot the system. On Gentoo I accomplished this by adding a script to my /etc/init.d:
cd /etc/init.d wget web.mit.edu/bonawitz/www/ivtv/ivtv chmod +x ivtv rc-update add ivtv default
Details
What happens with the lirc driver is the kernel generates input events these need to be mapped to event driver events, this is achieved with the ir_kbd_i2c.pvr350.conf mapping file.
The Lirc dev/input driver needs to map these to a remote as it is possible to use varions different remotes with Lirc, this mapping is done with /etc/lirc/lircd.conf
Finally the Lirc events need to be mapped to Freevo events and this is achived /etc/freevo/lircrc (configured by LIRCRC in local_conf.py.
The mapping files are listed below and finally are the boots scripts that I use.
/etc/ivtv/ir_kbd_i2c.pvr350.conf
I updated the ir_kbd_i2c.pvr350.conf that was retrieved from the above instructions for aditional commands
/etc/ivtv/ir_kbd_i2c.pvr350.conf
# Starting at the top 0x003d = 116 # KEY_POWER 0x003b = 218 # KEY_CONNECT 0x001C = 377 # KEY_TV 0x0018 = 393 # KEY_VIDEO 0x0019 = 392 # KEY_AUDIO 0x001A = 375 # KEY_SCREEN (Pictures) 0x001B = 395 # KEY_LIST (Guide) 0x0000 = 82 # KEY_KP0 0x0001 = 79 # KEY_KP1 0x0002 = 80 # KEY_KP2 0x0003 = 81 # KEY_KP3 0x0004 = 75 # KEY_KP4 0x0005 = 76 # KEY_KP5 0x0006 = 77 # KEY_KP6 0x0007 = 71 # KEY_KP7 0x0008 = 72 # KEY_KP8 0x0009 = 73 # KEY_KP9 0x001f = 1 # KEY_ESC 0x000d = 139 # KEY_MENU # cursor keys 0x0014 = 103 # KEY_UP 0x0015 = 108 # KEY_DOWN 0x0016 = 105 # KEY_LEFT 0x0017 = 106 # KEY_RIGHT # the colored buttons are kind of hard to label since they don't have one # red 0x000b = 120 # KEY_F21 # green 0x002e = 121 # KEY_F22 # yellow 0x0038 = 122 # KEY_F23 # blue 0x0029 = 123 # KEY_F24 # ch/vol +/- 0x0010 = 115 # KEY_VOLUMEUP 0x0011 = 114 # KEY_VOLUMEDOWN 0x0020 = 402 # KEY_CHANNELUP 0x0021 = 403 # KEY_CHANNELDOWN # OK (button in the middle of the ch/vol keys) 0x0025 = 28 # KEY_ENTER # mute 0x000f = 113 # KEY_MUTE # (blank) 0x000c = 148 # KEY_PROG1 (Radio) 0x003c = 132 # KEY_FRONT # next row 0x0032 = 168 # KEY_REWIND 0x0035 = 207 # KEY_PLAY 0x0034 = 208 # KEY_FASTFORWARD # next row 0x0037 = 167 # KEY_RECORD 0x0036 = 128 # KEY_STOP 0x0030 = 164 # KEY_PLAYPAUSE # last row (2 buttons) 0x001e = 163 # KEY_NEXTSONG 0x0024 = 165 # KEY_PREVIOUSSONG 0x000A = 368 # KEY_LANGUAGE 0x000E = 370 # KEY_SUBTITLE # you'll have to remove the comments from this file # because the input tools don't handle comments # # The codes on the right side of the equal sign came from input.h in the # kernel # The codes on the left came from a lot of pushing buttons and watching # the output from the ir-kbd-i2c module in the kernel logs
/etc/lirc/lircd.conf
I updated the lircd.conf that was retrieved from the above instructions
/etc/lirc/lircd.conf
# Please make this file available to others # by sending it to <lirc@bartelmus.de> # # this config file was automatically generated # using lirc-0.8.1(dev/input) on Tue Mar 27 14:22:13 2007 # # contributed by Keith Bonawitz (bonawitz at mit.edu) # # brand: Hauppauge # model no. of remote control: # devices being controlled by this remote: PVR 2/350 # begin remote name hauppauge_pvr350 bits 16 eps 30 aeps 100 one 0 0 zero 0 0 pre_data_bits 16 pre_data 0x8001 gap 135991 toggle_bit 0 begin codes Power 0x0074 Go 0x00DA TV 0x0179 Videos 0x0189 Music 0x0188 Pictures 0x0177 Guide 0x018B Blank 0x0094 Up 0x0067 Down 0x006C Left 0x0069 Right 0x006A 0 0x0052 1 0x004F 2 0x0050 3 0x0051 4 0x004B 5 0x004C 6 0x004D 7 0x0047 8 0x0048 9 0x0049 Back/Exit 0x0001 Menu 0x008B Red 0x0078 Green 0x0079 Yellow 0x007A Blue 0x007B Ch+ 0x0192 Ch- 0x0193 Vol- 0x0072 Vol+ 0x0073 Ok 0x001C Mute 0x0071 Full 0x0084 Rewind 0x00A8 Play 0x00CF Forward 0x00D0 Record 0x00A7 Stop 0x0080 Pause 0x00A4 Replay 0x00A5 Skip 0x00A3 Lang 0x0170 Sub 0x0172 Prev.Ch 0x00E1 end codes end remote
/etc/freevo/lircrc
/etc/freevo/lircrc
begin button = GO prog = freevo repeat = 0 config = MENU end begin button = HOME prog = freevo repeat = 0 config = MENU end begin button = POWER prog = freevo repeat = 0 config = POWER end begin button = TV prog = freevo repeat = 0 config = TV end begin button = VIDEOS prog = freevo repeat = 0 config = VIDEOS end begin button = MUSIC prog = freevo repeat = 0 config = MUSIC end begin button = PICTURES prog = freevo repeat = 0 config = PICTURES end begin button = RECTV prog = freevo repeat = 0 config = RECTV end begin button = GUIDE prog = freevo repeat = 0 config = GUIDE end begin button = LIVETV prog = freevo repeat = 0 config = LIVETV end begin button = DVD prog = freevo repeat = 0 config = RADIO end begin button = BLANK prog = freevo repeat = 0 config = EJECT end begin button = UP prog = freevo repeat = 3 config = UP end begin button = DOWN prog = freevo repeat = 3 config = DOWN end begin button = LEFT prog = freevo repeat = 3 config = LEFT end begin button = RIGHT prog = freevo repeat = 3 config = RIGHT end begin button = OK prog = freevo repeat = 0 config = SELECT end begin button = BACK/EXIT prog = freevo repeat = 0 config = EXIT end begin button = BACK prog = freevo repeat = 0 config = EXIT end begin button = MENU/I prog = freevo repeat = 0 config = ENTER end begin button = MORE prog = freevo repeat = 0 config = ENTER end begin button = VOL+ prog = freevo repeat = 3 config = VOL+ end begin button = VOL- prog = freevo repeat = 3 config = VOL- end begin button = MUTE prog = freevo repeat = 0 config = MUTE end begin button = CH+ prog = freevo repeat = 3 config = CH+ end begin button = CH- prog = freevo repeat = 3 config = CH- end begin button = PREV.CH prog = freevo repeat = 0 #config = PREV_CH config = DISPLAY end begin button = PLAY prog = freevo repeat = 0 config = PLAY end begin button = PAUSE prog = freevo repeat = 0 config = PAUSE end begin button = STOP prog = freevo repeat = 0 config = STOP end begin button = RECORD prog = freevo repeat = 0 config = REC end begin #button = REW button = REWIND prog = freevo repeat = 3 config = REW end begin #button = FFW button = FORWARD prog = freevo repeat = 3 config = FFWD end begin #button = REPLAY button = REPLAY/SKIPBACKWARD prog = freevo repeat = 3 config = REPLAY end begin #button = SKIP button = SKIPFORWARD prog = freevo repeat = 3 config = SKIP end begin button = 0 prog = freevo repeat = 3 config = 0 end begin button = 1 prog = freevo repeat = 3 config = 1 end begin button = 2 prog = freevo repeat = 3 config = 2 end begin button = 3 prog = freevo repeat = 3 config = 3 end begin button = 4 prog = freevo repeat = 3 config = 4 end begin button = 5 prog = freevo repeat = 3 config = 5 end begin button = 6 prog = freevo repeat = 3 config = 6 end begin button = 7 prog = freevo repeat = 3 config = 7 end begin button = 8 prog = freevo repeat = 3 config = 8 end begin button = 9 prog = freevo repeat = 3 config = 9 end begin #button = TEXT button = ASTERIX prog = freevo repeat = 0 config = LANG end begin #button = SUB/CC button = HASH prog = freevo repeat = 0 config = SUBTITLE end begin button = CLEAR prog = freevo repeat = 0 config = EJECT end begin button = RED prog = freevo repeat = 0 config = RED #config = EJECT end begin button = GREEN prog = freevo repeat = 0 config = GREEN end begin button = YELLOW prog = freevo repeat = 0 config = YELLOW end begin button = BLUE prog = freevo repeat = 0 config = BLUE #config = DISPLAY end
/etc/rc.d/init.d/lircd
Boot script that I use.
######################################################################## # Begin $rc_base/init.d/lircd # # Description : # # Authors : # # Version : 00.00 # # Notes : # ######################################################################## . /etc/sysconfig/rc . ${rc_functions} . /etc/sysconfig/lircd case "${1}" in start) boot_mesg "IVTV: Mapping Hauppauge Remote" /etc/ivtv/applykeymap /etc/ivtv/ir_kbd_i2c.pvr350.conf \ ${LIRC_EVENT} 2> /dev/null evaluate_retval boot_mesg "Starting Lirc daemon..." if [ -c ${LIRC_DEVICE} ]; then loadproc /usr/sbin/lircd --driver=${LIRC_DRIVER} \ --device=${LIRC_DEVICE} else echo_failure fi ;; stop) boot_mesg "Stopping Lirc daemon..." killproc /usr/sbin/lircd ;; reload) boot_mesg "Reloading Lirc daemon..." reloadproc /usr/sbin/lircd ;; restart) ${0} stop sleep 1 ${0} start ;; status) statusproc /usr/sbin/lircd ;; *) echo "Usage: ${0} {start|stop|reload|restart|status}" exit 1 ;; esac # End $rc_base/init.d/lircd
/etc/sysconfig/lircd
I run Freevo using LinuxFromScratch and not Gentoo but this only means that the start-up scripts are a little different.
These are the setting for by boot script
# Begin /etc/sysconfig/lircd export LIRC_EVENT=4 export LIRC_DEVICE=/dev/input/event${LIRC_EVENT} export LIRC_DRIVER=dev/input # End /etc/sysconfig/lircd
Creating a unique device name with udev
To circumvent the problem that udev sometimes renumbers the event-ids it´s usefull to create a unique name for a device. There´s already a detailed description at IVTVEventInterface on how to do that but for me, as I don´t have to change the ownership of the device (at least on Debian Etch where lircd runs as root), a somewhat shorter rule works fine also:
# /etc/udev/rules.d/010_own.rules KERNEL=="event*", SYSFS{name}=="AT Translated Set 2 keyboard", SYMLINK+="input/remote"
At first look "AT Translated Set 2 keyboard" doesn´t really look unique but that´s the only usefull string that the IR Receiver on my T-Online S100 (german website) gives back and so far it´s working flawless. Maybe only because the "normal" keyboard that I sometimes hook up via USB identifies as ATTRS{name}=="HID 046a:0001" but when a new plugged in event-Hardware interferes with my rule I think I could also incorporate the ATTR{dev}-string (or simply only use the ATTR{dev}-string). At least that´s my conclusion from reading IVTVEventInterface.