improved reading device properties

This commit is contained in:
Daniel Pavel 2013-06-20 12:54:27 +02:00
parent 783b317281
commit d07a20e6f8
1 changed files with 90 additions and 44 deletions

View File

@ -39,37 +39,66 @@ class PairedDevice(object):
self._codename = None self._codename = None
self._name = None self._name = None
self._protocol = None if self.receiver.unifying_supported else 1.0 unifying = self.receiver.unifying_supported
self._power_switch = None if self.receiver.unifying_supported else '(unknown)' if unifying:
self.serial = _hidpp10.get_serial(self) if self.receiver.unifying_supported else self.receiver.serial # force a reading of the codename
if self.codename is None:
raise _base.NoSuchDevice(nuber=number, receiver=receiver, error="read codename")
if self.receiver.unifying_supported: pair_info = receiver.request(0x83B5, 0x20 + number - 1)
pair_info = self.receiver.request(0x83B5, 0x20 + self.number - 1) if pair_info is None:
if pair_info: raise _base.NoSuchDevice(nuber=number, receiver=receiver, error="read pair info")
self.wpid = _strhex(pair_info[3:5])
kind = ord(pair_info[7:8]) & 0x0F self.wpid = _strhex(pair_info[3:5])
self._kind = _hidpp10.DEVICE_KIND[kind] kind = ord(pair_info[7:8]) & 0x0F
self.polling_rate = ord(pair_info[2:3]) self._kind = _hidpp10.DEVICE_KIND[kind]
self.polling_rate = ord(pair_info[2:3])
else:
# guesswork...
descriptor = _descriptors.DEVICES.get(self.receiver.product_id)
if descriptor is None:
self._codename = self.receiver.product_id
# actually there IS a device, just that we can't identify it
# raise _base.NoSuchDevice(nuber=number, receiver=receiver, product_id=receiver.product_id, failed="no descriptor")
self._name = 'Unknown device ' + self._codename
else: else:
# no device at this address... self._codename = descriptor.codename
return self._name = descriptor.name
# else: device_info = self.receiver.request(0x83B5, 0x04)
# # guesswork... assert device_info, "failed to read Nano device info"
# descriptor = _descriptors.DEVICES.get(self.receiver.product_id) self.wpid = _strhex(device_info[3:5])
# if descriptor: # self._kind = descriptor.kind
# self._kind = descriptor.kind self.polling_rate = 0
# self._codename = descriptor.codename
# self._name = descriptor.name
# device_info = self.receiver.request(0x83B5, 0x04) # the wpid is necessary to properly identify wireless link on/off notifications
# if device_info: assert self.wpid is not None, "failed to read wpid: device %d of %s" % (number, receiver)
# self.wpid = _strhex(device_info[3:5]) # the codename is necessary to guess all other info
assert self._codename is not None, "failed to read codename: device %d of %s" % (number, receiver)
# knowing the protocol as soon as possible helps reading all other info
# and avoids an unecessary ping
descriptor = _descriptors.DEVICES.get(self.codename)
if descriptor is None:
_log.warn("device without descriptor found: %s (%d of %s)", self.codename, number, receiver)
self._protocol = None if unifying else 1.0
else:
self._protocol = descriptor.protocol if unifying else 1.0 # may be None
self._power_switch = None if unifying else '(unknown)'
self.serial = _hidpp10.get_serial(self) if unifying else self.receiver.serial
self._firmware = None self._firmware = None
self._keys = None self._keys = None
self.features = _hidpp20.FeaturesArray(self) if self.receiver.unifying_supported else None if self.protocol is not None:
self.features = _hidpp20.FeaturesArray(self) if self.protocol >= 2.0 else None
elif unifying:
# may be a 2.0 device
self.features = _hidpp20.FeaturesArray(self)
else:
self.features = None
self._registers = None self._registers = None
self._settings = None self._settings = None
@ -77,6 +106,10 @@ class PairedDevice(object):
def protocol(self): def protocol(self):
if self._protocol is None: if self._protocol is None:
self._protocol = _base.ping(self.receiver.handle, self.number) self._protocol = _base.ping(self.receiver.handle, self.number)
if self._protocol is None:
descriptor = _descriptors.DEVICES.get(self.codename)
if descriptor and descriptor.protocol is not None:
self._protocol = descriptor.protocol
# _log.debug("device %d protocol %s", self.number, self._protocol) # _log.debug("device %d protocol %s", self.number, self._protocol)
return self._protocol or 0 return self._protocol or 0
@ -92,35 +125,41 @@ class PairedDevice(object):
@property @property
def codename(self): def codename(self):
if self._codename is None: if self._codename is None:
codename = self.receiver.request(0x83B5, 0x40 + self.number - 1) if self.receiver.unifying_supported:
if codename: codename = self.receiver.request(0x83B5, 0x40 + self.number - 1)
self._codename = codename[2:].rstrip(b'\x00').decode('utf-8') if codename:
# _log.debug("device %d codename %s", self.number, self._codename) self._codename = codename[2:].rstrip(b'\x00').decode('utf-8')
# _log.debug("device %d codename %s", self.number, self._codename)
return self._codename return self._codename
@property @property
def name(self): def name(self):
if self._name is None: if self._name is None:
if self.codename in _descriptors.DEVICES: if self.protocol >= 2.0:
self._name, self._kind = _descriptors.DEVICES[self._codename][:2]
elif self.protocol >= 2.0:
self._name = _hidpp20.get_name(self) self._name = _hidpp20.get_name(self)
if self._name is None:
descriptor = _descriptors.DEVICES.get(self.codename)
if descriptor and descriptor.name is not None:
self._name = descriptor.name
return self._name or self.codename or '?' return self._name or self.codename or '?'
@property @property
def kind(self): def kind(self):
if self._kind is None and self.receiver.unifying_supported: if self._kind is None:
pair_info = self.receiver.request(0x83B5, 0x20 + self.number - 1) # already handled in the constructor
if pair_info: # if self.receiver.unifying_supported:
kind = ord(pair_info[7:8]) & 0x0F # pair_info = self.receiver.request(0x83B5, 0x20 + self.number - 1)
self._kind = _hidpp10.DEVICE_KIND[kind] # if pair_info:
if self.wpid is None: # kind = ord(pair_info[7:8]) & 0x0F
self.wpid = _strhex(pair_info[3:5]) # self._kind = _hidpp10.DEVICE_KIND[kind]
# if self.wpid is None:
# self.wpid = _strhex(pair_info[3:5])
if self.protocol >= 2.0:
self._kind = _hidpp20.get_kind(self)
if self._kind is None: if self._kind is None:
if self.codename in _descriptors.DEVICES: descriptor = _descriptors.DEVICES.get(self.codename)
self._name, self._kind = _descriptors.DEVICES[self._codename][:2] if descriptor and descriptor.kind is not None:
elif self.protocol >= 2.0: self._kind = descriptor.kind
self._kind = _hidpp20.get_kind(self)
return self._kind or '?' return self._kind or '?'
@property @property
@ -135,7 +174,10 @@ class PairedDevice(object):
# @property # @property
# def serial(self): # def serial(self):
# if self._serial is None: # if self._serial is None:
# self._serial = _hidpp10.get_serial(self) # if self.receiver.unifying_supported:
# self._serial = _hidpp10.get_serial(self)
# else:
# self._serial = self.receiver.serial
# return self._serial or '?' # return self._serial or '?'
@property @property
@ -235,6 +277,7 @@ class Receiver(object):
self.handle = handle self.handle = handle
assert device_info assert device_info
self.path = device_info.path self.path = device_info.path
# USB product id
self.product_id = device_info.product_id self.product_id = device_info.product_id
# read the serial immediately, so we can find out max_devices # read the serial immediately, so we can find out max_devices
@ -306,11 +349,14 @@ class Receiver(object):
if self._devices.get(number) is not None: if self._devices.get(number) is not None:
raise IndexError("%s: device number %d already registered" % (self, number)) raise IndexError("%s: device number %d already registered" % (self, number))
dev = PairedDevice(self, number) try:
if dev.wpid: dev = PairedDevice(self, number)
assert dev.wpid
_log.info("%s: found new device %d (%s)", self, number, dev.wpid) _log.info("%s: found new device %d (%s)", self, number, dev.wpid)
self._devices[number] = dev self._devices[number] = dev
return dev return dev
except _base.NoSuchDevice:
_log.exception("register_new_device")
_log.warning("%s: looked for device %d, not found", self, number) _log.warning("%s: looked for device %d, not found", self, number)
self._devices[number] = None self._devices[number] = None