def get_indexed_string(device_handle, index): """Get a string from a HID device, based on its string index. Note: currently not working in the ``hidraw`` native implementation. :param device_handle: a device handle returned by open() or open_path(). :param index: the index of the string to get. """ if index not in _DEVICE_STRINGS: return None assert device_handle stat = _os.fstat(device_handle) dev = _Device.from_device_number(_Context(), 'char', stat.st_rdev) if dev: hid_dev = dev.find_parent('hid') if hid_dev: assert 'HID_ID' in hid_dev bus, _ignore, _ignore = hid_dev['HID_ID'].split(':') if bus == '0003': # USB usb_dev = dev.find_parent('usb', 'usb_device') assert usb_dev key = _DEVICE_STRINGS[index] attrs = usb_dev.attributes if key in attrs: return attrs[key] elif bus == '0005': # BLUETOOTH # TODO pass
def get_indexed_string(device_handle, index): """Get a string from a HID device, based on its string index. Note: currently not working in the ``hidraw`` native implementation. :param device_handle: a device handle returned by open() or open_path(). :param index: the index of the string to get. :returns: the value corresponding to index, or None if no value found :rtype: bytes or NoneType """ try: key = _DEVICE_STRINGS[index] except KeyError: return None assert device_handle stat = _os.fstat(device_handle) try: dev = _Device.from_device_number(_Context(), 'char', stat.st_rdev) except (DeviceNotFoundError, ValueError): return None hid_dev = dev.find_parent('hid') if hid_dev: assert 'HID_ID' in hid_dev bus, _ignore, _ignore = hid_dev['HID_ID'].split(':') if bus == '0003': # USB usb_dev = dev.find_parent('usb', 'usb_device') assert usb_dev return usb_dev.attributes.get(key) elif bus == '0005': # BLUETOOTH # TODO pass
def monitor(callback, *device_filters): m = _Monitor.from_netlink(_Context()) m.filter_by(subsystem='hidraw') for action, device in m: hid_dev = device.find_parent('hid') if hid_dev: for filter in device_filters: dev_info = _match(device, hid_dev, *filter) if dev_info: callback(action, dev_info) break
def enumerate(vendor_id=None, product_id=None, interface_number=None, hid_driver=None): """Enumerate the HID Devices. List all the HID devices attached to the system, optionally filtering by vendor_id, product_id, and/or interface_number. :returns: a list of matching ``DeviceInfo`` tuples. """ for dev in _Context().list_devices(subsystem='hidraw'): dev_info = _match('add', dev, vendor_id, product_id, interface_number, hid_driver) if dev_info: yield dev_info
def monitor_glib(callback, *device_filters): from gi.repository import GLib c = _Context() # already existing devices # for device in c.list_devices(subsystem='hidraw'): # # print (device, dict(device), dict(device.attributes)) # for filter in device_filters: # d_info = _match('add', device, *filter) # if d_info: # GLib.idle_add(callback, 'add', d_info) # break m = _Monitor.from_netlink(c) m.filter_by(subsystem='hidraw') def _process_udev_event(monitor, condition, cb, filters): if condition == GLib.IO_IN: event = monitor.receive_device() if event: action, device = event # print ("***", action, device) if action == 'add': for filter in filters: d_info = _match(action, device, filter) if d_info: GLib.idle_add(cb, action, d_info) break elif action == 'remove': # the GLib notification does _not_ match! pass return True try: # io_add_watch_full may not be available... GLib.io_add_watch_full(m, GLib.PRIORITY_LOW, GLib.IO_IN, _process_udev_event, callback, device_filters) # print ("did io_add_watch_full") except AttributeError: try: # and the priority parameter appeared later in the API GLib.io_add_watch(m, GLib.PRIORITY_LOW, GLib.IO_IN, _process_udev_event, callback, device_filters) # print ("did io_add_watch with priority") except Exception: GLib.io_add_watch(m, GLib.IO_IN, _process_udev_event, callback, device_filters) # print ("did io_add_watch") m.start()
def monitor_glib(callback, *device_filters): from gi.repository import GLib c = _Context() # already existing devices # for device in c.list_devices(subsystem='hidraw'): # # print (device, dict(device), dict(device.attributes)) # for filter in device_filters: # d_info = _match('add', device, *filter) # if d_info: # GLib.idle_add(callback, 'add', d_info) # break m = _Monitor.from_netlink(c) m.filter_by(subsystem='hidraw') def _process_udev_event(monitor, condition, cb, filters): if condition == GLib.IO_IN: event = monitor.receive_device() if event: action, device = event # print ("***", action, device) if action == 'add': for filter in filters: d_info = _match(action, device, *filter) if d_info: GLib.idle_add(cb, action, d_info) break elif action == 'remove': # the GLib notification does _not_ match! pass return True try: # io_add_watch_full may not be available... GLib.io_add_watch_full(m, GLib.PRIORITY_LOW, GLib.IO_IN, _process_udev_event, callback, device_filters) # print ("did io_add_watch_full") except AttributeError: try: # and the priority parameter appeared later in the API GLib.io_add_watch(m, GLib.PRIORITY_LOW, GLib.IO_IN, _process_udev_event, callback, device_filters) # print ("did io_add_watch with priority") except: GLib.io_add_watch(m, GLib.IO_IN, _process_udev_event, callback, device_filters) # print ("did io_add_watch") m.start()
def find_paired_node_wpid(receiver_path, index): """Find the node of a device paired with a receiver, get wpid from udev""" context = _Context() receiver_phys = _Devices.from_device_file(context, receiver_path).find_parent('hid').get('HID_PHYS') if not receiver_phys: return None phys = f'{receiver_phys}:{index}' for dev in context.list_devices(subsystem='hidraw'): dev_phys = dev.find_parent('hid').get('HID_PHYS') if dev_phys and dev_phys == phys: # get hid id like 0003:0000046D:00000065 hid_id = dev.find_parent('hid').get('HID_ID') # get wpid - last 4 symbols udev_wpid = hid_id[-4:] return udev_wpid return None
def find_paired_node(receiver_path, index, timeout): """Find the node of a device paired with a receiver""" context = _Context() receiver_phys = _Devices.from_device_file(context, receiver_path).find_parent('hid').get('HID_PHYS') if not receiver_phys: return None phys = f'{receiver_phys}:{index}' timeout += _timestamp() delta = _timestamp() while delta < timeout: for dev in context.list_devices(subsystem='hidraw'): dev_phys = dev.find_parent('hid').get('HID_PHYS') if dev_phys and dev_phys == phys: return dev.device_node delta = _timestamp() return None