Remote Controls

Many remote controls are supported directly by Mythbuntu. From years of experience with third party IR receivers, we have learned that the best ones to use (from the user experience perspective) are any of the USB, MCE-based remotes -- those that use the MCE driver lirc_mceusb or just mceusb (for later versions of Mythbuntu such as 12.04). The lirc_mceusb/mceusb driver is loaded into the kernel and therefore responds quickly and reliably to button presses by the user. The instances where the system does not respond to the helm are minimized, thereby maintaining the user's illusion of control. The Home Electro USB Tira-2 also seems to work well. Response to button presses is consistent and unexpected lockups rarely if ever occur.

However, despite warnings against crappy performance, unexpected lockups and other eratic behavior, should you still wish to use one of the other third party IR receivers (e.g. Home Electro serial Ira, or Iguana Works USB IguanaIR), you will need to do some work. Or, if you wish to use your favorite, unsupported remote, you will likewise have your work cut out for you.

For the MCE-based receivers, LIRC supports them via the "default" driver. You merely need to load the correct kernel module via modprobe for the MCE-based receivers to work properly. Typically, this is done automatically by the LIRC startup script, when you choose one of the MCE-based remotes in the config file so there's nothing else to be done. This is especially true for the latest versions of Mythbuntu (such as 12.04), which include, by default, drivers for not only the MCE-based receivers but a large number of other receivers as well.

Despite the fact that many remotes are directly supported by LIRC, you may sitll want or need to change the kernel module used by your current version of LIRC. For example, you may wish to replace the lirc_mceusb kernel driver in version 0.8.6 of LIRC (which comes built in to earlier versions of Mythbuntu), with a newer version of this driver that supports IR blasting for the latest TopSeed and Pinnacle MCE IR receivers. These receivers are readily obtainable on the Internet for a reasonable price but some of them (the 0x0008 version of the TopSeed, for example) have quirks that prevent IR blasting from working without the use of the latest code in lirc_mceusb.

If you have the latest version of Mythbuntu, it probably comes with version 0.9.0 of LIRC built in. It works quite well with many remotes. For earlier versions of Mythbuntu, that don't have the latest LIRC built in, or if you need to build an up-to-date version of LIRC to support some new, bleeding edge remote, you should follow these steps.

To begin, get the latest, packaged source for LIRC from http://www.lirc.org/software.html and prepare to build it in the usual manner. Then, if necessary, either download the new bleeding edge driver source from SourceForge (or wherever else is appropriate) and replace it in the proper subdirectory of the LIRC build tree, or update the latest source with any patches that you wish to make. Be careful that any new driver source that you use is compatible with the LIRC source that you download. The changes found in the latest source in the build tree may render it incompatible with the distributed source.

For instance, the code that adds support for IR blasting using the 0x0008 version of the above noted TopSeed receivers was added to the build tree after major architectural changes had been made that diverged from the 0.8.6 version of LIRC. Thus, to get TopSeed IR blasting to work, the following patch should be applied to the 0.8.6 LIRC source for lirc_mceusb.c:

lirc-0.8.6/drivers/lirc_mceusb/lirc_mceusb.c:

     --- lirc_mceusb-0.8.6.c     2009-09-02 10:04:02.000000000 -0400
     +++ lirc_mceusb-topseed.c   2010-05-19 17:59:01.824157087 -0400
     @@ -184,6 +184,8 @@
             { USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
             /* Topseed eHome Infrared Transceiver /
             { USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
     +       / Topseed eHome Infrared Transceiver /
     +       { USB_DEVICE(VENDOR_TOPSEED, 0x0011) },
             / Ricavision internal Infrared Transceiver /
             { USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
             / Itron ione Libra Q-11 /
     @@ -226,6 +228,12 @@
             { }
      };
 
     +static struct usb_device_id gen3_list[] = {
     +       { USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
     +       { USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
     +       {}
     +};
     +
      static struct usb_device_id pinnacle_list[] = {
             { USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
             {}
     @@ -245,6 +253,7 @@
             { USB_DEVICE(VENDOR_TOPSEED, 0x0007) },
             { USB_DEVICE(VENDOR_TOPSEED, 0x0008) },
             { USB_DEVICE(VENDOR_TOPSEED, 0x000a) },
     +       { USB_DEVICE(VENDOR_TOPSEED, 0x0011) },
             { USB_DEVICE(VENDOR_PINNACLE, 0x0225) },
             {}
      };
     @@ -272,7 +281,7 @@
             unsigned char is_pulse;
             struct {
                     u32 connected:1;
     -               u32 pinnacle:1;
     +               u32 gen3:1;
                     u32 transmitter_mask_inverted:1;
                     u32 microsoft_gen1:1;
                     u32 reserved:28;
     @@ -296,6 +305,12 @@
      static char pin_init2[] = { 0x9f, 0x13};
      static char pin_init3[] = { 0x9f, 0x0d};
 
     +static char DEVICE_RESET[]     = {0x00, 0xff, 0xaa};
     +static char GET_CARRIER_FREQ[] = {0x9f, 0x07};
     +static char GET_RX_TIMEOUT[]   = {0x9f, 0x0d};
     +static char GET_TX_BITMASK[]   = {0x9f, 0x13};
     +static char GET_RX_SENSOR[]    = {0x9f, 0x15};
     +
      #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
      static unsigned long usecs_to_jiffies(const unsigned int u)
      {
     @@ -944,8 +959,9 @@
             int i;
             char buf[63], name[128] = "";
             int mem_failure = 0;
     -       int is_pinnacle;
     -       int is_microsoft_gen1;
     +       bool is_gen3;
     +       bool is_microsoft_gen1;
     +       bool is_pinnacle;
 
          dprintk(DRIVER_NAME ": %s called\n", __func__);
 
     @@ -955,10 +971,12 @@
 
          idesc = intf->cur_altsetting;
 
     -       is_pinnacle = usb_match_id(intf, pinnacle_list) ? 1 : 0;
     +       is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0;
 
          is_microsoft_gen1 = usb_match_id(intf, microsoft_gen1_list) ? 1 : 0;
 
     +       is_pinnacle = usb_match_id(intf, pinnacle_list) ? 1 : 0;
     +
             / step through the endpoints to find first bulk in and out endpoint /
             for (i = 0; i < idesc->desc.bNumEndpoints; ++i) {
                     ep = &idesc->endpoint[i].desc;
     @@ -975,13 +993,14 @@
                                     "found\n");
                             ep_in = ep;
                             ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
     -                       if (is_pinnacle)
     +                       if (!is_pinnacle)
                                     /
     -                                * setting seems to 1 seem to cause issues with
     -                                * Pinnacle timing out on transfer.
     +                                * Ideally, we'd use what the device offers up,
     +                                * but that leads to non-functioning first and
     +                                * second-gen devices, and many devices have an
     +                                * invalid bInterval of 0. Pinnacle devices
     +                                * don't work witha  bInterval of 1 though.
                                      /
     -                               ep_in->bInterval = ep->bInterval;
     -                       else
                                     ep_in->bInterval = 1;
                     }
 
     @@ -997,13 +1016,14 @@
                                     "found\n");
                             ep_out = ep;
                             ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
     -                       if (is_pinnacle)
     +                       if (!is_pinnacle)
                                     /
     -                                * setting seems to 1 seem to cause issues with
     -                                * Pinnacle timing out on transfer.
     +                                * Ideally, we'd use what the device offers up,
     +                                * but that leads to non-functioning first and
     +                                * second-gen devices, and many devices have an
     +                                * invalid bInterval of 0. Pinnacle devices
     +                                * don't work witha  bInterval of 1 though.
                                      /
     -                               ep_out->bInterval = ep->bInterval;
     -                       else
                                     ep_out->bInterval = 1;
                     }
             }
     @@ -1103,7 +1123,7 @@
             ir->len_in = maxp;
             ir->overflow_len = 0;
             ir->flags.connected = 0;
     -       ir->flags.pinnacle = is_pinnacle;
     +       ir->flags.gen3 = is_gen3;
             ir->flags.microsoft_gen1 = is_microsoft_gen1;
             ir->flags.transmitter_mask_inverted =
                     usb_match_id(intf, transmitter_mask_list) ? 0 : 1;
     @@ -1136,7 +1156,7 @@
             ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
          / initialize device /
  -       if (ir->flags.pinnacle) {
  +       if (is_pinnacle) {
                  int usbret;
 
                  /
  @@ -1165,6 +1185,38 @@
                  request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
                  request_packet_async(ir, ep_out, pin_init3, sizeof(pin_init3),
                                       MCEUSB_OUTBOUND);
  +       }
  +
  +       /* initialize device /
  +       if (ir->flags.gen3) {
  +               request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
  +
  +               / device reset /
  +               request_packet_async(ir, ep_out, DEVICE_RESET,
  +                                    sizeof(DEVICE_RESET), MCEUSB_OUTBOUND);
  +               request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
  +
  +               / get the carrier and frequency /
  +               request_packet_async(ir, ep_out, GET_CARRIER_FREQ,
  +                                    sizeof(GET_CARRIER_FREQ),
  +                                    MCEUSB_OUTBOUND);
  +               request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
  +
  +               / get the transmitter bitmask /
  +               request_packet_async(ir, ep_out, GET_TX_BITMASK,
  +                                    sizeof(GET_TX_BITMASK), MCEUSB_OUTBOUND);
  +               request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
  +
  +               / get receiver timeout value /
  +               request_packet_async(ir, ep_out, GET_RX_TIMEOUT,
  +                                    sizeof(GET_RX_TIMEOUT), MCEUSB_OUTBOUND);
  +               request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
  +
  +               / get receiver sensor setting /
  +               request_packet_async(ir, ep_out, GET_RX_SENSOR,
  +                                    sizeof(GET_RX_SENSOR), MCEUSB_OUTBOUND);
  +               request_packet_async(ir, ep_in, NULL, maxp, MCEUSB_INBOUND);
  +
          } else if (ir->flags.microsoft_gen1) {
                  / original ms mce device requires some additional setup */
                  mceusb_gen1_init(ir);

Once your have the updated or modified source, build LIRC as follows:

     cd lirc-0.8.6
     ./configure --with-driver=mceusb
     make

Most versions of Mythbuntu install the necessary build environment to allow you to build the mceusb driver from scratch. However, if you get an error message that says "you need to have the Linux kernel source installed for this driver", you may have used the wrong driver name with the configure command (e.g. you used "--with-driver=lirc_mceusb" by mistake, instead of "--with-driver=mceusb") or you may not have the correct build environment installed. If you're sure you didn't use the wrong driver name, you should be able to install what you need with:

     sudo apt-get install build-essential linux-headers-`uname -r`

After the build succeeds, locate the existing LIRC kernel driver with a command something like this (here we're searching for the mceusb driver):

     sudo find /lib -name \*mceusb.ko

Once you find the existing driver, replace it in this fashion (assuming that the existing module is found in the kernel modules tree):

     sudo cp ~/lirc/lirc-0.8.6/drivers/lirc_mceusb/lirc_mceusb.ko \
       /lib/modules/`uname -r`/kernel/ubuntu/lirc/lirc_mceusb

Note that you may also need to replace the lirc_dev module if the new lirc_mceusb module references new symbols in lirc_dev. If that's the case, follow the same steps outlined herein for lirc_mceusb but substitute lirc_dev instead.

Check to see if the original module is loaded by the kernel and, if so, remove it:

     lsmod | grep lirc_mceusb
     sudo rmmod lirc_mceusb

Now, complete the install of the new module on the Mythbuntu machine:

     sudo depmod -a
     sudo insmod \
       /lib/modules/`uname -r`/kernel/ubuntu/lirc/lirc_mceusb/lirc_mceusb.ko

You can check whether the install is successful by doing:

     lsmod | grep lirc_mceusb

After you've completed all of the above, you must make the changes permanent. Mythbuntu boots from a RAM image of the kernel which will still have the old driver (if any) installed and the new driver missing. You need to update this image or the original driver will still get loaded. To update the RAM image:

     sudo update-initramfs -u

Reboot the machine to see if the changes are permanent and that the remote still works:

     sudo reboot

Then, test the updates that you've made accordingly.

Note that for later versions of the kernel and lirc (e.g. 3.2.0 and 0.9.0), mceusb is now one of the kernel drivers. Thus, mceusb.ko is now found in /lib/modules/`uname -r`/kernel/drivers/media/rc and you must build it as a kernel driver instead of as part of lirc. Hopefully, you won't have any need to do so but, if you do, make sure you have the driver build environment (this is not necessarily the full kernel build environment). To verify that you do have the driver build environment, try:

     ls -l /lib/modules/`uname -r`/build

If you have this directory installed, you're good to go (Mythbuntu usually provides them in a typical installation). Otherwise, you'll need to first get the build environment, either using the Package Manager or by doing:

     sudo apt-get install build-essential

Then, you should make sure to install the latest headers for your kernel:

     sudo apt-get install linux-headers-`uname -r`

Finally, if the link doesn't already exist, link the headers to the build folder in the proper place. This should get you compiling:

     sudo ln -s /usr/src/linux-headers-`uname -r` /lib/modules/`uname -r`/build

Download the latest version of the mceusb driver from the kernel sources Web site of your choice and place it in a convenient directory (you can build it in a subdirectory under your home directory, for example lirc_mceusb).

You can find lots of build instructions for kernel drivers on the Internet. Here's a link to a site that covers building the mceusb kernel module:

     http://www.hack-job.org/uncategorized/
          recompile-a-kernel-module-example-mceusb-c/

Apparently, it isn't necessary to place the driver in the system source tree any more, in order to build it (i.e. the way it used to be). Of course, you may opt to do this, if you wish, but we build it in our own directory. To do so, we create this makefile with our favorite editor:

.../lirc_mceusb/Makefile:

     obj-m = mceusb.o
     KVERSION = $(shell uname -r)
     all:
             make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
     clean:
             make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean

Note that the whitespace before each of the indented "make" commands is a single tab, not a bunch of spaces.

Once you have the makefile, you can compile the driver like this:

     cd .../lirc_mceusb
     make

Now, install the mceusb.ko module into the system:

     sudo install -m 744 -c mceusb.ko
          /lib/modules/`uname -r`/kernel/drivers/media/rc

There could be an older version of the module that you are replacing. You can check, for example, if the mceusb module is installed as follows:

     lsmod | grep mceusb

If mceusb is installed then you should remove it:

     sudo rmmod mceusb

Now, complete the install of the new module on the machine:

     sudo depmod -a
     sudo insmod mceusb.ko

You can check whether the install is successful by doing:

     lsmod | grep mceusb

Once you've completed all of the above, you must make the changes permanent. Mythbuntu boots from a RAM image of the kernel which will still have the old driver installed and the new driver missing. You need to update this image or the old driver will still get loaded. To do so, update the RAM image:

     sudo update-initramfs -u

Reboot the machine to make the changes permanent:

     sudo reboot

Then, test the updates that you've made accordingly.

LIRC supports the Tira-2 so Mythbuntu should have support for it built in. You can check whether it does with the following command:

     lircd --driver=?

This will give a list of drivers that are built into the lircd that is installed on the system. If you see "tira", you should be in business and you can skip ahead to the irrecord step, below. However, some versions of Mythbuntu ship without tira being built into LIRC. To remedy this situation, if you don't see the tira driver in the list, you will first need to download the latest LIRC software from http://www.lirc.org/software.html.

Once you've downloaded the software, you can uncompress it and unpack it, then build LIRC with tira enabled:

     cd lirc
     tar -xvjf lirc-0.8.3.tar.bz2
     cd lirc-0.8.3
     ./configure --with-driver=tira
     make

To install the new lircd, become super user and do the install:

     sudo make install

This should put the new lircd in /usr/local/sbin while keeping the original in /usr/sbin -- handy if you need to fall back on the original lircd. You can now skip ahead to the part about using irrecord to record your remote's key codes.

For the Ira-2 or Ira-3 OEM serial IR receivers from Home Electro, the setup is essentially the same as the Tira-2, above. You should check whether Mythbuntu has support for serial devices built in with the following command:

     lircd --driver=?

This will give a list of drivers that are installed on the system. If you see "irman", you should be in business. You can skip ahead to the irrecord step, below. If you don't see the irman driver in the list, in order to get the Ira-2/3 to work, you will first need to download the latest LIRC software from http://www.lirc.org/software.html.

Once you've downloaded the software, you can uncompress it and unpack it, then build LIRC with tira enabled:

     cd lirc
     tar -xvjf lirc-0.8.3.tar.bz2
     cd lirc-0.8.3
     ./configure --with-driver=irman
     make

To install the new lircd, become super user and do the install:

     sudo make install

This should put the new lircd in /usr/local/sbin while keeping the original in /usr/sbin -- handy if you need to fall back on the original lircd. You can now skip ahead to the part about using irrecord to record your remote's key codes.

The Iguana Works USB iguanaIR driver requires a special daemon to operate with LIRC (consider carefully the repercussions on response time and the potential for lockup issues that are implied by this architecture). You can try applying the appropriate RPM or module from their Web site but we have found that we need to compile it ourselves, on Mythbuntu.

To begin with, the daemon needs a whole bunch of prerequisite modules to build properly. On Mythbuntu 9.04, the required modules are:

     python-dev
     libusb-1.0-0
     libusb-1.0-0-dev
     libpopt-dev
     swig

You can install these modules from the Synaptic package manager's GUI or you can use the following command line, once for each package:

     sudo apt-get install pkgname

Once you got all the prerequisites, you can download the latest daemon source from http://iguanaworks.net/downloads.php. After you've done that, uncompress it and unpack it, then build the Iguana daemon:

     cd iguana
     tar -xvjf iguanaIR-1.0pre2.tar.bz2
     cd iguanaIR-1.0pre2
     ./configure
     make

Install the new daemon and other modules into the system:

     sudo make install

At this point, you must reboot, since a new rule is added to /lib/udev/rules.d (named 80-iguanaIR.rules) that creates the /dev/iguanaIR directory and sets its ownership to iguanair:iguanair. This allows the driver to run as user iguanair, not root, which is much safer. However, if you don't reboot, the udev rule will not yet be applied and the next step will fail.

Incidentally, if you experience problems with the responsivness of the remote or just want to be preemptive, you may want to alter the iguanaIR startup script to set the nice level to -3. This will give the daemon a higher priority than other tasks in the system (although a lower priority than the really important ones). Change the lines that set the start parameters as follows:

/etc/init.d/iguanaIR:

.

           .
      # figure out what command to run to start the daemon
      #
      # Set the nice level to -3 so that the remote is more responsive.
      if [ "$LOCKFILE" != "" ]; then 
          if [ ! -e $LOCKFILE ]; then
              START="daemon --user=iguanair -3 $IGPATH $IGUANAIR_OPTIONS \
                  -l $LOGFILE"
          fi
      else
          START="start-stop-daemon --start --chuid iguanair \
              --group iguanair --nicelevel -3 --exec $IGPATH -- \
              $IGUANAIR_OPTIONS -l $LOGFILE"
      fi
           .
           .
           .

Another problem with the startup script is that the Iguana install script sets it up to start in the wrong order. If you use the default installation of LIRC, it will probably start lirc in runlevels 2,3,4,5 at step 19. The Iguana install script sets iguanaIR up to run at step 20. Basically, its a race. Sometimes iguanaIR wins and all is fine. Sometimes lirc beats it to the punch and the remote disappears. Swell.

The fix is to start iguanaIR earlier on, before lirc is even started. You can list the contents of the runlevel 5 directory and see whether the start order is wrong. Enter this command:

     ls -l /etc/rc5.d

If you see:

     /etc/rc5.d/S19lirc --> ./init.d/lirc
     /etc/rc5.d/S20iguanaIR --> ./init.d/iguanaIR

You've got the makings of a race condition. The following commands should fix it:

     sudo rm -f /etc/rc*.d/S20iguanaIR
     sudo ln -s ../init.d/iguanaIR /etc/rc2.d/S15iguanaIR
     sudo ln -s ../init.d/iguanaIR /etc/rc3.d/S15iguanaIR
     sudo ln -s ../init.d/iguanaIR /etc/rc4.d/S15iguanaIR
     sudo ln -s ../init.d/iguanaIR /etc/rc5.d/S15iguanaIR

Note that we picked step 15 in runlevels 2,3,4,5 because there is nothing in between step 15 and step 19 (when lirc is started) that iguanaIR should depend on. If there is, you could change it to start at a later step. You could even move lirc, if you have to. However, starting iguanaIR at step 15 does the trick (eliminating the race) and hasn't caused any side effects as far as we can tell.

Once you've made your changes to the startup script (or not), start up the Iguana daemon:

     sudo /etc/init.d/iguanaIR start

Test it with:

     igclient --receiver-on --sleep 10

You should see commands being sent to the driver and the results being echoed for about 10 seconds, if all is well. If not, proceed to the IguanaWorks troubleshooting page:

     http://iguanaworks.net/projects/IguanaIR/wiki/TroubleShooting

Make sure that the Iguana device driver is started at the proper runlevels (2, 3, 4, and 5). To do this, using the dain-bramaged update-rc.d, run:

     sudo update-rc.d iguanaIR defaults

If you're on a regular system that uses chkconfig, you know what to do.

Now, as noted above for the other drivers, download the latest LIRC software from http://www.lirc.org/software.html, uncompress it and unpack it, then build LIRC with iguanaIR enabled:

     cd lirc
     tar -xvjf lirc-0.8.3.tar.bz2
     cd lirc-0.8.3
     ./configure --with-driver=iguanaIR
     make

To install the new lircd, become super user and do the install:

     sudo make install

Once again, this should put the new lircd in /usr/local/sbin while keeping the original in /usr/sbin where you can get to it if you need to fall back on the original lircd.

Since the new lircd is installed in a different location than the original, we need to modify /etc/init.d/lirc to invoke it. We can choose to do this by adding a new variable called LOAD_PATH that we set to "/usr/local/sbin". We then change all occurrences of /usr/sbin to ${LOAD_PATH}. This lets us change back to the original lircd, if need be.

Also, in some versions of the lirc startup script, it appears that someone forgot about the need to create the /var/run/lirc directory. We can fix this by adding a line in the start routine to create /var/run/lirc.

And, speaking of forgetting things, the hardware.conf file has pointers to two config files, one for the remote and one for the transmitter. Unfortunately, the lircd daemon always loads its config from /etc/lirc/lircd.conf and the two config files pointed to by hardware.conf are ignored. Consequently if you'd like to use two remote config files, one for your actual remote, and one for blasting your cable box, something needs to be done to make up a composite lircd.conf on the fly, using the two named config files (however, you should be careful with this change, if you aren't going to be setting the proper config file name in hardware.conf, since it will break any pre-existing lircd.conf).

Some later versions of lirc create the sockets needed for communication with their client in /var/run/lirc whereas your version of MythTV may expect to find them in /dev. This comes as a huge surprise to MythTV which petulantly refuses to talk to lircd. Consequently, the startup script may need to be modified to always tell lircd to create a pipe named /dev/lircd or /var/run/lirc/lircd instead of where it thinks the pipe should go. Bear this in mind, if all else in your remote setup is perfect and MythTV still won't talk to the remote. The startup script can be made to force the use of one socket name or another, as your MythTV requires.

Finally, you may experience problems with sluggish response from your remote control at times when the system is busy. Since the user typically believes (and who's to argue with them) that the system should always respond promptly to their commands, such sluggish response may not be acceptable. Setting the nice level of lircd to give it a higher priority may help. If you wish to try it, that change can be made in the startup script too.

Here's the complete, modified, startup script:

/etc/init.d/lirc:

     #! /bin/sh
     ### BEGIN INIT INFO
     # Provides:          lirc
     # Required-Start:    $remote_fs $syslog
     # Required-Stop:     $remote_fs $syslog
     # Default-Start:     2 3 4 5
     # Default-Stop:      0 1 6
     # Short-Description: Starts LIRC daemon.
     # Description:       LIRC is used to control different
     #                    infrared receivers and transceivers.
     ### END INIT INFO
     # Where we load lircd and lircmd from.
     LOAD_PATH=/usr/sbin
     # LOAD_PATH=/usr/local/sbin
     # The old name where lirc used to put its socket.  Some programs may still
     # look there.
     #
     # If this variable is defined, a symlink will be made when lircd is started
     # and removed when it is stopped.
     OLD_SOCKET="/dev/lircd"
     load_modules ()
     {
         local MODULES_MISSING=false
      log_daemon_msg "Loading LIRC modules"
      for mod in $*; do
          if [ $mod = "udev" ]; then
              log_end_msg 0
              log_success_msg "Restarted via udev, don't reload modules"
              break
          else
              modprobe $mod 2> /dev/null || MODULES_MISSING=true
          fi
      done
      log_end_msg $?
      if $MODULES_MISSING; then
          log_failure_msg "Unable to load LIRC kernel modules. Verify your"
          log_failure_msg "selected kernel modules in /etc/lirc/hardware.conf"
          START_LIRCMD=false
          START_LIRCD=false
      fi

}

     build_remote_args ()
     {
         local REMOTE_ARGS="$*"
      #For remote only detection support, we need
      #both REMOTE_DEVICE and TRANSMITTER_DEVICE undefined
      if [ -z "$REMOTE_DEVICE" ] && [ -z "$TRANSMITTER_DEVICE" ]; then
          for dev in /dev/lirc0; do
              if [ -c $dev ]; then
                  REMOTE_DEVICE="$dev"
                  break
              fi
          done
      fi
      #If we have a REMOTE_DEVICE or REMOTE_DRIVER defined (either because
      #no devices were defined, OR if we explicitly did), then populate
      #REMOTE_ARGS
      if [ ! -z "$REMOTE_DEVICE" ] || [ ! -z "$REMOTE_DRIVER" ]; then
          if [ -n "$REMOTE_DEVICE" ] && [ "$REMOTE_DEVICE" != "none" ]; then
              REMOTE_ARGS="--device=$REMOTE_DEVICE $REMOTE_ARGS"
          fi
          if [ -n "$REMOTE_DRIVER" ] && [ "$REMOTE_DRIVER" != "none" ]; then
              REMOTE_ARGS="--driver=$REMOTE_DRIVER $REMOTE_ARGS"
          fi
          #Now, if we ALSO have a transmitter defined, add some args
          #To make the first lircd listen up
          if [ ! -z "$TRANSMITTER_DEVICE" ] \
              || [ ! -z "$TRANSMITTER_DRIVER" ]; then
              REMOTE_ARGS="$REMOTE_ARGS --listen"
          fi
          #Because there's some confusion with locally-compiled versions of
          #lircd over what our pipe name is, let's make sure we're all
          #talking on the same one.
          REMOTE_ARGS="$REMOTE_ARGS --output=$REMOTE_SOCKET"
      fi
    
      echo $REMOTE_ARGS

}

     build_transmitter_args ()
     {
         local TRANSMITTER_ARGS="$*"
      #Transmitters must be explicitly be defined
      if [ ! -z "$TRANSMITTER_DEVICE" ] \
          || [ ! -z "$TRANSMITTER_DRIVER" ]; then
          if [ -n "$TRANSMITTER_DEVICE" ] \
              && [ "$TRANSMITTER_DEVICE" != "none" ]; then
              TRANSMITTER_ARGS="--device=$TRANSMITTER_DEVICE $TRANSMITTER_ARGS"
          fi
          if [ -n "$TRANSMITTER_DRIVER" ] \
              && [ "$TRANSMITTER_DRIVER" != "none" ]; then
              TRANSMITTER_ARGS="--driver=$TRANSMITTER_DRIVER $TRANSMITTER_ARGS"
          fi
          # Now, if we ALSO have a remote defined, add some args
          # to make the second lircd connect.
          if [ ! -z "$REMOTE_DEVICE" ] || [ ! -z "$REMOTE_DRIVER" ]; then
              TRANSMITTER_ARGS="$TRANSMITTER_ARGS \
                  --output=$TRANSMITTER_SOCKET --connect=localhost:8765 \
                  --pidfile=/var/run/lircd1.pid"
          # Otherwise, because there's some confusion with locally-compiled
          # versions of lircd over what our pipe name is, let's make sure
          # we're all talking on the same one.
          else
              TRANSMITTER_ARGS="$TRANSMITTER_ARGS --output=$TRANSMITTER_SOCKET"
          fi
      fi
      echo $TRANSMITTER_ARGS

}

     in_kernel_support()
     {
         if [ -d /sys/class/rc ]; then
             for file in `find /sys/class/rc/*/ -name protocols`; do
                 if [ "$1" = "disable" ]; then
                     echo "lirc" > $file
                 else
                     echo "none" > $file
                     for protocol in `cat $file`; do
                         echo "+${protocol}" > $file
                     done
                 fi
             done
         fi
     }
     . /lib/lsb/init-functions
     test -f ${LOAD_PATH}/lircd || exit 0
     test -f ${LOAD_PATH}/lircmd || exit 0
     START_LIRCMD=true
     START_LIRCD=true
     START_IREXEC=true
     if [ -f /etc/lirc/hardware.conf ];then
         . /etc/lirc/hardware.conf
     fi
     # The hardware.conf file has pointers to two config files, one for the
     # remote and one for the transmitter.  Unfortunately, the lircd daemon
     # always loads its config from /etc/lirc/lircd.conf and the two config files
     # pointed to by hardware.conf are ignored.  Nice, huh?  Consequently, we
     # make up lircd.conf on the fly, here, from the two named config files.
     if [ -n "$1" ] && [ "$1" = "start" ]; then
         rm -f /etc/lirc/lircd.conf >/dev/null 2>&1
      if [ -n "$REMOTE_LIRCD_CONF" ] \
          && [ "$REMOTE_LIRCD_CONF" != "none" ]; then
          cat $REMOTE_LIRCD_CONF >/etc/lirc/lircd.conf
          if [ -n "$TRANSMITTER_LIRCD_CONF" ] \
              && [ "$TRANSMITTER_LIRCD_CONF" != "none" ]; then
              cat $TRANSMITTER_LIRCD_CONF >>/etc/lirc/lircd.conf
          fi
      else
          if [ -n "$TRANSMITTER_LIRCD_CONF" ] \
              && [ "$TRANSMITTER_LIRCD_CONF" != "none" ]; then
              cat $TRANSMITTER_LIRCD_CONF >/etc/lirc/lircd.conf
          fi
      fi
      # Here we test to see if anyone has configured the lircd.conf file.  If
      # we made one up (above), it should be configured.  If not, there may
      # be a default one that was put there by install.  It is possible that
       the user configured this file.  If not, we don't start lirc.
      if [ ! -f /etc/lirc/lircd.conf ] \
          || grep -q "^UNCONFIGURED"  /etc/lirc/lircd.conf;then
          if [ "$1" = "start" ]; then
              log_success_msg "No valid /etc/lirc/lircd.conf has been found."
              log_success_msg "Remote control support has been disabled."
              log_success_msg "Reconfigure LIRC or manually replace \
                  /etc/lirc/lircd.conf to enable."
          fi
          START_LIRCD=false
          START_LIRCMD=false
          START_IREXEC=false
      fi

fi

     # Here we test to see if anyone has configured the lircmd.conf file.  If
      not, we don't start lircmd.
     if [ ! -f /etc/lirc/lircmd.conf ] \
         || grep -q "^UNCONFIGURED" /etc/lirc/lircmd.conf; then
         START_LIRCMD=false
     fi
     # Here we test to see if anyone has configured the lircrc.conf file.  If
      not, we don't start irexec.
     if [ ! -f /etc/lirc/lircrc ] \
         || grep -q "^UNCONFIGURED" /etc/lirc/lircrc; then
         START_IREXEC=false
     fi
     # The user can define which pipe path to use.  The default is /var/run/lirc
     # but this can be overridden.
     if [ -n "$PIPE_PATH" ] && [ "$PIPE_PATH" != "none" ]; then
         OUTPUT_PATH=$PIPE_PATH
     else
         OUTPUT_PATH="/var/run/lirc"
     fi
     # The user can define what socket names to use.  The defaults are "lirc"
     # and "lirc1".
     if [ -z "$REMOTE_SOCKET" ]; then
         REMOTE_SOCKET="${OUTPUT_PATH}/lircd"
     else
         REMOTE_SOCKET="${OUTPUT_PATH}/${REMOTE_SOCKET}"
     fi
     if [ -z "$TRANSMITTER_SOCKET" ]; then
         TRANSMITTER_SOCKET="${OUTPUT_PATH}/lircd"
      # Now, if we ALSO have a remote defined, change the default
      # transmitter socket.
      if [ ! -z "$REMOTE_DEVICE" ] || [ ! -z "$REMOTE_DRIVER" ]; then
          TRANSMITTER_SOCKET="${TRANSMITTER_SOCKET}1"
      fi
  else
      TRANSMITTER_SOCKET="${OUTPUT_PATH}/${TRANSMITTER_SOCKET}"

fi

     # Process the command given to this script (e.g. start, stop).
     case "$1" in
      # Start up all of the daemons.
      start)
          if [ "$LOAD_MODULES" = "true" ] && [ "$START_LIRCD" = "true" ]; then
              load_modules $2 $REMOTE_MODULES $TRANSMITTER_MODULES $MODULES
              in_kernel_support "disable"
          fi
          # If we're starting the lirc daemon, do it now.
          if [ "$START_LIRCD" = "true" ]; then
              # If the socket/pid directory isn't there, create it.
              if [ ! -d $OUTPUT_PATH ]; then
                  mkdir -p $OUTPUT_PATH >/dev/null 2>&1
              fi
              log_daemon_msg "Starting remote control daemon(s) : LIRC "
              REMOTE_LIRCD_ARGS=`build_remote_args $REMOTE_LIRCD_ARGS`
              TRANSMITTER_LIRCD_ARGS=`build_transmitter_args \
                  $TRANSMITTER_LIRCD_ARGS`
              # If we have a remote defined, it is the primary process
              #
              # We'll set the nice level of this process so that the remote
              # control is more responsive.
              if [ ! -z "$REMOTE_LIRCD_ARGS" ]; then
                  start-stop-daemon --start --quiet --nicelevel -5 \
                      --exec ${LOAD_PATH}/lircd -- $REMOTE_LIRCD_ARGS \
                      </dev/null
                  log_end_msg $?
                  # If an old socket is named, symlink it to the one that lirc
                  # is using now.  Note that, because of the "&&", the symlink
                  # is only put in if the old socket exists.
                  if [ -S "$REMOTE_SOCKET" \
                      -a "$OLD_SOCKET" != "$REMOTE_SOCKET" ]; then
                      rm -f $OLD_SOCKET \
                          && ln -s $REMOTE_SOCKET $OLD_SOCKET
                  fi
                  # Now, if we additionally have a transmitter defined, it
                  # is secondary process.
                  if [ ! -z "$TRANSMITTER_LIRCD_ARGS" ]; then
                      ${LOAD_PATH}/lircd $TRANSMITTER_LIRCD_ARGS < /dev/null
                      # If an old socket is named, symlink it to the one that
                      # lirc is using now.  Note that, because of the "&&",
                      # the symlink is only put in if the old socket exists.
                      if [ -S "$TRANSMITTER_SOCKET" ]; then
                          rm -f ${OLD_SOCKET}1 \
                              && ln -s $TRANSMITTER_SOCKET ${OLD_SOCKET}1
                      fi 
                  fi
              # Otherwise, if there's a transmitter defined, it is the
              # primary process.
              elif [ ! -z "$TRANSMITTER_LIRCD_ARGS" ]; then
                  start-stop-daemon --start --quiet \
                      --exec ${LOAD_PATH}/lircd -- $TRANSMITTER_LIRCD_ARGS \
                      </dev/null
              # Otherwise, we're done.
              else
                  log_end_msg 1
              fi
          fi
          # If we're starting the mouse daemon, do it now.
          if [ "$START_LIRCMD" = "true" ]; then
              # If the socket/pid directory isn't there, create it.
              if [ ! -d $OUTPUT_PATH ]; then
                  mkdir -p $OUTPUT_PATH >/dev/null 2>&1
              fi
              log_daemon_msg "Starting remote control mouse daemon : LIRCMD "
              start-stop-daemon --start --quiet \
                  --exec ${LOAD_PATH}/lircmd </dev/null
              log_end_msg $?
          fi
          # If we're starting the execution daemon, do it now.
          if [ "$START_IREXEC" = "true" ]; then
              # If the socket/pid directory isn't there, create it.
              if [ ! -d $OUTPUT_PATH ]; then
                  mkdir -p $OUTPUT_PATH >/dev/null 2>&1
              fi
              log_daemon_msg "Starting execution daemon: irexec"
              start-stop-daemon --start --quiet --oknodo \
                  --exec ${LOAD_PATH}/irexec -- -d /etc/lirc/lircrc \
                  </dev/null
              log_end_msg $?
          fi
          ;;
      # Shut down all of the daemons.
      stop)
          in_kernel_support "enable"
          # If we're started the execution daemon, do it now.
          if [ "$START_IREXEC" = "true" ]; then
              log_daemon_msg "Stopping execution daemon: irexec"
              start-stop-daemon --stop --quiet --exec ${LOAD_PATH}/irexec
              log_end_msg $?
          fi
          # If we're started the mouse daemon, do it now.
          if $START_LIRCMD; then
              log_daemon_msg "Stopping remote control mouse daemon: LIRCMD"
              start-stop-daemon --stop --quiet --exec ${LOAD_PATH}/lircmd
              log_end_msg $?
          fi
          # If we're started the lirc daemon, do it now.
          if $START_LIRCD; then
              log_daemon_msg "Stopping remote control daemon(s): LIRC"
              start-stop-daemon --stop --quiet --exec ${LOAD_PATH}/lircd
              log_end_msg $?
          fi
          ;;
      # Reload signals all of the daemons to reload their config.
      reload|force-reload)
          if [ "$START_IREXEC" = "true" ]; then
              start-stop-daemon --stop --quiet --signal 1 \
                  --exec ${LOAD_PATH}/irexec
          fi
          if [ "$START_LIRCD" = "true" ]; then
              start-stop-daemon --stop --quiet --signal 1 \
                  --exec ${LOAD_PATH}/lircd
          fi
          if $START_LIRCMD; then
              start-stop-daemon --stop --quiet --signal 1 \
                  --exec ${LOAD_PATH}/lircmd
          fi
          ;;
      # Restarts the service by shutting everything down and then starting
      # it back up.
      #
      # Note that, when we restart, we pass parameter $2, which is possibly
      # our udev paramater.
      restart)
          $0 stop
          $0 start $2
          ;;
      *)
          echo "Usage: /etc/init.d/lircd {start|stop|reload|restart|\
              force-reload}"
          exit 1

