os/linux/ RawInput
How to work out which /dev/input is which
make a threaded python program which has one thread per input, and prints out an event along with the /dev/input/
node it came from.
Look in /dev/input/by-path
See stack exchange question So if you are running X11, you can do
$ xinput
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ SynPS/2 Synaptics TouchPad id=13 [slave pointer (2)]
⎜ ↳ TPPS/2 IBM TrackPoint id=14 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
↳ Video Bus id=7 [slave keyboard (3)]
↳ Sleep Button id=8 [slave keyboard (3)]
↳ Integrated Camera: Integrated C id=11 [slave keyboard (3)]
↳ AT Translated Set 2 keyboard id=12 [slave keyboard (3)]
↳ ThinkPad Extra Buttons
/sys/class/input -- symlinks to folders in /sys/devices, e.g.
/sys/class/input/input32 =>
/sys/devices/pci0000:00/0000:00:1b.0/sound/card0/input36
Event Codes
See https://www.kernel.org/doc/html/v4.13/input/event-codes.html
How to parse /dev/input/etc
See http://www.kernel.org/doc/Documentation/input/input.txt for documentation on the format.
struct input_event {
struct timeval time;
unsigned short type;
unsigned short code;
unsigned int value;
};
Python modules
evdev
#!/usr/bin/env python3
from evdev import InputDevice
from select import select
import sys
try:
dev = InputDevice(sys.argv[1])
except IndexError:
print(f"{sys.argv[0]} /dev/input/eventX")
exit(1)
while True:
r,w,x = select([dev], [], [])
for event in dev.read():
print(event)
# event at 1337427573.061822, code 01, type 02, val 01
# event at 1337427573.061846, code 00, type 00, val 00
Code
Sample /dev/input parser in Python
#!/usr/bin/python
import struct
import time
import sys
infile_path = "/dev/input/event" + (sys.argv[1] if len(sys.argv) > 1 else "0")
"""
FORMAT represents the format used by linux kernel input event struct
See https://github.com/torvalds/linux/blob/v5.5-rc5/include/uapi/linux/input.h#L28
Stands for: long int, long int, unsigned short, unsigned short, unsigned int
"""
FORMAT = 'llHHI'
EVENT_SIZE = struct.calcsize(FORMAT)
#open file in binary mode
in_file = open(infile_path, "rb")
event = in_file.read(EVENT_SIZE)
while event:
(tv_sec, tv_usec, type, code, value) = struct.unpack(FORMAT, event)
if type != 0 or code != 0 or value != 0:
print("Event type %u, code %u, value %u at %d.%d" % \
(type, code, value, tv_sec, tv_usec))
else:
# Events with code, type and value == 0 are "separator" events
print("===========================================")
event = in_file.read(EVENT_SIZE)
in_file.close()
Threaded Event Listener
See here for more on threading.
#!/usr/bin/python
import struct
import time
import sys
from glob import glob
from threading import Thread
import socket
def send_message(host,port,message):
with socket.socket(socket.AF_INET,socket.SOCK_DGRAM) as s:
s.connect(("localhost",4005))
s.send(message)
def main():
threads = {}
args = sys.argv[1:]
if len(args) > 0:
nodes = []
for arg in args:
if arg.isnumeric():
nodes.append(f"/dev/input/event{arg}")
elif "/" in arg:
nodes.append(arg)
else:
nodes.append(f"/dev/input/{arg}")
else:
nodes = glob("/dev/input/event*")+glob("/dev/input/mouse*")+glob("/dev/input/mice")
print(nodes)
for node in nodes:
print(node)
threads[node] = start_thread(node)
def start_thread(node):
print(node)
thread = Thread(target=listen,args=(node,))
thread.start()
return thread
def listen(node):
try:
listen1(node)
except KeyboardInterrupt:
print("Ctrl-C")
exit(0)
def listen1(node):
"""
FORMAT represents the format used by linux kernel input event struct
See https://github.com/torvalds/linux/blob/v5.5-rc5/include/uapi/linux/input.h#L28
Stands for: long int, long int, unsigned short, unsigned short, unsigned int
"""
FORMAT = 'llHHI'
EVENT_SIZE = struct.calcsize(FORMAT)
#open file in binary mode
in_file = open(node, "rb")
event = in_file.read(EVENT_SIZE)
while event:
(tv_sec, tv_usec, ty, code, value) = struct.unpack(FORMAT, event)
if ty != 0 or code != 0 or value != 0:
print("%s: Event type %u, code %u, value %u at %d.%d" % \
(node, ty, code, value, tv_sec, tv_usec))
msg = "%s,%u,%u,%u@%d.%d" % (node, ty, code, value, tv_sec, tv_usec)
else:
# Events with code, type and value == 0 are "separator" events
print("===========================================")
event = in_file.read(EVENT_SIZE)
in_file.close()
if __name__ == "__main__":
main()