How can I capture raw HID input on Linux?
Asked Answered
N

6

40

Short version of what I want to accomplish: I have a foot pedal (INFINITY-IN-USB-1, if that's of any interest) that is implemented as a generic HID device, and I would like it to be behave as Ctrl and Alt keys on Linux. I'm looking for something on the level on X, i.e. not just individual programs.

Longer version: I have this setup working in Windows XP by calling DLL functions RegisterRawInputDevices and GetRawInputData and listening to the input in a hidden window. All is accomplished with a fairly straightforward AutoHotkey script (I can post here if anyone is interested). The point is, there isn't any need for any extra driver, etc.; only the native Windows DLL files are needed.

I want this setup to work on Linux (more specifically GNOME under Ubuntu, but I do occasionally use other distributions/window managers, so a solution on the level of X is appreciated). This foot pedal does not register itself as keyboard or even joystick, but as a HID device with UsagePage 12, Usage 3.

I notice that the latest Ubuntu can detect and use the favorite keys on the Microsoft Natural Keyboard, which also register as HID device*. I make use of those keys on Windows using the same method as I use the foot pedal (i.e., without the bundled software). So I assume that this pedal thing can work on Linux as well, but the question is how?

(I'm new to the lower-level stuff on Linux, so please be generous with links to introduction or tutorial whenever applicable.)

* For those not in the know, the Microsoft Natural Keyboard registers as both a regular keyboard and a generic HID device. Without some application (such as the bundled application) knowing how to interpret the HID input, the regular keys will work, but the favorite keys and the special function keys are useless.


To clarify, Linux is not seeing the pedal presses as input. It does recognize the USB device, but xev doesn't give any output for pedal presses. I have seen reports of people successfully using the pedal under Wine for transcription software, but that must work in a Windows way and does not give what I want (which is making the pedal look like a keyboard to all native Linux applications). Is some low-level Linux keyboard driver needed?


Here's some more information: If I issue this in the terminal

cat /dev/usb/hiddev0

(dev/usb/hiddev0 is my pedal), I get raw codes corresponding to my pedal presses. That's a start. I know what those raw code means: in binary, 0001, 0010, 0100 corresponds to each pedal, respectively, and combination of pedal presses sends combination of those binary number, and releases of pedal trigger input of whatever pedal still being pressed (if all pedal is up, 0000 is sent).

How can I get X to listen to dev/usb/hiddev0 and translate the raw codes into maybe a special keycode so that I can map them with xmodmap or something?

Nevsa answered 17/5, 2009 at 5:46 Comment(0)
H
23

You'll want uinput. You'll listen on your /dev/usb/hiddev0 and then create new events that you'll send out on /dev/input/uinput.

This explains it and gives a little tutorial: Using uinput driver in Linux- 2.6.x to send user input {This is the EInfochips' "Dashboard" publication issue January 2007 "Tip of the Month" article mentioned on this archived page}.

Helpmate answered 24/11, 2009 at 18:47 Comment(2)
Can you elaborate a little bit more? How does one listen to /dev/usb/hiddev0 programatically (the article you linked only talks about uinput)? The resulting program (that listens on hiddev and send keyboard/mouse events through uinput) would have to run as a daemon, I assume?Nevsa
Yes, I assume from your question that you already know how to read hiddev0. You will probably be writing a daemon. Start by writing a program that continually reads hiddev0 and prints out presses. Then you can modify it to emit new events via uinput. This will basically re-inject these events back into the kernel, but as keyboard or mouse events (of your choosing). No changes to X will be necessary.Helpmate
U
8

I wrote about how I got my Infinity IN-USB-1 (AKA "VEC USB Footpedal") to send arbitrary keysyms under X on my weblog:

Use VEC/Infinity USB Foot Pedal as a Keyboard Under Linux

(It should also work for IN-USB-2 and maybe some other USB foot controller models sold by VEC and P.I. Engineering and their clones.)

Here is the shorter version:

Get X to recognize the pedal

The pedal is an HID-compliant USB device and the kernel doesn't have any problem discovering it and making its events available to user space via a /dev/input/eventX node. To see that you can run the evtest program (on Debian: sudo apt install evtest). So you don't need to go to the HID level to use the foot pedals.

The problem is that udev does not tag it as a keyboard or mouse, so X ignores it. This can be fixed with a one-line udev rule file (thanks to Parlatype developer Gabor Karsay for providing this solution in Parlatype Issue 28):

ACTION=="add|change", KERNEL=="event[0-9]*", ATTRS{idVendor}=="05f3", ATTRS{idProduct}=="00ff", ENV{ID_INPUT_KEYBOARD}="1"

Put that line in a file called /etc/udev/rules.d/10-vec-usb-footpedal.rules. No need to restart anything, udev should automatically detect the file.

Now when you unplug and replug the USB pedal, it should be recognized by X (and send mouse button events). To verify, run xev.

Remapping keysyms with udev hwdb

Having a pedal that sends only mouse clicks is probably not what you want. These key codes sent by the pedal switches can be remapped with a udev hwdb file.

Create a file under /etc/udev/hwdb.d/ (I put mine in /etc/udev/hwdb.d/60-usb-footpedal.hwdb) containing these lines: /etc/udev/hwdb.d/60-usb-footpedal.hwdb

evdev:input:b*v05F3p00FF*
 KEYBOARD_KEY_90001=f14
 KEYBOARD_KEY_90002=f15
 KEYBOARD_KEY_90003=f16

This time we do need to inform the system to update the binary hwdb file:

sudo systemd-hwdb update

And then unplug and replug the device.

The first line of the hwdb file matches our device (USB vendor ID 0x05F3, USB product ID 0x00FF), and the subsequent lines map a scancode (hex) to a keycode. I chose the F14, F15, and F16 function keys, but a list of available keycodes is defined in /usr/include/linux/input-event-codes.h; to use the names #defined in that file as hwdb keycodes, simply convert them to lowercase and remove the key_ prefix.

The default (pc+us) xkb keyboard layout on my computer maps F14, F15, and F16 to the XF86Launch5, XF86Launch6, and XF86Launch7 keysyms, respectively. If you open xev now and press the pedals, you should see those keysyms emitted. Using those keysyms, each pedal switch can be mapped as a hotkey in your desktop or window manager.

You can also remap the XF86* keysyms to other keys using something like xmodmap. For more details, including getting the keys to be mappable in vim, more links to documentation, pointers toward reading the HID device directly if you want, and a solution for Mac OS X, see my weblog post

Footcontroller

One last thing I will mention is a Python program called footcontroller that reads events from the evdev device (/dev/input/eventX) and can be configured to issue key strokes (via xdotool) or run scripts in response to stepping on the pedals. It can be used in lieu of xmodmap to get your pedal to send any key stroke you want.

Unexampled answered 28/8, 2018 at 2:59 Comment(0)
W
4

If the device shows up in /dev/input, use the "evdev" X driver to hook it up just like you would do for a keyboard or mouse.

Willhite answered 6/11, 2009 at 0:52 Comment(1)
evdev is not available for TinyCore any ideas?Ventilate
B
2

You should investigate LIRC. It interprets input from remote controls. Some supported remotes apparently present themselves as generic HID devices, so you may be able to get your device to talk to LIRC.

Bayonne answered 21/5, 2009 at 13:15 Comment(0)
A
2

Same problem here, but with special keys on a wireless keyboard. I feel your pain.

Anyway, trying to get this to work, here's my method:

  1. sleep 10; killall cat then quickly in another terminal: cat /dev/usb/hiddevice0 > key1.usbdump and press/use the device. This will dump the hiddevice's binary output for that key.
  2. I quickly hacked together a Python script to read the hiddevice input and fire events. So far it works for the first time the key is hit. This is similar to what Adam suggested, but I think uinput is more difficult to program/use although perhaps more elegant, and Python is readily available.

So this is a work in progress (only works for the first time pressed), but maybe something like this could work for you:

sf1 = open("test.usbdump").read() # Read the earlier USB dump from hiddevice
kb = open("/dev/usb/hiddev0")
while 1:
    # Prints true if the specific key has been read.
    print (kb.read(len(sf1)) == sf1)
    # Basically all that has to be done is if ^ is true, then fire off the event you want.

If anyone can help me out with my program or if I'm doing this wrong, please tell me. ;)

I realise that there are some headers being included in the initial dump of the hiddevice. Using some bless hexadecimal editing and bit differencing, you could find which values are important and make a check for them in Python. (For example, the hexadecimal digit "B0" means a special function key has been pressed on my keyboard, and later on there is more information on which key was pressed, etc.)

My end result is this: hiddevice0 seems to hang and stop giving data after a while, not sure why, but instead, I use /dev/input/event* (it might work for you too), and that seems to work better. Again, the same hexadecimal editing and low-level parsing leads to success. Along the way I found that sudo cat /dev/input/event3 | hexdump is extremely helpful in determining which bytes are important to you.

So, if you have an SK-8812 IBM keyboard, and would like to use the special keys, you can talk to me to get the script I used.

Acme answered 2/12, 2010 at 6:10 Comment(1)
In the same terminal, you can type ( sleep 10 ; killall cat ) & cat /usb/dev/hiddev0 > key1.usbdumpPuff
U
0

For my binding/shortcuts I use a combination of Compiz, easystroke and xmacro.

For your needs, I think the missing piece is xbindkeys. I have found this link for you that maybe helps you to set this up:

http://linux-trackball.dreamhosters.com/

I wonder anyway whether there is a way to distinguish between several mouse devices.

Uncommonly answered 17/5, 2009 at 9:27 Comment(1)
I already know about xbindkeys etc. but the problem is X does NOT recognize my pedal presses so xbindkeys as of now is useless. Even the author of the link you gave have some buttons on his trackball that are still not working. My question is about how to get those not working keys working, not on how to make use of the keys that already work. Sorry the for confusion.Nevsa

© 2022 - 2024 — McMap. All rights reserved.