Skip to content

Instantly share code, notes, and snippets.

@cassc
Created September 3, 2021 12:21
Show Gist options
  • Save cassc/e801363286a40ceb1531ce45d0e88f9a to your computer and use it in GitHub Desktop.
Save cassc/e801363286a40ceb1531ce45d0e88f9a to your computer and use it in GitHub Desktop.
Search HID devices by name and listen keyboard events
# Get event id and names for connected HID devices:
# cat /proc/bus/input/devices | grep -P '^[NH]: ' | paste - -
#
# To allow current user to run this script without root:
# sudo usermod -a -G input $USER
import evdev
from evdev import InputDevice, categorize # import * is evil :)
import time
import traceback
import sys
# Provided as an example taken from my own keyboard attached to a Centos 6 box:
scancodes = {
# Scancode: ASCIICode
0: None, 1: u'ESC', 2: u'1', 3: u'2', 4: u'3', 5: u'4', 6: u'5', 7: u'6', 8: u'7', 9: u'8',
10: u'9', 11: u'0', 12: u'-', 13: u'=', 14: u'BKSP', 15: u'TAB', 16: u'Q', 17: u'W', 18: u'E', 19: u'R',
20: u'T', 21: u'Y', 22: u'U', 23: u'I', 24: u'O', 25: u'P', 26: u'[', 27: u']', 28: u'CRLF', 29: u'LCTRL',
30: u'A', 31: u'S', 32: u'D', 33: u'F', 34: u'G', 35: u'H', 36: u'J', 37: u'K', 38: u'L', 39: u';',
40: u'"', 41: u'`', 42: u'LSHFT', 43: u'\\', 44: u'Z', 45: u'X', 46: u'C', 47: u'V', 48: u'B', 49: u'N',
50: u'M', 51: u',', 52: u'.', 53: u'/', 54: u'RSHFT', 56: u'LALT', 100: u'RALT'
}
class KeyboardReader():
def __init__(self, keyword, handler=None):
self.keyword = keyword
self.devices = self.search_devices()
# device /dev/input/event21, name "Logitech K400 Plus", phys "usb-0000:00:14.0-2/input2:1"
self.handler=handler
def handle_line(self, dev, line):
print(f'Received line: {line} from {dev.phys}')
if self.handler is not None:
self.handler(dev, line)
def search_devices(self):
devs = []
while len(devs) < 1:
for p in evdev.list_devices():
dev = InputDevice(p)
if self.keyword in dev.name:
devs.append(dev)
if len(devs) < 1:
print(f'Searching for devices {self.keyword}')
time.sleep(1)
print(f'Found devices: {devs}')
return devs
def listen_device_loop(self, dev):
keyseq = []
for event in dev.read_loop():
if event.type == evdev.ecodes.EV_KEY:
data = evdev.categorize(event) # Save the event temporarily to introspect it
if data.keystate == 1: # Down events only
key = scancodes.get(data.scancode)
if key:
if key == u'CRLF':
self.handle_line(dev, ''.join(keyseq))
keyseq = []
else:
keyseq.append(key)
def start(self):
'''Blocking start handling events
'''
for dev in self.devices:
try:
self.listen_device_loop(dev)
# todo read from multiple devices
except OSError as e:
traceback.print_exc(file=sys.stdout)
self.devices = self.search_devices()
if __name__ == '__main__':
reader = KeyboardReader('Logitech')
reader.start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment