Guide for setting up lirc for Hauppauge PVR-150 IR Remote on Fedora Core 6

2007-08-06: After upgrading via yum to kernel 2.6.20-1.2962, I was unable to recompile lirc [10]. I ended up editing grub to boot the old 2948 kernel instead. Remeber, Fedora is a test-bed for RHEL and these pitfalls should be expected as bugs get ironed out. As of 2007-08-13, I see a new kernel is available which may address the problems I ran into.


This is a guide for getting your Hauppauge PVR-150 Remote Control working with lirc and mplayer on Fedora Core 6. There are lirc RPM packages available from different repositories but I've not been able to get things completely working with those. This Howto will take you through:

First off, removing the Fedora lirc rpm via yum will also remove Mplayer which was installed from Livna (dependancy on liblirc_client.so.0 from FC6) - forget that. I've built Mplayer before and it's something best left for a rainy day. We'll just grab the same version of lirc source which Fedora used and cross our fingers.

The Kernel Module

Lirc must have a kernel module[0] available in order for it to work, and for whatever reason, this doesn't seem to be around with kernel-2.6.20-1.2948.fc6 package or lirc-0.8.1-1.fc6. It may be compiled right into the FC6 kernel but I couldn't get it working. So, you will need the kernel development package installed in order to build Lirc (Lirc will take care of the rest). This is easy enough to do via yum:

$ yum install kernel-devel
 

Obtaining the Lirc Source

Download the latest lirc source[1] and save to it /tmp or other place you can write to. The source I used was lirc-0.8.1.tar.bz2. It's good practice to check the md5, gpg or sha1 signature of packages you download to make sure they've not been corrupted during the download, or somehow tampered with otherwise. Unfortunately, I haven't found these on the lirc site so here we go. Unwrap the source you downloaded from the lirc homepage and then change to the newly created directory:

$ cd /tmp
$ tar xvfj lirc-0.8.1.tar.bz2
$ cd lirc-0.8.1

Building Lirc

In the lirc build directory, you will find a configure script to run. This will be used to tell lirc we are building for a hauppauge remote as well as where to place the fresh binaries when installing. I like to put all non-standard stuff I build under /usr/local. I can tell at a glance what is non-standard on the system and keeping the version numbers intact show me at a glance which version is compiled. Also, if I need to remove whatever I've installed, I can just remove the directory under /usr/local and it's gone. No hunting around in /usr/lib or /usr/local/libexec or other bfugly places for parts of packages. I do make heavy use of symlinks with this method, so when a custom package is removed, I also need to search for broken links[2] and remove them to clean up. I don't have to wonder if I've completely removed a piece of software this way. Ok, so onto configuring. Note that it's also good practice to perform the build process as someone other than root. You will need to be root to install, but just in case something gets wacky during the build, the potential to hose the entire system is minimized. I can also recall one instance of trojaned build scripts many years ago, but the ubiquity of package signatures has minimized that risk quite a bit (but yes, they must be available of course).

$ ./configure --prefix=/usr/local/lirc-0.8.1 --with-driver=hauppauge
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
...
You will have to use the lirc_i2c kernel module.
Now enter 'make' and 'make install' to compile and install the package.

Pay close attention to configure. You may need some other development packages installed such as ncurses or even the C compiler, gcc[3]. After configure completes succesfully, continue building the source by running make.

$ make
cd . \
          && CONFIG_FILES= CONFIG_HEADERS=config.h \
             /bin/sh ./config.status
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing default-1 commands
make  all-recursive
make[1]: Entering directory `/tmp/lirc-0.8.1'
...
/bin/sh ../libtool --mode=link gcc  -O2 -g -Wall   -o man2html  man2html.o
mkdir .libs
gcc -O2 -g -Wall -o man2html man2html.o
make[3]: Leaving directory `/tmp/lirc-0.8.1/doc'
make[2]: Leaving directory `/tmp/lirc-0.8.1/doc'
make[2]: Entering directory `/tmp/lirc-0.8.1'
make[2]: Leaving directory `/tmp/lirc-0.8.1'
make[1]: Leaving directory `/tmp/lirc-0.8.1'

Installing Lirc

Time to install, so su to root however you have it setup, either via sudo bash, or simply su:

$ su
Password:
[root@localhost ~ ]

Run make install to move the fresh lirc binaries out of your build directory and into /usr/local/lirc-0.8.1

$ make install
Making install in drivers
make[1]: Entering directory `/tmp/lirc-0.8.1/drivers'
Making install in lirc_dev
make[2]: Entering directory `/tmp/lirc-0.8.1/drivers/lirc_dev'
make[3]: Entering directory `/tmp/lirc-0.8.1/drivers/lirc_dev'
...
 /usr/bin/install -c -m 644 ./lircd.8 /usr/local/lirc-0.8.1//man/man8/lircd.8
 /usr/bin/install -c -m 644 ./lircmd.8 /usr/local/lirc-0.8.1//man/man8/lircmd.8
...
make[2]: Leaving directory `/tmp/lirc-0.8.1'
make[1]: Leaving directory `/tmp/lirc-0.8.1'

Configuring Lirc

With Lirc installed, move onto configuration. You will need two files:

From the looks of it, these two files take care of mapping serial data from the remote into "buttons" and finally mapping the "buttons" to Mplayer commands. Mplayer reads ~/.lircrc and picks out it's configuration info so it knows what to do when you hit a button on the remote. The button names and Mplayer commands seem to be different between software versions and remotes, so I'm not sure which button mapping files are exactly correct. There are several sample .lircrc files out there, this is the one I used.

$ wget http://wilsonet.com/mythtv/lircrc-haupgrey-g3.txt -O ~/.lircrc

There is a lircd.conf file specially crafted for the hauppauge remote which is available from the Lirc sourceforge site, and one is also distributed with the lirc source code. Grab either of these and copy the file from to /etc/lircd.conf:

$ cp /tmp/lirc-0.8.1/remotes/hauppauge/lircd.conf /etc/lircd.conf

Installation of Duct Tape for Lirc binaries

Since we have all our lirc binaries under /usr/local/lirc-0.8.1, none of the new files are in the path, or available for other programs to use. Keep in mind the fedora Lirc rpm is still installed and those binaries *are* in the path. At this point we can:

I chose to forcibly remove[5] the installed lirc rpm to be certain there weren't any conflicting binaries laying around. This is going to cause a problem with Mplayer however because it is looking[6] for liblirc_client.so and it's been removed via rpm. That's OK, because We'll replace it with a symlink pointing to our compiled one in /usr/local/lirc-0.8.1/lib using lndir below:

create the destination directories if they do not exist already:

$ mkdir -p /usr/local/bin /usr/local/sbin /usr/local/lib

symlink the compiled lirc binaries into some common add-on locations: $ lndir /usr/local/lirc-0.8.1/bin/ /usr/local/bin/ $ lndir /usr/local/lirc-0.8.1/sbin/ /usr/local/sbin/ $ lndir /usr/local/lirc-0.8.1/lib/ /usr/local/lib/ }}}

To remove these links at a later time, I can delete the /usr/local/lirc-0.8.1 directory and then run symlinks[7] to clean up the links which point to the now non-existant files.

If we run ldd[6], we'll see that mplayer still hasn't found the liblirc_client.so.0 file. This is because the system hasn't been setup to use /usr/local/lib as a library directory. By default, the only location it will look is in /lib. We don't want to mess around with /lib. This is where all the libraries reside which are responsible for running the entire system. A mistake here may result in re-installing the entire system. It's silly to risk that when there are other options available, so we install our libraries to /usr/local/lib and then update the system configuration to use our new library location. We do this by adding an entry to /etc/ld.so.conf, as root, and then running ldconfig. We can run ldconfig with -v to get a printout of what it's doing. We can then grep this output to see that it finds our new lirc library. We can then ask mplayer[6] about it again to see that it finds the correct library.

$ echo /usr/local/lib >> /etc/ld.so.conf
$ ldconfig -v | grep lirc
        liblirc_client.so.0 -> liblirc_client.so.0.2.0
$ ldd /usr/bin/mplayer  | grep lirc
        liblirc_client.so.0 => /usr/local/lib/liblirc_client.so.0 (0x00002aaaaaadb000)
}}
==== Verifying the kernel module was built correctly ====
compiling lirc will have resulted in two kernel modules being built against your currently running kernel:
  * lirc_dev.ko
  * lirc_i2c.ko
Verify that these modules have a current date on them.  If they do not, there was most likely a conflict while building lirc wich you did not see.  You will need to go back and see what the problem is if you do not see the files as below.   A simple check here can save a lot of headaches later.
{{{
$ ls -laRt /lib/modules/`uname -r` | grep -i lirc
-rw-r--r-- 1 root root  170395 Jun 23 08:51 lirc_dev.ko
-rw-r--r-- 1 root root  155362 Jun 23 08:51 lirc_i2c.ko

Testing the lirc kernel modules

Check that the lirc_i2c module is not loaded by using lsmod and grepping appropriately. It should come up empty. If not, run modprobe -r to remove it and verify again:

$ lsmod | grep lirc
lirc_i2c               19332  0
lirc_dev               25320  1 lirc_i2c
i2c_core               32833  12 cx88xx,bttv,lirc_i2c,i2c_ec,msp3400,saa7115,tuner,nvidia,ivtv,i2c_algo_bit,tveeprom,i2c_nforce2
$ modprobe -r lirc_i2c
$ lsmod | grep lirc
}}
Now load the lirc_i2c module and verify that it is running. Also check with dmesg for any information it may have given us about the module loading process, and  lastly, check that the /dev/lirc0 device does indeed exist after loading:
{{{
$ modprobe lirc_i2c
$ lsmod | grep lirc
lirc_i2c               19332  0
lirc_dev               25320  1 lirc_i2c
i2c_core               32833  12 lirc_i2c,cx88xx,bttv,i2c_ec,msp3400,saa7115,tuner,nvidia,ivtv,i2c_algo_bit,tveeprom,i2c_nforce2
$ dmesg | grep lirc
lirc_dev: IR Remote Control driver registered, at major 61
lirc_i2c: no version for "lirc_unregister_plugin" found: kernel tainted.
lirc_i2c: chip found @ 0x18 (Hauppauge IR)
lirc_dev: lirc_register_plugin: sample_rate: 10
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
$ ls -lart /dev/lirc*
crw------- 1 root root 61, 0 Jun 23 11:33 /dev/lirc0

You will notice that modprobe loaded the lirc_dev module for us, which is needed by lirc_i2c.

One problem above is that root is the only person which can access the /dev/lirc0 device. We want to be able to access this as regular users, so certainly this will need to be addressed. Usually these permissions are taken care of with module loading parameters. There is some information about module loading in the lirc documentation[8] but there is talk of /etc/modules.conf and /etc/conf.modules which have been done away with for quite some time. Udev and sysfs are quite new, althogh I'm not clear how these mechanisms are used. The lirc documentation says to copy lirc.rules into the udev directory as follows:

$ cp /tmp/lirc-0.8.1/contrib/lirc.rules /etc/udev/rules.d/
`/tmp/lirc-0.8.1/contrib/lirc.rules' -> `/etc/udev/rules.d/lirc.rules'

...but things didn't work

$ rm /etc/udev/rules.d/lirc.rules

Finally getting to some button pressing

There is another way. I can just load the modules "by hand" at boot time in /etc/rc.local (which is a symlink to /etc/rc.d/rc.local) and make the neccesary adjustments to the device permissions there.

We know the modules we want, the device we need for communication, and the permissions that need to be set. I'm edit /etc/rc.local and load the module, start up lircd, and set the permissions on the device:

  /sbin/modprobe lirc_i2c
  /usr/local/sbin/lircd -d /dev/lirc0
  chmod 0666 /dev/lirc0

Lastly, we want to make sure /etc/rc.local is indeed a symlink to /etc/rc.d/rc.local. If we broke the symlink somehow, editing this file will do nothing. ultimately, we want to be editing /etc/rc.d/rc.local. /etc/rc.local is just a shortcut.

ls -l /etc/rc.local
lrwxrwxrwx 1 root root 13 Jan 13 08:27 /etc/rc.local -> rc.d/rc.local

Looks good.

For now, we can just run the three lines we entered into /etc/rc.local (/etc/rc.d/rc.local) by had to get our remote working with lirc. When/if we reboot rc.local will get executed and do the same thing.

Next we check the remote with irw, and hit a few buttons to see if it's sending and receiving.

$ irw 0000000000001792 00 Prev.Ch Hauppauge_350 0000000000001792 01 Prev.Ch Hauppauge_350

The button names come from /etc/lircd.conf that we copied into place earlier. When a button is pressed on the remote, the IR receiver hardware and the kernel modules talk to lircd to let it know what happened. The /etc/lircd.conf file contains button mapping data for several remotes. In this case, it's the Hauppage 350.

So, now that lircd, the kernel module, and the remote are all functional we configure mplayer to let it know it should be listening to /dev/lirc0 for remote control information.

in the source directory for lirc (src-0.8.1/contrib/lircrc) is a lircrc file. This file doesn't contain mplayer button info, so we need to use this one I gleaned from the mythtv dox.