esac

     exit 0

For later versions of Mythbuntu, many of the services that are necessary to run the system have been migrated to upstart. Fortunately for us, as of Mythbuntu 12.04, this hasn't happened to LIRC yet. So, the script that is shown above can still be used with the latest Mythbuntu. As a matter of fact, you can probably just use the LIRC that is pre-installed on the system (no need to build the latest one because the OS probably comes with the latest one). To do this, you simply have to switch the load path as follows:

     # Where we load lircd and lircmd from.
     LOAD_PATH=/usr/sbin
     # LOAD_PATH=/usr/local/sbin

If your system already had the appropriate driver built into lircd or you've successfully installed the updated LIRC software, its time to record all of the key codes that are generated by the remote that you wish to use with Mythbuntu. These steps are repeated for each remote that you wish to use or every time that you add a new remote.

Begin by making sure that lircd is not running (if you are not doing this for the first time) and then record the buttons as follows (picking the appropriate invocation of irrecord, depending on which IR receiver you are using, and being sure to use the correct installation of irrecord, if you built the source from scratch):

     [sudo /etc/init.d/lirc stop]
     sudo irrecord -n MCEUSB_myremote.conf
     sudo irrecord -n -H tira -d /dev/ttyUSB0 Tira-2_myremote.conf
     sudo irrecord -n -H irman -d /dev/ttyS0 Ira_myremote.conf
     sudo irrecord -n -H iguanaIR -d /dev/iguanaIR/0 Iguana_myremote.conf

If you have problems with irrecord recognizing the keys on your remote, you can run it in raw mode and then deal with the problems post-facto:

     [sudo /etc/init.d/lirc stop]
     sudo irrecord -f -n MCEUSB_myremote.conf
     sudo irrecord -f -n -H tira -d /dev/ttyUSB0 Tira-2_myremote.conf
     sudo irrecord -f -n -H irman -d /dev/ttyS0 Ira_myremote.conf
     sudo irrecord -f -n -H iguanaIR -d /dev/iguanaIR/0 Iguana_myremote.conf

Essentially, once you're running irrecord, you should follow its instructions. Be sure to carry out the first steps exactly (i.e. keep pressing keys or holding down a single key, as it instructs, until it tells you to stop) so that the correct gap is found and irrecord figures out how to decode the raw data. Also, at the end, press a single key rapidly so that the toggle bits can be figured out. If you fail to do these tasks properly, the remote will not be set up correctly.

Incidentally, there may be a problem when some remotes are being recorded by some IR receivers (e.g. the Sony TiVo remotes with any of the irman serial receivers). In these cases, irrecord asks you to press and hold a single key until it can figure out the correct gap. However, this depends on the remote's key being typematic (i.e. repeats automatically at a rapid rate, when held). If the "arbitrary" key that you hold down isn't typematic or doesn't repeate at a fast enough rate, irrecord won't be able to figure things out. To get it to work, you need to pick a key that is typematic and repeats fast enough (you should see a good stream of dots forming in short order). Often, the volume controls on a remote (if it has them) are typematic and work quite well when irrecord asks you to hold down an "arbitrary" key.

Once the initial phase of remote setup is completed, irrecord proceeds to capturing each of the remote's key codes. For each of the keys, you enter the key name on the computer's keyboard, press the enter key, and then press the remote's key and hold it until irrecord can identify its key code and record it. Try to give the keys meaningful names that can be used in the various LIRC config files.

If you want the remote to work with other applications (especially the script that auto-generates the MythTV config files -- you'll thank me for this later), pick the common key names from this list:

     ArrowDown
     ArrowLeft
     ArrowRight
     ArrowUp
     ChannelUp
     ChannelDown
     Eight  (the number 8)
     Enter
     Exit
     Five  (the number 5)
     Forward
     Four  (the number 4)
     Guide
     Home
     Info
     List
     Menu
     Mute
     Nine  (the number 9)
     One  (the number 1)
     Pause
     Play
     Power
     Record
     Replay
     Return
     Rewind
     Seven  (the number 7)
     Six  (the number 6)
     Skip
     Stop
     Three  (the number 3)
     Two  (the number 2)
     VolumeDown
     VolumeUp
     Zero  (the number 0)

For other keys that don't appear on this list, you can examine one or more .lircrc files (e.g. for your favorite application) to see what names are common. The names that you choose will be used to map the LIRC keypress codes to your application's control commands so making them meaningful is a good idea. Also, it is best to know what names you'll be using for all of the remote's keys before you begin so that you won't have to go looking once you start. Just for the sake of having a plan, I usually start with the top-left key on the remote and work my way down to the bottom-right so having the key names printed out in that order is helpful.

Once you have recorded your remote or remotes, you should join all of the config files together, for all of the remotes that you wish to use simultaneously, into a single lircd.conf file in /etc/lirc. It should look something like this (let's assume we want to use either the Sony or the Philips TiVo remote, or the Samsung TV remote to run Mythbuntu, depending on which one is closer to hand):

/etc/lirc/lircd.conf:

     # ========================  Tira-2_TiVoSony.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.3(tira) on Thu May 15 13:21:08 2008
     #
     # contributed by: xxx@yyy.com (Xxx Yyy)
     #
     # brand: Home Electro Tira-2 xceiver
     # model no. of remote control: TiVo (Sony) (RMT-V303)
     # devices being controlled by this remote: MythTV (Mythbuntu)
     #
     begin remote
     name  TiVoSony
     bits           48
     eps            30
     aeps          100
     one             0     0
     zero            0     0
     pre_data_bits   8
     pre_data       0x0
     post_data_bits  8
     post_data      0x0
     gap          149967
     toggle_bit_mask 0x0
        begin codes
            Power                    0xC0FF49BF5EC3
            TVPower                  0xFF3C75000000  # Programmable by user
            Menu                     0xC003748C5DC3  # TiVo logo on button
            Guide                    0xC0C3B7735DC3
            List                     0xC00F874F5DC3
            UpArrow                  0xC0F348835DC3
            DownArrow                0xC003964352C3
            LeftArrow                0xC003974F51C3
            RightArrow               0xC00386735EC3
            Select                   0xC0F358B351C3
            ThumbsDown               0xC0C3B67F5EC3
            ThumbsUp                 0xC0C3A64F52C3
            Mute                     0xFF3F65000000  # TiVo logo on button
            Record                   0xC0FF8A8F5EC3
            Play                     0xC0FFAB7051C3
            Back                     0xC0FFBB405DC3
            Forward                  0xC0FF9ABF52C3
            Pause                    0xC0FFBA4C5EC3
            Slow                     0xC00F447F5DC3
            Replay                   0xC0F378405DC3
            Skip                     0xC0C3A74351C3
            VolumeUp                 0xFF3F54000000  # TiVo logo on button
            VolumeDown               0xFF3F44000000  # TiVo logo on button
            ChannelUp                0xC0FF694C52C3
            ChannelDown              0xC0FF797C5EC3
            One                      0xC03F594052C3
            Two                      0xC03F49705EC3
            Three                    0xC03F584C51C3
            Four                     0xC03F487C5DC3
            Five                     0xC03F698352C3
            Six                      0xC03F79B35EC3
            Seven                    0xC03F688F51C3
            Eight                    0xC03F78BF5DC3
            Nine                     0xC03F9A7052C3
            Zero                     0xC03F8A405EC3
            Clear                    0xC003877F5DC3
            Enter                    0xC03F8B4C5DC3
        end codes
     end remote
     # =======================  Tira-2_TiVoPhilips.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.3(tira) on Thu May 15 06:22:55 2008
     #
     # contributed by: xxx@yyy.com (Xxx Yyy)
     #
     # brand: Home Electro Tira-2 xceiver
     # model no. of remote control: TiVo (Philips) Peanut (SBOM-00004-000)
     # devices being controlled by this remote: MythTV (Mythbuntu)
     #
     begin remote
     name  TiVoPhilips
     bits           48
     eps            30
     aeps          100
     one             0     0
     zero            0     0
     pre_data_bits   8
     pre_data       0x0
     post_data_bits  8
     post_data      0x0
     gap          207966
     min_repeat      2
     toggle_bit_mask 0x0
        begin codes
            Power                    0xFF3C75000000  # Programmable by user
            Menu                     0xA914FDFF5FFF  # TiVo logo on button
            Guide                    0x29147D7F5FFF
            UpArrow                  0x29147DF75FFF
            DownArrow                0x29147DD75FFF
            LeftArrow                0x29147D575FFF
            RightArrow               0x29147D775FFF
            Select                   0x29147D7D5FFF
            ThumbsDown               0x29147DFD5FFF
            ThumbsUp                 0x29147DDD5FFF
            Mute                     0xFF3C65000000  # Programmable by user
            Record                   0x8914DDFF5FFF
            Play                     0x8914DD7F5FFF
            Back                     0x8914DDDF5FFF
            Forward                  0x8914DDF75FFF
            Pause                    0x8914DD5F5FFF
            Slow                     0x8914DD775FFF
            Replay                   0x8914DDD75FFF
            Skip                     0x8914DD575FFF
            VolumeUp                 0xFF3C54000000  # Programmable by user
            VolumeDown               0xFF3C44000000  # Programmable by user
            ChannelUp                0x29147DD55FFF
            ChannelDown              0x29147D555FFF
            One                      0x8914DDFD5FFF
            Two                      0x8914DD7D5FFF
            Three                    0x8914DDDD5FFF
            Four                     0x8914DD5D5FFF
            Five                     0x8914DDF55FFF
            Six                      0x8914DD755FFF
            Seven                    0x8914DDD55FFF
            Eight                    0x8914DD555FFF
            Nine                     0x09145DFF5FFF
            Zero                     0x09145D7F5FFF
            Clear                    0x09145DDF5FFF
            Enter                    0x09145D5F5FFF
        end codes
     end remote
     # =====================  Tira-2_SamsungLN32A450.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.4a(tira) on Sat Jan 23 19:28:51 2010
     #
     # contributed by: xxx@yyy.com (Xxx Yyy)
     #
     # brand: Home Electro USB Tira-2
     # model no. of remote control: Samsung LN32A450 TV (BN59-00687A)
     # devices being controlled by this remote: MythTV (Mythbuntu)
     #
     # Codes marked with "x" should not be used because the display interprets
     # them under all conditions (e.g. Power).
     #
     # Codes marked with "*" can be used but the display pops up an annoying
     # idiot message about the key not being available right now.  These keys
     # are good for displaying things like the OSD (i.e. something that will
     # hang around for awhile until the annoying message goes away).
     #
     # Codes marked with "M" work OK but they actually do something when the
     # Menu button is pressed and the Menu is displayed.  If you map these keys,
     # you probably should exit your application before you enter the display's
     # Menu.
     #
     begin remote
     name  SamsungLN32A450
     bits            48
     eps             30
     aeps            100
     one             0     0
     zero            0     0
     pre_data_bits   8
     pre_data        0x0
     post_data_bits  8
     post_data       0x0
     gap             207962
     min_repeat      1
     toggle_bit_mask 0x0
        begin codes
            Power                    0xFF17FC9FFF07    # x
            TVMode                   0x7F907D18FE07    # x
            Source                   0xFFF7FD7FFE07    # x
            One                      0xFF6FFCE7FF07    # *
            Two                      0xFFEFFD67FE07    # *
            Three                    0xFF0FFC87FF07    # *
            Four                     0xFF71FCF9FF07    # *
            Five                     0xFFF1FD79FE07    # *
            Six                      0xFF11FC99FF07    # *
            Seven                    0xFF69FCE1FF07    # *
            Eight                    0xFFE9FD61FE07    # *
            Nine                     0xFF09FC81FF07    # *
            Zero                     0x7FF67D7EFE07    # *
            Minus                    0x9F979D1FFE07    # *
            Previous                 0x7F967D1EFE07    # *  - Pre-Ch button
            VolumeUp                 0xFF8FFD07FE07    # x
            VolumeDown               0xFF91FD19FE07    # x
            Mute                     0xFF89FD01FE07    # x
            ChannelUp                0x7F167C9EFF07    # x
            ChannelDown              0x7F767CFEFF07    # x
            List                     0x87918519FE07    # *  - Ch. List button
            Menu                     0x7F107C98FF07    # x
            ClosedCaption            0x9FEF9D67FE07    # *  - CC button
            Tools                    0xE791E519FE07    # x  - Tools button
            Info                     0x7F887D00FE07    # x
            Return                   0x677064F8FF07    # M  - Return button
            Exit                     0x9FE99D61FE07    # xM
            ArrowUp                  0x877784FFFF07    # M  - In circular
                                                       #       button cluster
            ArrowDown                0x87F7857FFE07    # M
            ArrowLeft                0x87EF8567FE07    # M
            ArrowRight               0x8717849FFF07    # M
            Enter                    0x877184F9FF07    # M
            Red                      0x876984E1FF07    # Red button
            Green                    0x7F6E7CE6FF07    # Green button
            Yellow                   0x7FEE7D66FE07    # Yellow button
            Blue                     0x7F0E7C86FF07    # Blue button
            SRSButton                0x87098481FF07    # x  - SRS button
            MTSButton                0xFF77FCFFFF07    # x  - MTS button
            DMAButton                0x8797851FFE07    # x  - DMA button
            EMode                    0x796E7AE6FF07    # x  - E. Mode button
            PSize                    0x1F081C80FF07    # x  - P. Size button
            FavoriteChannel          0xE76FE4E7FF07    # x  - Fav. Ch. button
            Rewind                   0xE7EFE567FE07
            Pause                    0xE711E499FF07
            FastForward              0xE771E4F9FF07
            Record                   0xE7F1E579FE07
            Play                     0xE78FE507FE07
            Stop                     0xE70FE487FF07
        end codes
     end remote

As long as the codes are different for each remote, you can have as many remotes defined as you want. LIRC will figure out which one is being used by the codes that it receives. Thus, you can control one system with several remotes, if you're that ambitious.

LIRC needs a hardware configuration file to tell it what remote and IR blaster drivers to use, etc. This file should be set up now and should look something like this (the combined file, above, is used with a USB Tira-2):

/etc/lirc/hardware.conf:

     # /etc/lirc/hardware.conf
     #
     #Chosen Remote Control
     REMOTE="Combined"
     REMOTE_MODULES=""
     REMOTE_DRIVER="tira"
     REMOTE_DEVICE="/dev/ttyUSB0"
     REMOTE_LIRCD_CONF="/etc/lirc/lircd.conf"
     REMOTE_LIRCD_ARGS=""
     #Chosen IR Transmitter
     TRANSMITTER="None"
     TRANSMITTER_MODULES=""
     TRANSMITTER_DRIVER=""
     TRANSMITTER_DEVICE=""
     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="false"
     # Default configuration files for your hardware if any
     LIRCMD_CONF=""
     #Forcing noninteractive reconfiguration
     #If lirc is to be reconfigured by an external application
     #that doesn't have a debconf frontend available, the noninteractive
     #frontend can be invoked and set to parse REMOTE and TRANSMITTER
     #It will then populate all other variables without any user input
     #If you would like to configure lirc via standard methods, be sure
     #to leave this set to "false"
     FORCE_NONINTERACTIVE_RECONFIGURATION="false"
     START_LIRCMD=""

As another example, the hardware.conf file for a Samsung LN32A450 remote, used with a USB IguanaIR, should include this section for the remote:

     #Chosen Remote Control
     REMOTE="SamsungLN32A450"
     REMOTE_MODULES=""
     REMOTE_DRIVER="iguanaIR"
     REMOTE_DEVICE="/dev/iguanaIR/0"
     REMOTE_LIRCD_CONF="/etc/lirc/lircd.conf"
     REMOTE_LIRCD_ARGS=""

Finally, in this example a singel Philips TiVo remote is used with a serial Ira:

     #Chosen Remote Control
     REMOTE="TiVoPhilips"
     REMOTE_MODULES=""
     REMOTE_DRIVER="irman"
     REMOTE_DEVICE="/dev/ttyS0"
     REMOTE_LIRCD_CONF="/etc/lirc/lircd.conf"
     REMOTE_LIRCD_ARGS=""

If you want, you can give your config files meaningful names, based on the remote or class of remotes that they represent and then copy those files to the /etc/lirc directory, whereupon they can be symlinked to the proper file names. For example:

     sudo ln -s Ira_TiVoPhilips-hardware.conf hardware.conf
     sudo ln -s TiVoRemotes-lircd.conf lircd.conf

Incidentally, if you made the modifications to /etc/init.d/lirc, mentioned above, to allow the hardware.conf file to correctly specify which lircd config file should be used for the receiver and transmitter, you can have descriptions for the same remote under different receivers, in different files, and select them in the config file. For example, here's the same Samsung LN34A450 remote (shown in the combined file, above) as it would appear to an Iguana Works receiver:

/etc/lirc/IguanaIR_SamsungLN32A450.conf:

     # ====================  IguanaIR_SamsungLN32A450.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.6(iguanaIR) on Fri Jan 22 14:30:37 2010
     #
     # contributed by: xxx@yyy.com (Xxx Yyy)
     #
     # brand: Iguana Works USB iguanaIR
     # model no. of remote control: Samsung LN32A450 TV (BN59-00687A)
     # devices being controlled by this remote: MythTV (Mythbuntu)
     #
     # Codes marked with "x" should not be used because the display interprets
     # them under all coditions (e.g. Power).
     #
     # Codes marked with "*" can be used but the display pops up an annoying
     # idiot message about the key not being available right now.  These keys
     # are good for displaying things like the OSD (i.e. something that will
     # hang around for awhile until the annoying message goes away).
     #
     # Codes marked with "M" work OK but they actually do something when the
     # Menu button is pressed and the Menu is displayed.  If you map these keys,
     # you probably should exit your application before you enter the display's
     # Menu.
     #
     begin remote
     name  SamsungLN32A450
     bits            16
     flags           SPACE_ENC
     eps             30
     aeps            100
     header          4529 4418
     one             586  1625
     zero            586  498
     ptrail          585
     pre_data_bits   16
     pre_data        0xE0E0
     gap             46780
     min_repeat      1
     toggle_bit_mask 0x0
        begin codes
            Power                    0x40BF    # x
            TVMode                   0xD827    # x
            Source                   0x807F    # x
            One                      0x20DF    # *
            Two                      0xA05F    # *
            Three                    0x609F    # *
            Four                     0x10EF    # *
            Five                     0x906F    # *
            Six                      0x50AF    # *
            Seven                    0x30CF    # *
            Eight                    0xB04F    # *
            Nine                     0x708F    # *
            Zero                     0x8877    # *
            Minus                    0xC43B    # *
            Previous                 0xC837    # *  - Pre-Ch button
            VolumeUp                 0xE01F    # x
            VolumeDown               0xD02F    # x
            Mute                     0xF00F    # x
            ChannelUp                0x48B7    # x
            ChannelDown              0x08F7    # x
            List                     0xD629    # *  - Ch. List button
            Menu                     0x58A7    # x
            ClosedCaption            0xA45B    # *  - CC button
            Tools                    0xD22D    # x  - Tools button
            Info                     0xF807    # x
            Return                   0x1AE5    # M  - Return button
            Exit                     0xB44B    # xM
            ArrowUp                  0x06F9    # M  - In circular button
                                               #      cluster
            ArrowDown                0x8679    # M
            ArrowLeft                0xA659    # M
            ArrowRight               0x46B9    # M
            Enter                    0x16E9    # M
            Red                      0x36C9    # Red button
            Green                    0x28D7    # Green button
            Yellow                   0xA857    # Yellow button
            Blue                     0x6897    # Blue button
            SRSButton                0x7689    # x  - SRS button
            MTSButton                0x00FF    # x  - MTS button
            DMAButton                0xC639    # x  - DMA button
            EMode                    0x29D6    # x  - E. Mode button
            PSize                    0x7C83    # x  - P. Size button
            FavoriteChannel          0x22DD    # x  - Fav. Ch. button
            Rewind                   0xA25D
            Pause                    0x52AD
            FastForward              0x12ED
            Record                   0x926D
            Play                     0xE21D
            Stop                     0x629D
        end codes
     end remote

The modified /etc/init.d/lirc, mentioned above, allows the hardware.conf file to correctly specify that the Iguana lircd config file should be used for the receiver, like this:

     #Chosen Remote Control
     REMOTE="SamsungLN32A450"
     REMOTE_MODULES=""
     REMOTE_DRIVER="iguanaIR"
     REMOTE_DEVICE="/dev/iguanaIR/0"
     REMOTE_LIRCD_CONF="/etc/lirc/IguanaIR_SamsungLN32A450.conf"
     REMOTE_LIRCD_ARGS=""

After your hardware configuration file is all set, you can restart the LIRC daemon and test whether your remote is being mapped properly:

     sudo /etc/init.d/lirc start
     sudo irw

As long as irw is running, you should see the names of each of the keys that you press on the remote echoed on the display.

Now, you should go to the Infrared Devices configuration page that is found under the Applications/System/Mythbuntu Control Center menu on the Mythbuntu desktop. Here you can select Enable A Remote Cotrol and pick the Custom remote, and optionally select Enable An IR Transmitter and pick the Custom IR blaster. Uncheck the box to Generate Dynamic Button Mappings. After you apply these changes, this should get MythTV listening to the remote.

The last step is to generate mappings for all of the applications, that you'll be using the remote with. Each mapping translates the key names, that you gave to each of the remote's keys, to the actions that are actually to be carried out in the application. In Mythbuntu, there is a slick little application that uses common key names (i.e. the ones that were suggested above) as input to create the key mappings for all of the Mythbuntu applications automatically. To use it, do the following:

     [Make sure you're logged in as the user that runs Mythbuntu]
     cd ~/
     mythbuntu-lircrc-generator

This will generate mapping files for all of the Mythbuntu applications in the ~/.lirc directory. If the remote then works perfectly with the generated mapping files, well and good. Be sure to test it with any and all of the following applications that you use:

     elisa
     mplayer
     mythtv
     totem
     vlc
     xine
     xmame
     xmess

If the remote does not work perfectly (what are the chances of that), you may wish to hack the files in the ~/.lirc directory. Begin by deleting any remote keys that are needed to operate other devices (e.g. the TV/Display). Here is a list of suggested keys to delete:

     ChannelDown
     ChannelUp
     Menu
     Mute
     VolumeDown
     VolumeUp

Next, you might want to add or remap the special keys that mean so much to your application (e.g. for MythTV, the commercial skip key is always a winner). Do this in consultation with your application's key/command table and a list of the remote's keys (or, you can just look at the remote). Here we show, by way of example, hacks made to the mythtv mapping file for a Sony TiVo remote:

~/.lirc/mythtv:

     Most of the generated key mappings are OK but, for the TiVo remote, you may
     want to add the missing keys like this:
     begin
         remote = TiVoSony
         prog = mythtv
         button = List
         config = I
         repeat = 0
         delay = 0
     end
     begin
         remote = TiVoSony
         prog = mythtv
         button = Select
         config = Return
         repeat = 0
         delay = 0
     end
     begin
         remote = TiVoSony
         prog = mythtv
         button = ThumbsDown
         config = W
         repeat = 0
         delay = 0
     end
     begin
         remote = TiVoSony
         prog = mythtv
         button = ThumbsUp
         config = C
         repeat = 0
         delay = 0
     end
     begin
         remote = TiVoSony
         prog = mythtv
         button = Back
         config = <
         repeat = 0
         delay = 0
     end
     begin
         remote = TiVoSony
         prog = mythtv
         button = Slow
         config = J
         repeat = 0
         delay = 0
     end
     begin
         remote = TiVoSony
         prog = mythtv
         button = Clear
         config = Esc
         repeat = 0
         delay = 0
     end

If we also wanted the Philips TiVo remote to control MythTV, here are the additional hacks made to the mythtv mapping file for a that remote:

~/.lirc/mythtv:

     Most of the generated key mappings are OK but, for the TiVo remote, you may
     want to add the missing keys like this:
     begin
         remote = TiVoPhilips
         prog = mythtv
         button = List
         config = I
         repeat = 0
         delay = 0
     end
     begin
         remote = TiVoPhilips
         prog = mythtv
         button = Select
         config = Return
         repeat = 0
         delay = 0
     end
     begin
         remote = TiVoPhilips
         prog = mythtv
         button = ThumbsDown
         config = W
         repeat = 0
         delay = 0
     end
     begin
         remote = TiVoPhilips
         prog = mythtv
         button = ThumbsUp
         config = C
         repeat = 0
         delay = 0
     end
     begin
         remote = TiVoPhilips
         prog = mythtv
         button = Back
         config = <
         repeat = 0
         delay = 0
     end
     begin
         remote = TiVoPhilips
         prog = mythtv
         button = Slow
         config = J
         repeat = 0
         delay = 0
     end
     begin
         remote = TiVoPhilips
         prog = mythtv
         button = Clear
         config = Esc
         repeat = 0
         delay = 0
     end

You could actually have the identical keys on the two remotes mapped to different functions, if you want, but there's no percentage in that. We're just pointing out that, because there's a set of mappings for each remote that can generate keys (from the lircd config file), each remote's keys can be handled in whatever way you see fit.

Anyway, here we show, by way of another example, the complete key mapping file for a Samsung LN32A450 remote. This remote comes with the LN32A450 display/TV and is normally meant to be used to control the TV. We'd like to only use one remote for watching Myth TV so we take over some of the TV remote's keys to control MythTV, thereby giving the user a single remote solution to MythTV and their display. Here's the mapping file:

~/.lirc/mythtv:

     # LIRCRC Auto Generated by Mythbuntu Lirc Generator
     # Author(s): Mario Limonciello, Nick Fox
     # Created for use with Mythbuntu
     #
     # Changed to reflect actual usage of the remote-ski.
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = One
         config = 1
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Two
         config = 2
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Three
         config = 3
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Four
         config = 4
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Five
         config = 5
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Six
         config = 6
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Seven
         config = 7
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Eight
         config = 8
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Nine
         config = 9
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Zero
         config = 0
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Previous
         config = I
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = List
         config = M
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = ClosedCaption
         config = T
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Return
         config = Escape
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = ArrowUp
         config = Up
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = ArrowDown
         config = Down
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = ArrowLeft
         config = Left
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = ArrowRight
         config = Right
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Enter
         config = Return
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Red
         config = W
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Green
         config = Q
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Yellow
         config = Z
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Rewind
         config = <
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Pause
         config = P
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = FastForward
         config = >
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Record
         config = Space
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Play
         config = P
         repeat = 0
         delay = 0
     end
     begin
         remote = SamsungLN32A450
         prog = mythtv
         button = Stop
         config = Escape
         repeat = 0
         delay = 0
     end

The best technique for building mapping files is to work your way through all of the keys in the appropriate LIRC config file for the remote and make sure that each key is mapped to something. You can also check that each key is only mapped once but this isn't a hard and fast rule (e.g. you might map both the Pause and Stop keys to a single command in MythTV, since the both do the same thing in that application).

All of the other files in the ~/.lirc directory may need hacking too, if you use the applications associated with them.