Created
May 9, 2019 17:40
-
-
Save JasonLS/1713f3ba87ccb83267de20d4d233d2f2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import print_function | |
import re | |
import sys | |
import select | |
import atexit | |
import termios | |
import optparse | |
try: | |
input = raw_input | |
except NameError: | |
pass | |
from evdev import ecodes, list_devices, AbsInfo, InputDevice | |
def parseopt(): | |
parser = optparse.OptionParser(add_help_option=False) | |
parser.add_option('-h', '--help', action='store_true') | |
parser.add_option('-g', '--grab', action='store_true') | |
parser.add_option('-c', '--capabilities', action='store_true') | |
return parser.parse_args() | |
def main(): | |
opts, devices = parseopt() | |
if opts.help: | |
print(__doc__.strip()) | |
return 0 | |
if not devices: | |
devices = select_devices() | |
else: | |
devices = [InputDevice(path) for path in devices] | |
if opts.capabilities: | |
for device in devices: | |
print_capabilities(device) | |
return 0 | |
if opts.grab: | |
for device in devices: | |
device.grab() | |
# Disable tty echoing if stdin is a tty. | |
if sys.stdin.isatty(): | |
toggle_tty_echo(sys.stdin, enable=False) | |
atexit.register(toggle_tty_echo, sys.stdin, enable=False) | |
print('Listening for events (press ctrl-c to exit) ...') | |
fd_to_device = {dev.fd: dev for dev in devices} | |
while True: | |
r, w, e = select.select(fd_to_device, [], []) | |
for fd in r: | |
for event in fd_to_device[fd].read(): | |
print_event(event) | |
def select_devices(device_dir='/dev/input'): | |
''' | |
Select one or more devices from a list of accessible input devices. | |
''' | |
def devicenum(device_path): | |
digits = re.findall(r'\d+$', device_path) | |
return [int(i) for i in digits] | |
devices = sorted(list_devices(device_dir), key=devicenum) | |
devices = [InputDevice(path) for path in devices] | |
if not devices: | |
msg = 'error: no input devices found (do you have rw permission on %s/*?)' | |
print(msg % device_dir, file=sys.stderr) | |
sys.exit(1) | |
dev_format = '{0:<3} {1.path:<20} {1.name:<35} {1.phys:<35} {1.uniq:<4}' | |
dev_lines = [dev_format.format(num, dev) for num, dev in enumerate(devices)] | |
print('ID {:<20} {:<35} {:<35} {}'.format('Device', 'Name', 'Phys', 'Uniq')) | |
print('-' * len(max(dev_lines, key=len))) | |
print('\n'.join(dev_lines)) | |
print() | |
choices = input('Select devices [0-%s]: ' % (len(dev_lines) - 1)) | |
try: | |
choices = choices.split() | |
choices = [devices[int(num)] for num in choices] | |
except ValueError: | |
choices = None | |
if not choices: | |
msg = 'error: invalid input - please enter one or more numbers separated by spaces' | |
print(msg, file=sys.stderr) | |
sys.exit(1) | |
return choices | |
def print_capabilities(device): | |
capabilities = device.capabilities(verbose=True) | |
print('Device name: {.name}'.format(device)) | |
print('Device info: {.info}'.format(device)) | |
print('Repeat settings: {}\n'.format(device.repeat)) | |
if ('EV_LED', ecodes.EV_LED) in capabilities: | |
leds = ','.join(i[0] for i in device.leds(True)) | |
print('Active LEDs: %s' % leds) | |
active_keys = ','.join(k[0] for k in device.active_keys(True)) | |
print('Active keys: %s\n' % active_keys) | |
print('Device capabilities:') | |
for type, codes in capabilities.items(): | |
print(' Type {} {}:'.format(*type)) | |
for code in codes: | |
# code <- ('BTN_RIGHT', 273) or (['BTN_LEFT', 'BTN_MOUSE'], 272) | |
if isinstance(code[1], AbsInfo): | |
print(' Code {:<4} {}:'.format(*code[0])) | |
print(' {}'.format(code[1])) | |
else: | |
# Multiple names may resolve to one value. | |
s = ', '.join(code[0]) if isinstance(code[0], list) else code[0] | |
print(' Code {:<4} {}'.format(s, code[1])) | |
print('') | |
def print_event(e): | |
if e.type == ecodes.EV_SYN: | |
if e.code == ecodes.SYN_MT_REPORT: | |
msg = 'time {:<16} +++++++++ {} ++++++++' | |
else: | |
msg = 'time {:<16} --------- {} --------' | |
#print(msg.format(e.timestamp(), ecodes.SYN[e.code])) | |
else: | |
if e.type in ecodes.bytype: | |
codename = ecodes.bytype[e.type][e.code] | |
else: | |
codename = '?' | |
evfmt = 'time {:<16} type {} ({}), code {:<4} ({}), value {}' | |
if e.code == 0: | |
#L2 312 | |
#R2 5 | |
#LS l-R = 0 | |
#LS U-D = 1 | |
#left and up are 0 values | |
print(evfmt.format(e.timestamp(), e.type, ecodes.EV[e.type], e.code, codename, e.value)) | |
def toggle_tty_echo(fh, enable=True): | |
flags = termios.tcgetattr(fh.fileno()) | |
if enable: | |
flags[3] |= termios.ECHO | |
else: | |
flags[3] &= ~termios.ECHO | |
termios.tcsetattr(fh.fileno(), termios.TCSANOW, flags) | |
if __name__ == '__main__': | |
try: | |
ret = main() | |
except (KeyboardInterrupt, EOFError): | |
ret = 0 | |
sys.exit(ret) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment