From d5f8a4bc45999bc18d729f03b8dd4dd8e521a832 Mon Sep 17 00:00:00 2001 From: Daniel Pavel Date: Sat, 3 Nov 2012 07:49:10 +0200 Subject: [PATCH] cleanup in the pyudev hidapi implementation, incremented app version --- app/solaar.py | 2 +- app/ui/__init__.py | 2 +- app/ui/action.py | 10 ---- lib/hidapi/__init__.py | 9 +--- lib/hidapi/native.py | 7 ++- lib/hidapi/udev.py | 73 +++++++++++++------------- lib/logitech/__init__.py | 2 +- lib/logitech/unifying_receiver/base.py | 6 ++- 8 files changed, 50 insertions(+), 61 deletions(-) diff --git a/app/solaar.py b/app/solaar.py index 4458c341..80930c09 100644 --- a/app/solaar.py +++ b/app/solaar.py @@ -2,7 +2,7 @@ APPNAME = 'Solaar' __author__ = "Daniel Pavel " -__version__ = '0.6' +__version__ = '0.7' __license__ = "GPL" # diff --git a/app/ui/__init__.py b/app/ui/__init__.py index 17a53930..f5bf6f6e 100644 --- a/app/ui/__init__.py +++ b/app/ui/__init__.py @@ -1,7 +1,7 @@ # pass APPNAME = 'Solaar' -APPVERSION = '0.6' +APPVERSION = '0.7' from . import (notify, status_icon, main_window, pair_window, action) diff --git a/app/ui/action.py b/app/ui/action.py index d8a52002..c1db5133 100644 --- a/app/ui/action.py +++ b/app/ui/action.py @@ -21,16 +21,6 @@ def _toggle_action(name, label, function, *args): action.connect('activate', function, *args) return action - -def wrap_action(action, prefire): - def _wrap(aw, aa): - prefire(aa) - aa.activate() - wrapper = _action(action.get_name(), action.get_label(), None) - wrapper.set_icon_name(action.get_icon_name()) - wrapper.connect('activate', _wrap, action) - return wrapper - # # # diff --git a/lib/hidapi/__init__.py b/lib/hidapi/__init__.py index a6f14ef7..dc19ebfa 100644 --- a/lib/hidapi/__init__.py +++ b/lib/hidapi/__init__.py @@ -1,15 +1,8 @@ """Generic Human Interface Device API.""" -from __future__ import absolute_import - __author__ = "Daniel Pavel" __license__ = "GPL" -__version__ = "0.3" - -# -# This package exists in case a future pure-Python implementation is feasible. -# - +__version__ = "0.4" try: from hidapi.udev import * diff --git a/lib/hidapi/native.py b/lib/hidapi/native.py index 16f57272..ce0b1773 100644 --- a/lib/hidapi/native.py +++ b/lib/hidapi/native.py @@ -74,7 +74,9 @@ DeviceInfo = namedtuple('DeviceInfo', [ 'release', 'manufacturer', 'product', - 'interface']) + 'interface', + 'driver', + ]) del namedtuple @@ -88,7 +90,8 @@ def _makeDeviceInfo(native_device_info): release=hex(native_device_info.release)[2:], manufacturer=native_device_info.manufacturer, product=native_device_info.product, - interface=native_device_info.interface) + interface=native_device_info.interface, + driver=None) # diff --git a/lib/hidapi/udev.py b/lib/hidapi/udev.py index b7db6fe7..46316cce 100644 --- a/lib/hidapi/udev.py +++ b/lib/hidapi/udev.py @@ -4,7 +4,7 @@ # import os as _os -import select as _select +from select import select as _select from pyudev import Context as _Context from pyudev import Device as _Device @@ -22,7 +22,9 @@ DeviceInfo = namedtuple('DeviceInfo', [ 'release', 'manufacturer', 'product', - 'interface']) + 'interface', + 'driver', + ]) del namedtuple # @@ -31,26 +33,19 @@ del namedtuple # def init(): - """Initialize the HIDAPI library. + """This function is a no-op, and exists only to match the native hidapi + implementation. - This function initializes the HIDAPI library. Calling it is not strictly - necessary, as it will be called automatically by enumerate() and any of the - open_*() functions if it is needed. This function should be called at the - beginning of execution however, if there is a chance of HIDAPI handles - being opened by different threads simultaneously. - - :returns: ``True`` if successful. + :returns: ``True``. """ return True def exit(): - """Finalize the HIDAPI library. + """This function is a no-op, and exists only to match the native hidapi + implementation. - This function frees all of the static data associated with HIDAPI. It should - be called at the end of execution to avoid memory leaks. - - :returns: ``True`` if successful. + :returns: ``True``. """ return True @@ -65,9 +60,10 @@ def enumerate(vendor_id=None, product_id=None, interface_number=None): """ for dev in _Context().list_devices(subsystem='hidraw'): hid_dev = dev.find_parent('hid') - if not hid_dev or 'HID_ID' not in hid_dev: + if not hid_dev: continue + assert 'HID_ID' in hid_dev bus, vid, pid = hid_dev['HID_ID'].split(':') if vendor_id is not None and vendor_id != int(vid, 16): continue @@ -79,7 +75,6 @@ def enumerate(vendor_id=None, product_id=None, interface_number=None): if not intf_dev: continue - # interface = int(intf_dev.attributes['bInterfaceNumber'], 16) interface = intf_dev.attributes.asint('bInterfaceNumber') if interface_number is not None and interface_number != interface: continue @@ -87,19 +82,20 @@ def enumerate(vendor_id=None, product_id=None, interface_number=None): serial = hid_dev['HID_UNIQ'] if 'HID_UNIQ' in hid_dev else None usb_dev = dev.find_parent('usb', 'usb_device') - if usb_dev: - attrs = usb_dev.attributes - devinfo = DeviceInfo(path=dev.device_node, - vendor_id=vid[-4:], - product_id=pid[-4:], - serial=serial, - release=attrs['bcdDevice'], - manufacturer=attrs['manufacturer'], - product=attrs['product'], - interface=interface) - yield devinfo + assert usb_dev + attrs = usb_dev.attributes + d_info = DeviceInfo(path=dev.device_node, + vendor_id=vid[-4:], + product_id=pid[-4:], + serial=serial, + release=attrs['bcdDevice'], + manufacturer=attrs['manufacturer'], + product=attrs['product'], + interface=interface, + driver=hid_dev['DRIVER']) + yield d_info - if bus == '0005': # BLUETOOTH + elif bus == '0005': # BLUETOOTH # TODO pass @@ -186,7 +182,7 @@ def read(device_handle, bytes_count, timeout_ms=-1): """ try: timeout = None if timeout_ms < 0 else timeout_ms / 1000.0 - rlist, wlist, xlist = _select.select([device_handle], [], [], timeout) + rlist, wlist, xlist = _select([device_handle], [], [], timeout) if rlist: assert rlist == [device_handle] return _os.read(device_handle, bytes_count) @@ -243,13 +239,18 @@ def get_indexed_string(device_handle, index): dev = _Device.from_device_number(_Context(), 'char', stat.st_rdev) if dev: hid_dev = dev.find_parent('hid') - if hid_dev and 'HID_ID' in hid_dev: + if hid_dev: + assert 'HID_ID' in hid_dev bus, _, _ = hid_dev['HID_ID'].split(':') if bus == '0003': # USB usb_dev = dev.find_parent('usb', 'usb_device') - if usb_dev: - attrs = usb_dev.attributes - key = _DEVICE_STRINGS[index] - if key in attrs: - return attrs[key] + assert usb_dev + key = _DEVICE_STRINGS[index] + attrs = usb_dev.attributes + if key in attrs: + return attrs[key] + + elif bus == '0005': # BLUETOOTH + # TODO + pass diff --git a/lib/logitech/__init__.py b/lib/logitech/__init__.py index e5a3437e..f1e61944 100644 --- a/lib/logitech/__init__.py +++ b/lib/logitech/__init__.py @@ -2,4 +2,4 @@ __author__ = "Daniel Pavel" __license__ = "GPL" -__version__ = "0.4" +__version__ = "0.5" diff --git a/lib/logitech/unifying_receiver/base.py b/lib/logitech/unifying_receiver/base.py index 12cbd07b..6165b678 100644 --- a/lib/logitech/unifying_receiver/base.py +++ b/lib/logitech/unifying_receiver/base.py @@ -75,7 +75,9 @@ def list_receiver_devices(): """List all the Linux devices exposed by the UR attached to the machine.""" # (Vendor ID, Product ID) = ('Logitech', 'Unifying Receiver') # interface 2 if the actual receiver interface - return _hid.enumerate(0x046d, 0xc52b, 2) + for d in _hid.enumerate(0x046d, 0xc52b, 2): + if d.driver is None or d.driver == 'logitech-djreceiver': + yield d _COUNT_DEVICES_REQUEST = b'\x10\xFF\x81\x00\x00\x00\x00' @@ -104,7 +106,7 @@ def try_open(path): # if this is the right hidraw device, we'll receive a 'bad device' from the UR # otherwise, the read should produce nothing - reply = _hid.read(receiver_handle, _MAX_REPLY_SIZE, DEFAULT_TIMEOUT) + reply = _hid.read(receiver_handle, _MAX_REPLY_SIZE, DEFAULT_TIMEOUT / 2) if reply: if reply[:5] == _COUNT_DEVICES_REQUEST[:5]: # 'device 0 unreachable' is the expected reply from a valid receiver handle