Snapstream firefly mini

From MythTV Official Wiki
Revision as of 16:42, 22 October 2010 by Wagnerrp (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Snapstream Firefly Mini Remote (IR, USB, mini)


Product Web page:

There are two version of this remote. The original full size rf firefly remote, Snapstream Firefly and the new mini-firefly remote that is IR based. This guide is for the IR version.


This remote is cheap IR-based USB remote control, the smaller cousin of the larger, RF-based Snapstream Firefly remote. I have found this device to be an acceptable remote; it is cheap, compact and performs as expected when setup correctly. The IR range and sensitivity is a little disappointing, I have found that correct placement of the IR receiver makes a big difference.

Issues and Problems

The Firefly Mini is a USB HID device so should work without dedicated drivers. Indeed plugging this remote should result in some of the buttons working immediately (0-9, up, down, left, right, and OK). The remainder - except for 3 of them (Last, Guide, and the special "Firefly" buttion) can be mapped as any key on the keyboard using the 'Xmodmap' command. You can see you current keymappings with by typing "xmodmap -pke" at the terminal.

The list of keycodes for each non-standard buttion (found with XEV command) are:

Close = 175

Mute = 160

Last = no keycode in XEV

Exit = 234

VOL+ = 176

VOL- = 174

Option = 134

Firefly = no keycode in XEV

Menu = 158

Record = 177

Guide = no keycode in XEV

Stop = 164

Prev|<< = 144

Play = 179

Next>>| = 153

REW<< = 152

Pause = 110

FFWD>> = 180

For example, from the terminal one can enter:

xmodmap -e "keycode 179 = p"

And the main keymap will be changed so when you press the "Play" button on the Firefly remote it will act as if it is pressing "p" on the keyboard. This is a temporary modification that is lost on re-boot. So, in order to keep these settings you need to include these xmodmap commands in an init script during your window manager startup. Alternatively, you can create a text file of the key settings to launch with xmodmap. For example one can create a keys.txt file like this:

# /var/lib/mythtv/keys.txt 
keycode 164 = Escape
keycode 134 = m
keycode 152 = Left
keycode 180 = Right
keycode 144 = less
keycode 179 = p
keycode 153 = greater
keycode 177 = r
keycode 160 = F9

And then executing "xmodmap /var/lib/mythtv/keys.txt". In Mythbuntu, you can add this line to "programs run at statup" gui in XFCE window manager. Using this method does not require the use of LIRC, the remote will act as if it is a keystroke on the keyboard.

To determine the key name of a key do:


press the key you want to know the name of and you will see

KeyPress event, serial 31, synthetic NO, window 0x3000001,
    root 0x1a6, subw 0x0, time 794284, (-250,-129), root:(301,319),
    state 0x0, keycode 34 (keysym 0x5b, bracketleft), same_screen YES,
    XLookupString gives 1 bytes: (5b) "["
    XmbLookupString gives 1 bytes: (5b) "["
    XFilterEvent returns: False

bracketleft is the name of that key.

The rest of this guide is dedicated to configuring your system so that all buttons on the Firefly Mini are functional. This is achieved by:

  • Ensuring kernel support for all buttons on the Firefly Mini
  • Configuring lirc to read keypresses from the Linux /dev/input/event subsystem
  • Configuring lirc to send appropriate events to MythTV

NOTE: lirc is used to handle 'special' buttons, the normal buttons (0-9, up, down, left, right, ok) are not handled by lirc.

Ensure Firefly Mini hardware is working

When plugged in to the system the Firefly Mini should be recognized as a composite USB device with two interfaces:

[root@localhost simon]# cat /proc/bus/usb/devices
T:  Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=1.5 MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=1233 ProdID=e007 Rev= 1.00
S:  Manufacturer=HOLTEK
S:  Product=USB Keyboard
C:* #Ifs= 2 Cfg#= 1 Atr=a0 MxPwr=100mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=01 Driver=usbhid
E:  Ad=81(I) Atr=03(Int.) MxPS=   8 Ivl=10ms
I:  If#= 1 Alt= 0 #EPs= 1 Cls=03(HID  ) Sub=01 Prot=02 Driver=usbhid
E:  Ad=82(I) Atr=03(Int.) MxPS=   8 Ivl=10ms

The first interface is a USB HID Keyboard (Prot=01), most of the 'standard keyboard' buttons found on a standard keyboard are attached to this interface, they are generally the ones that work out-of-the-box even without full kernel support.

The second interface is a USB HID mouse device (Prot=02) that maps to most of the other buttons (close, guide, menu etc.).

When the Firefly Mini is attached two entries should be created in /dev/input/ that correspond with the the keyboard and consumer device (e.g. event0 and event1). The exact numbers used depend on the number of other USB HID devices attached to your system.

Fixed device names for these devices are also generated by udev under /dev/input/by-id, with symbolic links to the underlying devices, for example:

# stat -c "%N" /dev/input/by-id/usb-HOLTEK_USB_Keyboard-*
`/dev/input/by-id/usb-HOLTEK_USB_Keyboard-event-kbd' -> `../event1'
`/dev/input/by-id/usb-HOLTEK_USB_Keyboard-event-mouse' -> `../event2'
`/dev/input/by-id/usb-HOLTEK_USB_Keyboard-mouse' -> `../mouse1'

You should be able to read from each of the above event devices and see some data appear when keys are pressed. If you do not have full kernel support, some keys (such as the red 'Snapstream' button) do not produce any output on any of the event devices.


Kernel 2.6.20 and up have support for all of the keys on the remote.

The following patch was created against FC6 2.6.18-1.2849, use it or a similar change to add full support for earlier kernels.

--- a/drivers/usb/input/hid-input.c     2006-09-19 20:42:06.000000000 -0700
+++ b/drivers/usb/input/hid-input.c     2006-12-31 14:26:00.000000000 -0800
@@ -403,9 +403,12 @@ static void hidinput_configure_usage(str
                                case 0x000: goto ignore;
                                case 0x034: map_key_clear(KEY_SLEEP);          break;
                                case 0x036: map_key_clear(BTN_MISC);           break;
+                               case 0x040: map_key_clear(KEY_MENU);           break;
                                case 0x045: map_key_clear(KEY_RADIO);          break;
                                case 0x08a: map_key_clear(KEY_WWW);            break;
+                               case 0x083: map_key_clear(KEY_LAST);           break;
                                case 0x08d: map_key_clear(KEY_PROGRAM);        break;
+                               case 0x09a: map_key_clear(KEY_PVR);            break;
                                case 0x095: map_key_clear(KEY_HELP);           break;
                                case 0x09c: map_key_clear(KEY_CHANNELUP);      break;
                                case 0x09d: map_key_clear(KEY_CHANNELDOWN);    break;
@@ -426,10 +429,12 @@ static void hidinput_configure_usage(str
                                case 0x0ea: map_key_clear(KEY_VOLUMEDOWN);     break;
                                case 0x183: map_key_clear(KEY_CONFIG);         break;
                                case 0x18a: map_key_clear(KEY_MAIL);           break;
+                               case 0x18e: map_key_clear(KEY_CALENDAR);       break;
                                case 0x192: map_key_clear(KEY_CALC);           break;
                                case 0x194: map_key_clear(KEY_FILE);           break;
                                case 0x1a7: map_key_clear(KEY_DOCUMENTS);      break;
                                case 0x201: map_key_clear(KEY_NEW);            break;
+                               case 0x203: map_key_clear(KEY_CLOSE);          break;
                                case 0x207: map_key_clear(KEY_SAVE);           break;
                                case 0x208: map_key_clear(KEY_PRINT);          break;
                                case 0x209: map_key_clear(KEY_PROPS);          break;

Apply the patch, install the resulting kernel and reboot. When running the new kernel pressing each button on the Firefly Mini should result in some characters appearing on one of the /dev/input/eventX devices.

Create a udev rule for the remote control consumer device =

We will be using lirc to interpret the data from /dev/input and generate events however lirc must have a fixed device name to read data from. In order to create a fixed device name we need a custom udev rule.

Identify the /dev/input/eventX device that corresponds to the red 'Snapstream' button button on the remote control. Repeatedly pressing the red button while using cat to read from each eventX device should do the trick. Next we need to find unique modalias for this device:

udevinfo -a -p $(udevinfo -q path -n /dev/input/eventX)

[root@localhost SOURCES]# udevinfo -a -p $(udevinfo -q path -n /dev/input/event1)

Udevinfo starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/class/input/input1/event1':

  looking at parent device '/class/input/input1':
    SYSFS{name}=="HOLTEK USB Keyboard"

  looking at parent device '/devices/pci0000:00/0000:00:10.2/usb3/3-1/3-1:1.1':
    SYSFS{modalias}=="usb:v1233pE007d0100dc00dsc00dp00ic03isc01ip02"     <==== THIS ONE!
    SYSFS{bAlternateSetting}==" 0"

  looking at parent device '/devices/pci0000:00/0000:00:10.2/usb3/3-1':
    SYSFS{product}=="USB Keyboard"
    SYSFS{version}==" 1.10"

Locate the first modalias line and note the long value contained within it. Now create a new file /etc/udev/rules.d/10-local.rules with the following content:

KERNEL=="event*",SYSFS{modalias}=="<your modalias value here>",SYMLINK="input/firefly-mini"

With this rule in place unplugging and replugging the remote control should result in this:

[root@localhost SOURCES]# ls -l /dev/input/*
crw------- 1 root root 13, 64 Jan  1 14:36 /dev/input/event0
crw------- 1 root root 13, 65 Jan  1 14:36 /dev/input/event1
crw------- 1 root root 13, 66 Jan  1 14:36 /dev/input/event2
lrwxrwxrwx 1 root root      6 Jan  1 14:36 /dev/input/firefly-mini -> event1
crw------- 1 root root 13, 63 Jan  1 14:36 /dev/input/mice
crw------- 1 root root 13, 32 Jan  1 14:36 /dev/input/mouse0
[root@localhost SOURCES]#

Configure lirc

The Firefly Mini remote needs to be defined in the lircd.conf file, add the following to yours:

begin remote
        name firefly-mini
        bits 32
        begin codes
                CLOSE                0x100ce
                MUTE                 0x10071
                VOLUMEDOWN           0x10072
                VOLUMEUP             0x10073
                CHANNELUP            0x10192
                CHANNELDOWN          0x10193
                LAST                 0x10195
                BACK                 0x1009e
                PROPS                0x10082
                PVR                  0x1016e
                MENU                 0x1008b
                RECORD               0x100a7
                CALENDAR             0x1018d
                STOPCD               0x100a6
                PREVIOUSSONG         0x100a5
                PLAY                 0x100cf
                NEXTSONG             0x100a3
                REWIND               0x100a8
                PAUSE                0x10077
                FASTFORWARD          0x100d0
        end codes
end remote

We will use lirc to read events from /dev/input/firefly-mini. To do this we'll use the lirc 'dev/input' driver, which uses the lirc_i2c kernel module. If you have not yet configured and installed lirc, do so now.

When lircd the device and driver to use should be specified. I added the following line to /etc/rc.local:

/usr/local/sbin/lircd --driver=dev/input --device=/dev/input/firefly-mini --output=/dev/lircd --pidfile /var/run/

Or, perhaps configure LIRCD_OPTIONS in /etc/init.d/lircd, such that you can use the standard rc scripts to start/stop/restart lircd:

LIRCD_OPTIONS="--driver=dev/input --device=/dev/input/firefly-mini --output=/dev/lircd --pidfile /var/run/"

With lircd.conf updated and lircd running irw and pressing special keys (other than 0-9, up, down, left, right, ok) should generate output:

[root@localhost SOURCES]# irw
0000000000010073 00 VOLUMEUP firefly-mini
0000000000010072 00 VOLUMEDOWN firefly-mini
0000000000010192 00 CHANNELUP firefly-mini
0000000000010193 00 CHANNELDOWN firefly-mini
000000000001016e 00 PVR firefly-mini

Finally modify your /home/mythtv/.lircrc and /home/mythtv/.mythtv/lircrc files to perform appropriate actions when buttons are pressed. Here is my lircrc file as it stands today, it's a work in progress.

NOTE: Alt+Home and Alt+G should be configured using Setup->Keys to make the red button and the guide button work.

# MythTV
        prog = mythtv
        button = CLOSE
        config = Esc
        repeat = 1

        prog = mythtv
        button = MUTE
        config = |
        repeat = 1

        prog = mythtv
        button = VOLUMEUP
        config = ]

        prog = mythtv
        button = VOLUMEDOWN
        config = [

        prog = mythtv
        button = CHANNELUP
        config = Up

        prog = mythtv
        button = CHANNELDOWN
        config = Down

        prog = mythtv
        button = LAST
        config = H
        repeat = 1

        prog = mythtv
        button = BACK
        config = Esc
        repeat = 1

        prog = mythtv
        button = PROPS
        config = I
        repeat = 1

        prog = mythtv
        button = PVR
        config = Alt+Home
        repeat = 1

        prog = mythtv
        button = MENU
        config = M
        repeat = 1

        prog = mythtv
        button = RECORD
        config = R
        repeat = 1

        prog = mythtv
        button = CALENDAR
        config = Alt+G
        repeat = 1

        prog = mythtv
        button = STOPCD
        config = Esc
        repeat = 1

        prog = mythtv
        button = PREVIOUSSONG
        config = Q
        repeat = 1

        prog = mythtv
        button = PLAY
        config = P
        repeat = 1

        prog = mythtv
        button = NEXTSONG
        config = Z
        repeat = 1

        prog = mythtv
        button = REWIND
        config = <
        repeat = 1

        prog = mythtv
        button = PAUSE
        config = P

        prog = mythtv
        button = FASTFORWARD
        config = >

# mplayer
        prog = mplayer
        button = BACK
        config = quit

Good luck!