Source code for input.drivers.hid
from evdev import InputDevice as HID, list_devices, ecodes
from time import sleep
from helpers import setup_logger
from skeleton import InputSkeleton
logger = setup_logger(__name__, "warning")
def get_input_devices():
"""Returns list of all the available InputDevices"""
devices = []
for fn in list_devices():
try:
devices.append(HID(fn))
except:
pass
return devices
def get_path_by_name(name):
"""Gets HID device path by name, returns None if not found."""
path = None
for dev in get_input_devices():
if dev.name == name:
path = dev.fn
return path
def get_name_by_path(path):
"""Gets HID device path by name, returns None if not found."""
name = None
for dev in get_input_devices():
if dev.fn == path:
name = dev.name
return name
[docs]class InputDevice(InputSkeleton):
""" A driver for HID devices. As for now, supports keyboards and numpads."""
default_name_mapping = {"KEY_KPENTER":"KEY_ENTER", "KEY_PAGEUP":"KEY_F3", "KEY_PAGEDOWN":"KEY_F4"}
supports_key_states = True
supports_held_state = True
[docs] def __init__(self, path=None, name=None, **kwargs):
"""Initialises the ``InputDevice`` object.
Kwargs:
* ``path``: path to the input device. If not specified, you need to specify ``name``.
* ``name``: input device name
"""
if not name and not path: #No necessary arguments supplied
raise TypeError("HID device driver: expected at least path or name; got nothing. =(")
self.path = path
self.name = name
InputSkeleton.__init__(self, mapping = [], **kwargs)
self.hid_device_error_filter = False
@property
def status_available(self):
return True
@status_available.setter
def status_available(self, value):
pass
[docs] def set_available_keys(self):
if hasattr(self, 'device'):
keys = [ecodes.keys[x] for x in self.device.capabilities()[ecodes.EV_KEY] \
if isinstance(ecodes.keys[x], basestring) ]
self.available_keys = keys
else:
self.available_keys = None
def detect_device_path(self):
if not self.path:
self.path = get_path_by_name(self.name)
if not self.name:
self.name = get_name_by_path(self.path)
if not self.name and not self.path: #Seems like nothing was found by get_input_devices
raise IOError("Device not found by path and no name was provided")
def init_hw(self):
self.detect_device_path()
self.device = HID(self.path)
self.device.grab() #Can throw exception if already grabbed
return True
[docs] def runner(self):
"""Blocking event loop which just calls supplied callbacks in the keymap."""
while not self.stop_flag:
if not self.check_connection():
# Looping while the device is not found
sleep(self.connection_check_sleep)
continue
try:
event = self.device.read_one()
self.hid_device_error_filter = False
except (IOError, AttributeError) as e:
if not self.hid_device_error_filter:
logger.exception("Error while reading from the HID device {}!".format(self.path))
self.hid_device_error_filter = True
if isinstance(e, IOError) and e.errno == 11:
#raise #Uncomment only if you have nothing better to do - error seems to appear at random
continue
else:
self.connected.clear()
except Exception as e:
logger.exception("Error while reading from the HID device {}!".format(self.path))
self.connected.clear()
else:
self.process_event(event)
sleep(0.01)
def process_event(self, event):
if event is not None and event.type == ecodes.EV_KEY:
key = ecodes.keys[event.code]
value = event.value
if self.enabled:
key = self.keycode_mapping.get(key, key)
self.map_and_send_key(key, state = value)
def atexit(self):
InputSkeleton.atexit(self)
try:
self.device.ungrab()
except:
pass
if __name__ == "__main__":
print("Available device names:")
print([dev.name for dev in get_input_devices()])
#id = InputDevice(name = get_input_devices()[0].name, threaded=False)
#id.runner()