# ~/.mythtv/lircrc
#
# MythTV native LIRC config file for
# the new grey Hauppauge remote
#
# Modified from Jarod Wilson's which came from Jeff Campbell's
# By Brad Templeton
# Modified by digitek for mplayer
#
### MPlayer lirc setup
# Show OSD
begin
prog = mplayer
button = MENU
repeat = 3
config = osd
end
# Pause playback
begin
prog = mplayer
button = PAUSE
repeat = 3
config = pause
end
# Skip ahead a minute if playing
# If paused, resume playing
begin
prog = mplayer
button = PLAY
repeat = 3
config = seek +1
end
# Stop playback and exit
begin
prog = mplayer
button = STOP
repeat = 3
config = quit
end
# Mute
begin
prog = mplayer
button = MUTE
repeat = 3
config = mute
end
# Seek forward 30 seconds
begin
prog = mplayer
button = Forward
repeat = 3
config = seek +10
end
# Quit
begin
prog = mplayer
button = BACK/EXIT
repeat = 3
config = quit
end
# Seek backward 10 minutes
begin
prog = mplayer
button = Rewind
repeat = 3
config = seek -10
end
# fullscreen
begin
prog = mplayer
button = OK
repeat = 3
config = vo_fullscreen
config = vo_ontop
end
# volume up
begin
prog = mplayer
button = Vol+
repeat = 3
config = volume  +1
end
# volume down
begin
prog = mplayer
button = Vol-
repeat = 3
config = volume  -1
end

After saving this file, you should be able to start-up mplayer (from a terminal window) and control it via the hauppauge remote. Watch for the first few lines of mplayer to spit out errors about lirc indicating something is amiss.

mplayer: bad file format, /home/yagi/.lircrc:386 Failed to read LIRC config file ~/.lircrc.

Also, don't forget to plug in the IR receiver ;-)


Notes/References[0] - lirc_i2c

[1] - http://www.lirc.org/software.html

[2] - man symlinks or symlinks -dr /usr/local

[3] - yum install ncurses-devel; yum install gcc

[4] - http://wilsonet.com/mythtv/lircrc-haupgrey-g3.txt

[5] - $ rpm -e --nodeps lirc-0.8.1-1.fc6

[6] - $ ldd /usr/bin/mplayer | grep lirc liblirc_client.so.0 => not found

[7] - $ symlinks -dr /usr/local/sbin /usr/local/bin /usr/local/lib

deleted: /sbin/lircmd -> /usr/local/lirc-0.8.1/sbin/lircmd

dangling: /sbin/lircd -> /usr/local/lirc-0.8.1/sbin/lircd

deleted: /sbin/lircd -> /usr/local/lirc-0.8.1/sbin/lircd

[8] - http://www.lirc.org/html/install.html#installing

[9] - Failed to open LIRC support. You will not be able to use your remote control.

[10] - after upgrading via yum ....

make[3]: Entering directory `/usr/local/lirc-0.8.1/src/lirc-0.8.1/drivers/lirc_i2c'
mv Makefile Makefile.automake
cp ../Makefile.kernel Makefile
make -C /lib/modules/2.6.20-1.2962.fc6/build/ SUBDIRS=/usr/local/lirc-0.8.1/src/lirc-0.8.1/drivers/lirc_i2c modules \
KBUILD_VERBOSE=1
make[4]: Entering directory `/usr/src/kernels/2.6.20-1.2962.fc6-x86_64'
test -e include/linux/autoconf.h -a -e include/config/auto.conf || (            \
echo;                                                           \
echo "  ERROR: Kernel configuration is invalid.";               \
echo "         include/linux/autoconf.h or include/config/auto.conf are missing.";      \
echo "         Run 'make oldconfig && make prepare' on kernel src to fix it.";  \
echo;                                                           \
/bin/false)
mkdir -p /usr/local/lirc-0.8.1/src/lirc-0.8.1/drivers/lirc_i2c/.tmp_versions

ok.. so..

cp /boot/config-2.6.20-1.2962.fc6 .config               
make oldconfig

#[1]$ make bzImage
  CHK     include/linux/version.h
  CHK     include/linux/utsrelease.h
  HOSTCC  scripts/genksyms/genksyms.o
  HOSTCC  scripts/genksyms/lex.o
  HOSTCC  scripts/genksyms/parse.o
  HOSTLD  scripts/genksyms/genksyms
  CC      scripts/mod/empty.o
  HOSTCC  scripts/mod/mk_elfconfig
  MKELF   scripts/mod/elfconfig.h
  HOSTCC  scripts/mod/file2alias.o
  HOSTCC  scripts/mod/modpost.o
  HOSTCC  scripts/mod/sumversion.o
  HOSTLD  scripts/mod/modpost
  HOSTCC  scripts/kallsyms
  HOSTCC  scripts/pnmtologo
  HOSTCC  scripts/conmakehash
make[1]: *** No rule to make target `init/main.o', needed by `init/built-in.o'.  Stop.
make: *** [init] Error 2

..and still borked.

mplayer/lirc howto for Hauppauge pvr-150 (last edited 2007-08-13 12:05:25 by digitek)