24

What I would like to take ownership of a hid device that may already have been plugged in, consume it's output, while preventing others(X11 or terminal) from consuming it.

If I can help it, I don't want to pretend to be a terminal, but rather to monopolize a particular hid or character device. The idea is that some hid devices may be recognized as mice/keyboards by x/terminal, but a second mouse or keyboard could be used for something else, but to do that you need to make sure they aren't sending spurious input into an open terminal.

Does anyone have any insight as to how this might be done?

Catskul
  • 17,916
  • 15
  • 84
  • 113

1 Answers1

26

I have done this - my specific application was a daemon that read events from a USB HID barcode reader (which presents as a USB HID keyboard device).

To do this I used the event device interface, opening the /dev/input/event* device corresponding to the device I was after. You can then issue the EVIOCGRAB ioctl on the device, which grabs it for exclusive use, and read events (which represent keypresses, mouse movements etc) from the device as they become available.

(When the device is grabbed for exclusive use, only your application will see events from it).

caf
  • 233,326
  • 40
  • 323
  • 462
  • 2
    Sounds just what I need for a RFID reader that reads a 10-digit number from a tag and presents the information as a keyboard input so as to use as an access control device in conjunction with a Raspberry Pi Home-automation project - and still be able to log in with a keyboard/mouse/monitor for other (debugging) purposes. – SlySven Jan 10 '16 at 03:15
  • Sometimes I wonder if stackexchange was sent on Earth to save us all ! Is your project Open source ? Do you mind sharing the sources ? I'love to control a few things using custom printed QR-codes. – Michel L Jan 12 '17 at 22:49
  • @SlySven Is your project Open source too ? Do you mind sharing the sources ? – Michel L Jan 12 '17 at 22:49
  • @MichelL: I'll see if I can dig up the code but it's nothing super complicated. – caf Jan 13 '17 at 01:00
  • Ok, thank you. I think I will capture the input and send it to a REST webservice. In my case, The input is not fixed-length. – Michel L Jan 13 '17 at 07:03
  • 1
    @MichelL - it is still incomplete but eventually I'll try to make it available in my GitHub repositories - but it will be GPLed 2+ so I don't want to post it here as I've not got to the bottom of exact terms for stuff published here! Basically use `int fd= open( devPathFile", O_RDWR|O_NONBLOCK, S_IRUSR|S_IWUSR )` to open the device and get the file descriptor number `fd`, then use `ioctl( fd, EVIOCGRAB, 1 )` to grab exclusive use. Don't forget to handle the signals that will close your program so that you can release that exclusivity (though it might happen automatically on application... – SlySven Jan 13 '17 at 21:27
  • @SlySven ok, thank you. I'll see how I can handle the events with Qt. I will eventually mix Qt and non Qt code. – Michel L Jan 13 '17 at 21:32
  • ... exit anyhow!) In my case I then had to write a simple event handler to parse the keyboard events that my RFID receivers produce (as that is what they emulate but we are __intercepting__ the events that are produced so they never get to the kernel's keyboard handler as we desire!) The events are received from the open file as a number of `struct input_event` and we are particularly interested in those of type `EV_KEY` as defined in `linux/input.h`. – SlySven Jan 13 '17 at 21:36
  • Perhaps you can - just remember: "we are not inside Qt own keyboard code now, Toto". Oh, and IIRC, you usually have to be root or otherwise privileged to grab devices from the `/dev/` part of the file-system! – SlySven Jan 13 '17 at 21:38
  • For another example of handling the keyboard events that I presume you will get, the question: "[Accessing Keys from linux input device](http://stackoverflow.com/questions/20943322/accessing-keys-from-linux-input-device)" might give you some more pointers as to the code needed in a handler... – SlySven Jan 13 '17 at 21:52
  • I have a program that does this in node (not the usb exclusive reading, which is why I'm here). The interesting bits are: process.stdin.resume(); process.stdin.on("data", function (chunk) { console.log(chunk.toString()); }); process.on("SIGINT", function() { console.log("Detected Ctrl+C (SIGINT)"); process.exit(); }); – user1529413 May 24 '21 at 04:02