From 0905ed5f4333e58258c877fae2b907ea5bbbd034 Mon Sep 17 00:00:00 2001 From: "Peter F. Patel-Schneider" Date: Thu, 12 Jan 2023 08:20:01 -0500 Subject: [PATCH] device: clean up pinging code --- lib/logitech_receiver/base.py | 35 +++++++++---------------------- lib/logitech_receiver/listener.py | 32 ++-------------------------- 2 files changed, 12 insertions(+), 55 deletions(-) diff --git a/lib/logitech_receiver/base.py b/lib/logitech_receiver/base.py index adb0ff9c..0bdadda6 100644 --- a/lib/logitech_receiver/base.py +++ b/lib/logitech_receiver/base.py @@ -499,40 +499,29 @@ def request(handle, devnumber, request_id, *params, no_reply=False, return_error def ping(handle, devnumber, long_message=False): """Check if a device is connected to the receiver. - :returns: The HID protocol supported by the device, as a floating point number, if the device is active. """ if _log.isEnabledFor(_DEBUG): _log.debug('(%s) pinging device %d', handle, devnumber) - - # import inspect as _inspect - # print ('\n '.join(str(s) for s in _inspect.stack())) - with acquire_timeout(handle_lock(handle), handle, 10.): + notifications_hook = getattr(handle, 'notifications_hook', None) + try: + _skip_incoming(handle, int(handle), notifications_hook) + except NoReceiver: + _log.warn('device or receiver disconnected') + return # randomize the SoftwareId and mark byte to be able to identify the ping # reply, and set most significant (0x8) bit in SoftwareId so that the reply # is always distinguishable from notifications request_id = 0x0018 | _random_bits(3) request_data = _pack('!HBBB', request_id, 0, 0, _random_bits(8)) + write(int(handle), devnumber, request_data, long_message) - ihandle = int(handle) - notifications_hook = getattr(handle, 'notifications_hook', None) - try: - _skip_incoming(handle, ihandle, notifications_hook) - except NoReceiver: - _log.warn('device or receiver disconnected') - return - - write(ihandle, devnumber, request_data, long_message) - - # we consider timeout from this point - request_started = _timestamp() + request_started = _timestamp() # we consider timeout from this point delta = 0 - while delta < _PING_TIMEOUT: reply = _read(handle, _PING_TIMEOUT) - if reply: report_id, reply_devnumber, reply_data = reply if reply_devnumber == devnumber: @@ -540,17 +529,14 @@ def ping(handle, devnumber, long_message=False): # HID++ 2.0+ device, currently connected return ord(reply_data[2:3]) + ord(reply_data[3:4]) / 10.0 - if report_id == HIDPP_SHORT_MESSAGE_ID and reply_data[:1] == b'\x8F' and reply_data[1:3] == request_data[:2 - ]: + if report_id == HIDPP_SHORT_MESSAGE_ID and reply_data[:1] == b'\x8F' and \ + reply_data[1:3] == request_data[:2]: # error response assert reply_data[-1:] == b'\x00' error = ord(reply_data[3:4]) - if error == _hidpp10.ERROR.invalid_SubID__command: # a valid reply from a HID++ 1.0 device return 1.0 - if error == _hidpp10.ERROR.resource_error: # device unreachable return - if error == _hidpp10.ERROR.unknown_device: # no paired device with that number _log.error('(%s) device %d error on ping request: unknown device', handle, devnumber) raise NoSuchDevice(number=devnumber, request=request_id) @@ -565,4 +551,3 @@ def ping(handle, devnumber, long_message=False): delta = _timestamp() - request_started _log.warn('(%s) timeout (%0.2f/%0.2f) on device %d ping', handle, delta, _PING_TIMEOUT, devnumber) - # raise DeviceUnreachable(number=devnumber, request=request_id) diff --git a/lib/logitech_receiver/listener.py b/lib/logitech_receiver/listener.py index de0a2f68..8456f2c5 100644 --- a/lib/logitech_receiver/listener.py +++ b/lib/logitech_receiver/listener.py @@ -141,33 +141,20 @@ class EventsListener(_threading.Thread): def __init__(self, receiver, notifications_callback): super().__init__(name=self.__class__.__name__ + ':' + receiver.path.split('/')[2]) - self.daemon = True self._active = False - self.receiver = receiver self._queued_notifications = _Queue(16) self._notifications_callback = notifications_callback - # self.tick_period = 0 - def run(self): self._active = True - # replace the handle with a threaded one self.receiver.handle = _ThreadedHandle(self, self.receiver.path, self.receiver.handle) - # get the right low-level handle for this thread - ihandle = int(self.receiver.handle) if _log.isEnabledFor(_INFO): - _log.info('started with %s (%d)', self.receiver, ihandle) - + _log.info('started with %s (%d)', self.receiver, int(self.receiver.handle)) self.has_started() - # last_tick = 0 - # the first idle read -- delay it a bit, and make sure to stagger - # idle reads for multiple receivers - # idle_reads = _IDLE_READS + (ihandle % 5) * 2 - if self.receiver.isDevice: # ping (wired or BT) devices to see if they are really online if self.receiver.ping(): self.receiver.status.changed(True, reason='initialization') @@ -175,36 +162,21 @@ class EventsListener(_threading.Thread): while self._active: if self._queued_notifications.empty(): try: - # _log.debug("read next notification") n = _base.read(self.receiver.handle, _EVENT_READ_TIMEOUT) except _base.NoReceiver: _log.warning('%s disconnected', self.receiver.name) self.receiver.close() break - if n: n = _base.make_notification(*n) else: - # deliver any queued notifications - n = self._queued_notifications.get() - + n = self._queued_notifications.get() # deliver any queued notifications if n: - # if _log.isEnabledFor(_DEBUG): - # _log.debug("%s: processing %s", self.receiver, n) try: self._notifications_callback(n) except Exception: _log.exception('processing %s', n) - # elif self.tick_period: - # idle_reads -= 1 - # if idle_reads <= 0: - # idle_reads = _IDLE_READS - # now = _timestamp() - # if now - last_tick >= self.tick_period: - # last_tick = now - # self.tick(now) - del self._queued_notifications self.has_stopped()