Infrared Remote Control

The Silverstone LC11M case comes equipped with a built in version of the Soundgraph iMon VFD/PAD, the device was seen on the USB bus

[root@localhost ~]# lsusb
...
Bus 001 Device 003: ID 15c2:ffdc SoundGraph Inc. iMON PAD Remote Controller
...

This device is supported by drivers for LIRC which is distributed in Fedora Extras, so I installed that and then discovered that the kernel modules are not built as they can't be shipped in extras.

So I installed kernel-devel and the source for lirc, then configured it for the iMon, I had to make one fix to build the drivers, unfortunately when doing a modprobe lirc_imon the driver caused a kernel oops.

lirc_dev: IR Remote Control driver registered, at major 61
lirc_imon: no version for "lirc_unregister_plugin" found: kernel tainted.
/usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: Driver for Soundgraph iMON MultiMedian IR/VFD, v0.3
/usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: Venky Raju <dev@venky.ws>
/usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: imon_probe: found IMON device
lirc_dev: lirc_register_plugin: sample_rate: 0
Unable to handle kernel NULL pointer dereference at virtual address 00000000
 printing eip:
c01f5483
*pde = 253c9001
Oops: 0000 [#1]
SMP
Modules linked in: lirc_imon(U) lirc_dev(U) radeon drm ipv6 lp autofs4 lm85 hwmon_vid hwmon eeprom rfcomm l2cap bluetooth sunrpc iptable_filter ip_tables video button battery ac parport_pc parport yealink ov511 e100 ohci1394 mii ieee1394 saa7134 video_buf v4l2_common v4l1_compat
ir_kbd_i2c ir_common videodev snd_hda_intel snd_hda_codec snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss snd_pcm snd_timer i2c_i801 snd hw_random soundcore i2c_core uhci_hcd shpchp ehci_hcd snd_page_alloc dm_snapshot dm_zero dm_mirror dm_mod ext3 jbd ahci libata sd_mod scsi_mod
CPU:    0
EIP:    0060:[<c01f5483>]    Tainted: GF     VLI
EFLAGS: 00210206   (2.6.14-1.1709_FC5smp)
EIP is at vsnprintf+0x35/0x62d
eax: edb801d3   ebx: edb80164   ecx: 00000000   edx: 00000014
esi: fffffff4   edi: edb801e7   ebp: e3e51b4c   esp: e475fdc8
ds: 007b   es: 007b   ss: 0068
Process modprobe (pid: 10469, threadinfo=e475f000 task=ed26cab0)
Stack: badc0ded f70b1a18 00200246 000b174e ed26cbdc f7fff980 000000d0 00000014
       edb801d4 c01579b2 c0157b32 f640cf54 00000084 edb807ac 00000000 edb80164
       fffffff4 edb807ac e3e51b4c c027d806 e475fe40 e475fe40 f640cf54 f8c8a8a0
Call Trace:
 [<c01579b2>] __kmalloc+0xa1/0xf4
 [<c0157b32>] kzalloc+0xd/0x36
 [<c027d806>] class_device_create+0x76/0x9e
 [<f8c8656d>] lirc_register_plugin+0x25a/0x564 [lirc_dev]
 [<c0154ddf>] dbg_redzone1+0x11/0x22
 [<f8ceb302>] imon_probe+0x328/0x70b [lirc_imon]
 [<c02053d9>] usb_probe_interface+0x56/0x7e
 [<c027c8fd>] driver_probe_device+0x35/0x98
 [<c027ca20>] __driver_attach+0x4c/0x4e
 [<c027c194>] bus_for_each_dev+0x3b/0x59
 [<c027ca38>] driver_attach+0x16/0x1a
 [<c027c9d4>] __driver_attach+0x0/0x4e
 [<c027c54f>] bus_add_driver+0x63/0xa9
 [<c02054bf>] usb_register+0x54/0xb0
 [<c01261aa>] printk+0x1b/0x1f
 [<f8b40035>] imon_init+0x35/0x68 [lirc_imon]
 [<c0140fbb>] sys_init_module+0xd3/0x21b
 [<c01040a5>] syscall_call+0x7/0xb
Code: 1c 89 54 24 18 89 4c 24 34 85 d2 0f 88 c4 05 00 00 8b 44 24 1c 03 44 24 18 8d 78 ff 8b 44 24 1c 83 e8 01 39 c7 0f 82 4d 01 00 00 <0f>
b6 01 8b 74 24 1c 84 c0 0f 84 29 01 00 00 c7 44 24 24 00 00

So I set to finding what the problem was, it turned out the drivers needed some minor patching to work with recent kernels.

--- lirc_imon.org       2005-11-26 11:18:39.000000000 +0000
+++ lirc_imon.c 2005-11-26 11:43:59.000000000 +0000
@@ -3,6 +3,10 @@
  *
  *   $Id: lirc_imon.c,v 1.7 2005/08/10 19:22:20 lirc Exp $
  *
+ *   Version 0.3.1 [November 26, 2005]
+ *             <andy@burns.net>
+ *             mode field has been removed from usb_class_driver
+ *             remove usb prefix from devfs_name
  *   Version 0.3
  *             Supports newer iMON models that send decoded IR signals.
  *                     This includes the iMON PAD model.
@@ -68,11 +72,10 @@
 #define MOD_AUTHOR     "Venky Raju <dev@venky.ws>"
 #define MOD_DESC       "Driver for Soundgraph iMON MultiMedian IR/VFD"
 #define MOD_NAME       "lirc_imon"
-#define MOD_VERSION    "0.3"
+#define MOD_VERSION    "0.3.1"

 #define VFD_MINOR_BASE 144     /* Same as LCD */
-#define DEVFS_MODE     S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
-#define DEVFS_NAME     "usb/lcd%d"
+#define DEVFS_NAME     "lcd%d"

 #define BUF_CHUNK_SIZE 4
 #define BUF_SIZE       128
@@ -216,7 +219,6 @@
 static struct usb_class_driver imon_class = {
        .name           = DEVFS_NAME,
        .fops           = &vfd_fops,
-       .mode           = DEVFS_MODE,
        .minor_base     = VFD_MINOR_BASE,
 };
 #endif


--- lirc_dev.org        2005-11-26 11:27:02.000000000 +0000
+++ lirc_dev.c  2005-11-26 12:00:04.000000000 +0000
@@ -19,6 +19,10 @@
  *
  * $Id: lirc_dev.c,v 1.44 2005/08/08 06:04:48 lirc Exp $
  *
+ *   Version x.x.x [November 26, 2005]
+ *             <andy@burns.net>
+ *             add parent class in call to class_device_create()
+ *
  */

 #ifdef HAVE_CONFIG_H
@@ -382,7 +386,8 @@
                        S_IFCHR|S_IRUSR|S_IWUSR,
                        DEV_LIRC "/%u", ir->p.minor);
 #endif
-       (void) class_device_create(lirc_class, MKDEV(IRCTL_DEV_MAJOR, ir->p.minor),
+       (void) class_device_create(lirc_class, NULL,
+                                       MKDEV(IRCTL_DEV_MAJOR, ir->p.minor),
                                       NULL, "lirc%u", ir->p.minor);

        if(p->sample_rate || p->get_queue) {

With the fixed modules I could happily modprobe lirc_imon so I fired up mode2 and lo and behold something is being received

[root@localhost lirc-0.7.2]# mode2
Nov 26 12:08:29 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: IR port opened
code: 0x230988fa
code: 0x227b57ff
code: 0x310d80f8
code: 0x77ffffff
code: 0x631980fa
code: 0x57ffffff
code: 0x6319c0f8
code: 0x47ffffff
code: 0x310d88fa
code: 0x77ffffff
code: 0x310980f8
code: 0x67ffffff
code: 0x230988fa
code: 0x67ffffff
code: 0x310d88fa

Now I haven't seen the output of mode2 before, so I don't know if it is usually susceptible to picking up stray sunlight etc, but it seems like it to me, you can generate codes by waving your fingers between the VFD and the window :-)

Also there seems to be a problem where if you quit mode2 and re-start it you get an error about opening the device, for now I work around that by doing an rmmod lirc_imon and starting again, enough debugging for one day!

Nov 26 12:08:31 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: IR port closed
Nov 26 12:08:31 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: usb_rx_callback: status (-104): ignored
Nov 26 12:13:24 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: ir_open: usb_submit_urb failed for ir_open (-22)

Now all I need to do is configure lircd/lircmd to actually respond to the infrared codes ...

[root@localhost lirc-0.7.2]# modprobe lirc_imon
sNov 26 12:37:14 localhost kernel: lirc_dev: IR Remote Control driver registered, at major 61
Nov 26 12:37:14 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: Driver for Soundgraph iMON MultiMedian IR/VFD, v0.3.1
Nov 26 12:37:14 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: Venky Raju <dev@venky.ws>
Nov 26 12:37:14 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: imon_probe: found IMON device
Nov 26 12:37:14 localhost kernel: lirc_dev: lirc_register_plugin: sample_rate: 0
Nov 26 12:37:14 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: imon_probe: Registered iMON plugin (minor:0)
Nov 26 12:37:14 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: imon_probe: iMON device on usb<1:3> initialized
Nov 26 12:37:14 localhost kernel: usbcore: registered new driver lirc_imon

[root@localhost lirc-0.7.2]# service lirc start
Starting infrared remote control daemon (lircd):           [  OK  ]
Starting infrared remote control mouse daemon (lircmd):    [  OK  ]
Nov 26 12:37:29 localhost lircd-0.7.2[8079]: lircd(any) ready
Nov 26 12:37:29 localhost lircd-0.7.2[8079]: accepted new client on /dev/lircd
Nov 26 12:37:29 localhost lircd-0.7.2[8079]: could not get file information for /dev/lirc
Nov 26 12:37:29 localhost lircd-0.7.2[8079]: default_init(): No such file or directory
Nov 26 12:37:29 localhost lircd-0.7.2[8079]: caught signal

OK so lircd is defaulting to /dev/lirc, when we've got /dev/lirc0, a quick edit to /etc/sysconfig/lirc

# Note: in addition to these parameters, you need to have working    -*- sh -*-
# configuration file for lircd (and lircmd if enabled).

# Options to lircd(8).  Typically, at least a remote controller driver
# ("-H foo") needs to be specified here.  Run "/usr/sbin/lircd -H help" to get
# a listing of supported drivers.
LIRCD_OPTIONS="-d /dev/lirc0"

# If "yes", the init script will try to start lircmd(8) too.
ENABLE_LIRCMD="yes"

# Options to lircmd(8).
LIRCMD_OPTIONS=""

Still need to remove and re-install the driver due to the the re-opening problem ...

[root@localhost sysconfig]# service lirc stop
Stopping infrared remote control mouse daemon (lircmd):    [  OK  ]
Stopping infrared remote control daemon (lircd):           [  OK  ]
Nov 26 12:47:15 localhost lircd-0.7.2[8239]: removed client
Nov 26 12:47:15 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: IR port closed
Nov 26 12:47:15 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: usb_rx_callback: status (-104): ignored
Nov 26 12:47:16 localhost lircd-0.7.2[8239]: caught signal

[root@localhost sysconfig]# rmmod lirc_imon
[root@localhost sysconfig]# rmmod lirc_dev
Nov 26 12:47:23 localhost kernel: usbcore: deregistering driver lirc_imon
Nov 26 12:47:23 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: usb_rx_callback: status (-108): ignored
Nov 26 12:47:23 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: imon_disconnect: iMON device disconnected
Nov 26 12:47:23 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: Deregistered iMON plugin (minor:0)
Nov 26 12:47:23 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: module removed. Goodbye!

[root@localhost sysconfig]# modprobe lirc_imon
Nov 26 12:47:39 localhost kernel: lirc_dev: IR Remote Control driver registered, at major 61
Nov 26 12:47:39 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: Driver for Soundgraph iMON MultiMedian IR/VFD, v0.3.1
Nov 26 12:47:39 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: Venky Raju <dev@venky.ws>
Nov 26 12:47:39 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: imon_probe: found IMON device
Nov 26 12:47:39 localhost kernel: lirc_dev: lirc_register_plugin: sample_rate: 0
Nov 26 12:47:39 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: imon_probe: Registered iMON plugin (minor:0)
Nov 26 12:47:39 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: imon_probe: iMON device on usb<1:3> initialized
Nov 26 12:47:39 localhost kernel: usbcore: registered new driver lirc_imon

[root@localhost sysconfig]# service lirc start
Starting infrared remote control daemon (lircd):           [  OK  ]
Starting infrared remote control mouse daemon (lircmd):    [  OK  ]
Nov 26 12:47:49 localhost lircd-0.7.2[8361]: lircd(any) ready
Nov 26 12:47:49 localhost lircd-0.7.2[8361]: accepted new client on /dev/lircd
Nov 26 12:47:49 localhost kernel: /usr/src/redhat/SOURCES/lirc-0.7.2/drivers/lirc_imon/lirc_imon.c: IR port opened

[root@localhost lirc_dev]# irw
Nov 26 15:38:36 localhost lircd-0.7.2[8361]: accepted new client on /dev/lircd
0000000028b595b7 00 1 iMON-PAD
000000002bb195b7 00 2 iMON-PAD
0000000028b195b7 00 3 iMON-PAD
0000000028a395b7 00 Vol+ iMON-PAD
0000000028a595b7 00 Vol- iMON-PAD
00000000288195b7 00 AppExit iMON-PAD
000000002a8115b7 00 Play iMON-PAD
00000000299115b7 00 MouseKeyboard iMON-PAD
00000000688301b7 00 MouseLeftClick iMON-PAD
00000000688301b7 00 MouseLeftClick iMON-PAD
00000000688481b7 00 MouseRightClick iMON-PAD
Nov 26 15:39:26 localhost lircd-0.7.2[8361]: removed client

That looks quite promising, but the power and mouse/arrow buttons don't seem to show up.

Links

LKML: Remove the mode field from usb_class_driver as it's no longer needed
LKML: Add the ability for class_device structures to be nested
LKML: Fix up all callers of class_device_create()
LKML: Do not register statically allocated input devices Bugzilla entry