Logitech Wireless Keyboard for Wii

From MythTV Official Wiki
Jump to: navigation, search

The wireless keyboard for the video game console Wii™ produced by Logitech, Inc., is a cheap input device ideal to enter short text (such as web search strings, quick email replies, chat messages, etc.). It features:

  • compact size (30x16.5x2cm)
  • full-size keys
  • six dedicated keys
  • 2.4GHz wireless connection
  • slot on the back side to store the connection USB key
  • mechanical power switch to save up battery energy

It misses an important key, though, the left Alt_L key.


Installation

Provided that kernel module usbhid is loaded and HAL is running, the keyboard is automatically recognised as Logitech USB Wireless HID Receiver as soon as the USB key is attached.

 lorcap ~ $ lshal > /tmp/hal
 USB key receiver inserted.  wait 2-3 seconds to settle...
 lorcap ~ $ lshal > /tmp/hal-wii
 lorcap ~ $ diff --old-line-format="" \
                 --unchanged-line-format="" \
                 --new-line-format="%L" \
                 /tmp/hal /tmp/hal-wii \
            | egrep -v "^Dump"
 udi = '/org/freedesktop/Hal/devices/usb_device_46d_cab1_noserial'
   info.linux.driver = 'usb'  (string)
   info.parent = '/org/freedesktop/Hal/devices/usb_device_1d6b_1_0000_00_1d_0'  (string)
   info.product = 'USB Wireless HID Receiver'  (string)
   info.subsystem = 'usb_device'  (string)
   info.udi = '/org/freedesktop/Hal/devices/usb_device_46d_cab1_noserial'  (string)
   info.vendor = 'Logitech, Inc.'  (string)
   linux.device_file = '/dev/bus/usb/002/003'  (string)
   linux.hotplug_type = 2  (0x2)  (int)
   linux.subsystem = 'usb'  (string)
   linux.sysfs_path = '/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1'  (string)
   usb_device.bus_number = 2  (0x2)  (int)
   usb_device.can_wake_up = true  (bool)
   usb_device.configuration_value = 1  (0x1)  (int)
   usb_device.device_class = 0  (0x0)  (int)
   usb_device.device_protocol = 0  (0x0)  (int)
   usb_device.device_revision_bcd = 288  (0x120)  (int)
   usb_device.device_subclass = 0  (0x0)  (int)
   usb_device.is_self_powered = false  (bool)
   usb_device.linux.device_number = 3  (0x3)  (int)
   usb_device.linux.sysfs_path = '/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1'  (string)
   usb_device.max_power = 100  (0x64)  (int)
   usb_device.num_configurations = 1  (0x1)  (int)
   usb_device.num_interfaces = 1  (0x1)  (int)
   usb_device.num_ports = 0  (0x0)  (int)
   usb_device.product = 'USB Wireless HID Receiver'  (string)
   usb_device.product_id = 51889  (0xcab1)  (int)
   usb_device.speed = 1.5 (1.5) (double)
   usb_device.vendor = 'Logitech, Inc.'  (string)
   usb_device.vendor_id = 1133  (0x46d)  (int)
   usb_device.version = 2.0 (2) (double)
 
 udi = '/org/freedesktop/Hal/devices/usb_device_46d_cab1_noserial_usbraw'
   info.capabilities = {'usbraw'} (string list)
   info.category = 'usbraw'  (string)
   info.parent = '/org/freedesktop/Hal/devices/usb_device_46d_cab1_noserial'  (string)
   info.product = 'USB Raw Device Access'  (string)
   info.subsystem = 'usb_device'  (string)
   info.udi = '/org/freedesktop/Hal/devices/usb_device_46d_cab1_noserial_usbraw'  (string)
   linux.device_file = '/dev/usbdev2.3'  (string)
   linux.hotplug_type = 2  (0x2)  (int)
   linux.subsystem = 'usb_device'  (string)
   linux.sysfs_path = '/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/usb_device/usbdev2.3'  (string)
   usbraw.device = '/dev/usbdev2.3'  (string)
 
 udi = '/org/freedesktop/Hal/devices/usb_device_46d_cab1_noserial_if0'
   info.linux.driver = 'usbhid'  (string)
   info.parent = '/org/freedesktop/Hal/devices/usb_device_46d_cab1_noserial'  (string)
   info.product = 'USB HID Interface'  (string)
   info.subsystem = 'usb'  (string)
   info.udi = '/org/freedesktop/Hal/devices/usb_device_46d_cab1_noserial_if0'  (string)
   linux.hotplug_type = 2  (0x2)  (int)
   linux.subsystem = 'usb'  (string)
   linux.sysfs_path = '/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0'  (string)
   usb.bus_number = 2  (0x2)  (int)
   usb.can_wake_up = true  (bool)
   usb.configuration_value = 1  (0x1)  (int)
   usb.device_class = 0  (0x0)  (int)
   usb.device_protocol = 0  (0x0)  (int)
   usb.device_revision_bcd = 288  (0x120)  (int)
   usb.device_subclass = 0  (0x0)  (int)
   usb.interface.class = 3  (0x3)  (int)
   usb.interface.number = 0  (0x0)  (int)
   usb.interface.protocol = 1  (0x1)  (int)
   usb.interface.subclass = 1  (0x1)  (int)
   usb.is_self_powered = false  (bool)
   usb.linux.device_number = 3  (0x3)  (int)
   usb.linux.sysfs_path = '/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0'  (string)
   usb.max_power = 100  (0x64)  (int)
   usb.num_configurations = 1  (0x1)  (int)
   usb.num_interfaces = 1  (0x1)  (int)
   usb.num_ports = 0  (0x0)  (int)
   usb.product = 'USB HID Interface'  (string)
   usb.product_id = 51889  (0xcab1)  (int)
   usb.speed = 1.5 (1.5) (double)
   usb.vendor = 'Logitech, Inc.'  (string)
   usb.vendor_id = 1133  (0x46d)  (int)
   usb.version = 2.0 (2) (double)
 
 udi = '/org/freedesktop/Hal/devices/usb_device_46d_cab1_noserial_if0_logicaldev_input'
   info.addons.singleton = {'hald-addon-input'} (string list)
   info.capabilities = {'input', 'input.keyboard', 'input.keypad', 'input.keys', 'button'} (string list)
   info.category = 'input'  (string)
   info.parent = '/org/freedesktop/Hal/devices/usb_device_46d_cab1_noserial_if0'  (string)
   info.product = 'Logitech USB Wireless HID Receiver'  (string)
   info.subsystem = 'input'  (string)
   info.udi = '/org/freedesktop/Hal/devices/usb_device_46d_cab1_noserial_if0_logicaldev_input'  (string)
   input.device = '/dev/input/event11'  (string)
   input.originating_device = '/org/freedesktop/Hal/devices/usb_device_46d_cab1_noserial_if0'  (string)
   input.product = 'Logitech USB Wireless HID Receiver'  (string)
   input.x11_driver = 'evdev'  (string)
   input.xkb.layout = 'it'  (string)
   input.xkb.model = 'evdev'  (string)
   input.xkb.rules = 'base'  (string)
   input.xkb.variant =   (string)
   linux.device_file = '/dev/input/event11'  (string)
   linux.hotplug_type = 2  (0x2)  (int)
   linux.subsystem = 'input'  (string)
   linux.sysfs_path = '/sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1:1.0/input/input12/event11'  (string)

Keyboard Layout

The keyboard found at the local store provides an Italian layout. It features six extra keys:

  • Quit, between Esc and F1
  • Zoom_In and Zoom_Out, in place of Windows key and left Alt_L
  • Backward and Forward, between Space and AltGr
  • Ok just below the right Shift_R.

The keyboard provides also the four arrow keys (Up, Down, Left, and Right) on the lower right-hand-side corner which come very handy when surfing through MythTV menus. In the same place, there is also the blue key FN which, when combined with the arrow keys, serve as Page_Up, Page_Down, Begin, and End.

The blue key FN can be used to enter digits with a keypad layout. Unfortunately, FN and keypad keys are all on the right-hand-side of the keyboard and the digits should be entered with one hand by pressing two keys at the same time.

The biggest shortcoming of the keyboard, though, is that it misses the left Alt_L key. The ALT_L is vital for a more advanced usage of the home theater hosting MythTV, e.g., when text console is required.


Scancodes

The key codes, called scancodes and produced by the keyboard at each key press/release, can be shown with the utility showkey run in a text console. Even when using the kernel parameter atkbd.softram=0, as suggested in showkey's manual page, the scancodes don't change.

 lorcap ~ $ showkey -s
 kb mode was UNICODE
 [ if you are trying this under X, it might not work
 since the X server is also reading /dev/console ]
 
 press any key (program terminates 10s after last keypress)...
 0x9c 
 0x38 0x0e            # Quit     = Alt_L Backspace
 0xb8 0x8e
 0x4a                 # Zoom_Out = KP_Subtract
 0xca
 0x4e                 # Zoom_In  = KP_Add
 0xce
 0xe0 0x1d 0xe0 0x4b  # Backward = Control_L Left
 0xe0 0x9d 0xe0 0xcb
 0xe0 0x1d 0xe0 0x4d  # Forward  = Control_L Right
 0xe0 0x9d 0xe0 0xcd
 0x38 0x1c            # Ok       = Alt_L Return
 0xb8 0x9c


Keycodes

Keycodes are numbers assigned by the kernel to each individual physical key and read by applications.

 lorcap ~ $ showkey -k
 kb mode was UNICODE
 [ if you are trying this under X, it might not work
 since the X server is also reading /dev/console ]
 
 press any key (program terminates 10s after last keypress)...
 keycode  28 release
 keycode  56 press     # Quit     = Alt_L
 keycode  14 press     #            Backspace
 keycode  56 release
 keycode  14 release
 keycode  74 press     # Zoom_Out = KP_Subtract
 keycode  74 release
 keycode  78 press     # Zoom_In  = KP_Add
 keycode  78 release
 keycode  97 press     # Backward = Control_L
 keycode 105 press     #            Left
 keycode  97 release
 keycode 105 release
 keycode  97 press     # Forward  = Control_L
 keycode 106 press     #            Right
 keycode  97 release
 keycode 106 release
 keycode  56 press     # Ok       = Alt_L
 keycode  28 press     #            Return
 keycode  56 release
 keycode  28 release


HAL Keymap

As seen above, the keyboard does not generate any special scancode and the use of setkeycodes or an equivalent utility is probably useless. Nonetheless, here it is the way to re-bind a scancode with a new keycode using HAL. Create the file 30-keymap-wii.fdi in /etc/hal/fdi/policy/ with the following customizable content:

 <?xml version="1.0" encoding="ISO-8859-1"?> 
 
 <deviceinfo version="0.2">
   <device>
 
     <match key="@input.originating_device:info.linux.driver" string="usbhid">
       <match key="info.product" string="Logitech USB Wireless HID Receiver">
 
           <append key="input.keymap.data" type="strlist">4a:volumedown</append>
           <append key="input.keymap.data" type="strlist">4e:volumeup</append>
 
           <addset key="info.capabilities" type="strlist">input.keymap</addset>
 
       </match>
     </match>
 
   </device>
 </deviceinfo>


How to Add the Alt_L Key

Console and X require two different utilities in order to get back the Alt_L key. The following instructions assume you want to bind the key Zoom_In, which is equivalent to the keypad add.


Alt_L in a Console

The Alt_L key can be obtained via utility loadkeys. Choose the key which will be used as Alt_L, e.g. Zoom_In, and then issue the following command:

 lorcap ~ $ echo "keycode 78 = Alt" | loadkeys it -
 Loading /usr/share/kbd/keymaps/i386/qwerty/it.map.gz
 Loading <stdin>

Alternatively, it is possible to place a map file wii.map in /usr/share/kbd/keymaps/i386/qwerty/:

 lorcap ~ $ echo "keycode 78 = Alt" > /usr/share/kbd/keymaps/i386/qwerty/wii.map
 loadkeys it wii
 Loading /usr/share/kbd/keymaps/i386/qwerty/it.map.gz
 Loading /usr/share/kbd/keymaps/i386/qwerty/wii.map

One more option is to have only one map file:

 lorcap ~ $ cd /usr/share/kbd/keymaps/i386/qwerty
 lorcap ~ $ echo 'include "it.map"'  > wii.map
 lorcap ~ $ echo 'keycode 78 = Alt" >> wii.map
 lorcap ~ $ cd
 lorcap ~ $ loadkeys wii
 Loading /usr/share/kbd/keymaps/i386/qwerty/wii.map


Alt_L under X

The command to use and get back the Alt_L is xmodmap. Because special keys produce ordinary keys which are already defined, expression keysym can be used.

 lorcap ~ $ xmodmap -e 'keysym KP_Add = Alt_L'

To check that the new binding is working, run xev under X and press the new key:

 lorcap ~ $ xev
 KeyPress event, serial 43, synthetic NO, window 0x1000001,
     root 0x10b, subw 0x0, time 1980226, (-463,-67), root:(380,54),
     state 0x0, keycode 86 (keysym 0xffe9, Alt_L), same_screen YES,
     XKeysymToKeycode returns keycode: 64
     XLookupString gives 0 bytes: 
     XmbLookupString gives 0 bytes: 
     XFilterEvent returns: False
 
 KeyRelease event, serial 43, synthetic NO, window 0x1000001,
     root 0x10b, subw 0x0, time 1980298, (-463,-67), root:(380,54),
     state 0x8, keycode 86 (keysym 0xffe9, Alt_L), same_screen YES,
     XKeysymToKeycode returns keycode: 64
     XLookupString gives 0 bytes: 
     XFilterEvent returns: False

When everything is working, the definitive expression can be written to .xmodmaprc:

 lorcap ~ $ echo 'keysym KP_Add = Alt_L' >> ~/.xmodmaprc