improved support for HID 1.0 devices

This commit is contained in:
Daniel Pavel 2012-11-08 11:41:09 +02:00
parent c9843e4408
commit a59ad221a1
6 changed files with 73 additions and 79 deletions

View File

@ -11,7 +11,7 @@ from logitech.unifying_receiver import api as _api
from logitech.unifying_receiver.listener import EventsListener as _EventsListener
from logitech.unifying_receiver.common import FallbackDict as _FallbackDict
from logitech import devices as _devices
from logitech.devices.constants import (STATUS, STATUS_NAME, PROPS, NAMES)
from logitech.devices.constants import (STATUS, STATUS_NAME, PROPS)
#
#
@ -107,17 +107,14 @@ class DeviceInfo(_api.PairedDevice):
"""
def __init__(self, listener, number, status=STATUS.UNKNOWN):
super(DeviceInfo, self).__init__(listener.handle, number)
self._features = _FeaturesArray(self)
self.LOG = _Logger("Device[%d]" % number)
self._listener = listener
self._serial = None
self._codename = None
self._status = status
self.props = {}
self.features = _FeaturesArray(self)
# read them now, otherwise it it temporarily hang the UI
# if status >= STATUS.CONNECTED:
# n, k, s, f = self.name, self.kind, self.serial, self.firmware
@ -155,53 +152,6 @@ class DeviceInfo(_api.PairedDevice):
t.append('Light: %d lux' % self.props[PROPS.LIGHT_LEVEL])
return ', '.join(t) if t else STATUS_NAME[STATUS.CONNECTED]
@property
def name(self):
if self._name is None:
if self._status < STATUS.CONNECTED:
codename = self.codename
if codename in NAMES:
self._name, self._kind = NAMES[codename]
elif self.features:
self._name = _api.get_device_name(self.handle, self.number, self.features)
return self._name or self.codename
@property
def kind(self):
if self._kind is None:
if self._status < STATUS.CONNECTED:
codename = self.codename
if codename in NAMES:
self._name, self._kind = NAMES[codename]
elif self.features:
self._kind = _api.get_device_kind(self.handle, self.number, self.features)
return self._kind or '?'
@property
def serial(self):
if self._serial is None:
prefix = _base.request(self.handle, 0xFF, b'\x83\xB5', 0x20 + self.number - 1)
prefix = (_base._hex(prefix[3:5]) + '-') if prefix else ''
serial = _base.request(self.handle, 0xFF, b'\x83\xB5', 0x30 + self.number - 1)
serial = _base._hex(serial[1:5]) if serial else '?'
self._serial = prefix + serial
return self._serial or '?'
@property
def codename(self):
if self._codename is None:
codename = _base.request(self.handle, 0xFF, b'\x83\xB5', 0x40 + self.number - 1)
if codename:
self._codename = codename[2:].rstrip(b'\x00').decode('ascii')
return self._codename or '?'
@property
def firmware(self):
if self._firmware is None:
if self._status >= STATUS.CONNECTED and self.features:
self._firmware = _api.get_device_firmware(self.handle, self.number, self.features)
return self._firmware or ()
def process_event(self, code, data):
if code == 0x10 and data[:1] == b'\x8F':
self.status = STATUS.UNAVAILABLE
@ -229,7 +179,7 @@ class DeviceInfo(_api.PairedDevice):
return False
def __str__(self):
return 'DeviceInfo(%d,%s,%d)' % (self.number, self._name or '?', self._status)
return '<DeviceInfo(%d,%s,%d)>' % (self.number, self._name or '?', self._status)
#
#

View File

@ -89,7 +89,7 @@ if __name__ == '__main__':
def status_changed(receiver, device=None, urgent=False):
ui.update(receiver, icon, window, device)
if ui.notify.available and urgent:
ui.notify.show(device or receiver)
GObject.idle_add(ui.notify.show, device or receiver)
global listener
if not listener:

View File

@ -22,8 +22,9 @@ def _info_text(dev):
(f.kind, f.name, ' ' if f.name else '', f.version) for f in dev.firmware])
return ('<small>'
'Serial \t\t<tt>%s</tt>\n'
'HID protocol\t<tt>%1.1f</tt>\n'
'%s'
'</small>' % (dev.serial, fw_text))
'</small>' % (dev.serial, dev.protocol, fw_text))
def _toggle_info(action, label_widget, box_widget, frame):
if action.get_active():

View File

@ -8,18 +8,26 @@ def print_receiver(receiver):
for f in receiver.firmware:
print (" %-10s: %s" % (f.kind, f.version))
print ("--------")
def scan_devices(receiver):
for dev in receiver:
print ("--------")
print (str(dev))
print ("Name: %s" % dev.name)
print ("Kind: %s" % dev.kind)
print ("Name : %s" % dev.name)
print ("Kind : %s" % dev.kind)
print ("Serial number: %s" % dev.serial)
if not dev.protocol:
print ("HID protocol : UNKNOWN")
continue
print ("HID protocol : HID %01.1f" % dev.protocol)
if dev.protocol < 2.0:
print ("Features query not supported by this device")
continue
firmware = dev.firmware
for fw in firmware:
print (" %-10s: %s %s" % (fw.kind, fw.name, fw.version))
print (" %-10s: %s %s" % (fw.kind, fw.name, fw.version))
all_features = api.get_device_features(dev.handle, dev.number)
for index in range(0, len(all_features)):

View File

@ -32,32 +32,74 @@ class PairedDevice(object):
self.handle = handle
self.number = number
self._protocol = None
self._features = None
self._codename = None
self._name = None
self._kind = None
self._serial = None
self._firmware = None
self.features = [FEATURE.ROOT]
@property
def protocol(self):
if self._protocol is None:
self._protocol = _base.ping(self.handle, self.number)
return 0 if self._protocol is None else self._protocol
@property
def features(self):
if self._features is None:
if self.protocol >= 2.0:
self._features = [FEATURE.ROOT]
return self._features
@property
def codename(self):
if self._codename is None:
codename = _base.request(self.handle, 0xFF, b'\x83\xB5', 0x40 + self.number - 1)
if codename:
self._codename = codename[2:].rstrip(b'\x00').decode('ascii')
return self._codename or '?'
@property
def name(self):
if self._name is None:
self._name = get_device_name(self.handle, self.number, self.features)
return self._name or '?'
if self.protocol < 2.0:
from ..devices.constants import NAMES as _DEVICE_NAMES
if self.codename in _DEVICE_NAMES:
self._name, self._kind = _DEVICE_NAMES[self._codename]
else:
self._name = get_device_name(self.handle, self.number, self.features)
return self._name or self.codename
@property
def kind(self):
if self._kind is None:
self._kind = get_device_kind(self.handle, self.number, self.features)
if self.protocol < 2.0:
from ..devices.constants import NAMES as _DEVICE_NAMES
if self.codename in _DEVICE_NAMES:
self._name, self._kind = _DEVICE_NAMES[self._codename]
else:
self._kind = get_device_kind(self.handle, self.number, self.features)
return self._kind or '?'
@property
def firmware(self):
if self._firmware is None:
if self._firmware is None and self.protocol >= 2.0:
self._firmware = get_device_firmware(self.handle, self.number, self.features)
return self._firmware or ()
@property
def serial(self):
if self._serial is None:
prefix = _base.request(self.handle, 0xFF, b'\x83\xB5', 0x20 + self.number - 1)
serial = _base.request(self.handle, 0xFF, b'\x83\xB5', 0x30 + self.number - 1)
if prefix and serial:
self._serial = _base._hex(prefix[3:5]) + '-' + _base._hex(serial[1:5])
return self._serial or '?'
def ping(self):
reply = _base.request(self.handle, self.number, b'\x00\x10', b'\x00\x00\xAA')
return reply is not None and reply[2:3] == b'\xAA'
return _base.ping(self.handle, self.number) is not None
def __str__(self):
return '<PairedDevice(%X,%d,%s)>' % (self.handle, self.number, self._name or '?')
@ -148,8 +190,8 @@ class Receiver(object):
if self.handle == 0:
return False
if type(dev) == int:
return (dev < 1 or dev > MAX_ATTACHED_DEVICES) and ping(self.handle, dev)
return ping(self.handle, dev.number)
return dev > 0 and dev <= MAX_ATTACHED_DEVICES and _base.ping(self.handle, dev) is not None
return dev.ping()
def __str__(self):
return '<Receiver(%X,%s)>' % (self.handle, self.path)
@ -228,20 +270,12 @@ def request(handle, devnumber, feature, function=b'\x00', params=b'', features=N
return _base.request(handle, devnumber, feature_index + function, params)
def ping(handle, devnumber):
"""
:returns: True if the device is connected to the UR.
"""
reply = _base.request(handle, devnumber, b'\x00\x10', b'\x00\x00\xAA')
return reply is not None and reply[2:3] == b'\xAA'
def get_device(handle, devnumber, features=None):
"""Gets the complete info for a device (type, features).
:returns: a PairedDevice or ``None``.
"""
if ping(handle, devnumber):
if _base.ping(handle, devnumber):
devinfo = PairedDevice(handle, devnumber)
# _log.debug("found device %s", devinfo)
return devinfo
@ -291,6 +325,7 @@ def _get_feature_index(handle, devnumber, feature, features=None):
if len(features) <= index:
features += [None] * (index + 1 - len(features))
features[index] = feature
# _log.debug("%s: found feature %s at %d", features, _base._hex(feature), index)
return index

View File

@ -85,7 +85,7 @@ class EventsListener(_Thread):
if task and task[-1] is None:
task_dev, task_data = task[:2]
if event[1] == task_dev:
_log.debug("matching %s to (%d, %s)", event, task_dev, repr(task_data))
# _log.debug("matching %s to (%d, %s)", event, task_dev, repr(task_data))
matched = event[2][:2] == task_data[:2] or (event[2][:1] in b'\x8F\xFF' and event[2][1:3] == task_data[:2])
if matched: