Raspberry Pi: USB Keypad Via evdev

The general idea is to use keystrokes plucked from a cheap numeric keypad to control mplayer, with the intent of replacing some defunct CD players and radios and suchlike. The keypads look about like you’d expect:

Numeric keypads
Numeric keypads

The keypad layouts are, of course, slightly different (19 vs 18 keys!) and they behave differently with regard to their NumLock state, but at least they produce the same scancodes for the corresponding keys. The black (wired) keypad has a 000 button that sends three 0 events in quick succession, which isn’t particularly useful in this application.

With the appropriate udev rule in full effect, this Python program chews its way through incoming events and reports only the key-down events that will eventually be useful:

from evdev import InputDevice,ecodes,KeyEvent
k=InputDevice('/dev/input/keypad')
for e in k.read_loop():
if (e.type == ecodes.EV_KEY) and (KeyEvent(e).keystate == 1):
if (KeyEvent(e).keycode == 'KEY_NUMLOCK'):
continue # we don't care about the NumLock state
else:
print KeyEvent(e).scancode, KeyEvent(e).keycode

Pressing the keys on the white keypad in an obvious sequence produces the expected result:

82 KEY_KP0
79 KEY_KP1
80 KEY_KP2
81 KEY_KP3
75 KEY_KP4
76 KEY_KP5
77 KEY_KP6
71 KEY_KP7
72 KEY_KP8
73 KEY_KP9
98 KEY_KPSLASH
55 KEY_KPASTERISK
14 KEY_BACKSPACE
74 KEY_KPMINUS
78 KEY_KPPLUS
96 KEY_KPENTER
83 KEY_KPDOT

Observations

  • KeyEvent(e).keycode is a string: 'KEY_KP0'
  • e.type is numeric, so just compare against evcodes.EV_KEY
  • KeyEvent(e).scancode is the numeric key identifier
  • KeyEvent(e).keystate = 1 for the initial press
  • Those KeyEvent(e).key_down/up/hold values don’t change

If you can type KEY_KP0 correctly, wrapping it in quotes isn’t such a big stretch, so I don’t see much point to running scancodes through ecodes.KEY[KeyEvent(e).scancode] just to compare the enumerations.

I’m surely missing something Pythonic, but I don’t get the point of attaching key_down/up/hold constants to the key event class. I suppose that accounts for changed numeric values inside inherited classes, but … sheesh.

Anyhow, that loop looks like a good starting point.

3 thoughts on “Raspberry Pi: USB Keypad Via evdev

  1. I’m imagining custom keycaps (probably stickers) at some point in the future. I follow your logic about converting keycode strings to scancodes. Using keycodes is less (computer) efficient but more readable and future-proof (and therefore more programmer efficient), and programmer efficiency trumps computer efficiency for this task.

    1. The event interface emits a raw scancode-per-key, along with an indication of the key state change, rather than the cooked result from the usual keyboard handler. That turns the keypad into a button array: the Backspace key doesn’t do buffer editing and the NumLock state doesn’t change anything.

      You’ll see crude sticker labels tomorrow and better ones later on; we’re definitely not talking commercial quality, but it’s much easier than conjuring up my own wireless button array!

Comments are closed.