device: push settings when device requests software reconfiguration

This commit is contained in:
Peter F. Patel-Schneider 2021-12-18 10:15:57 -05:00
parent 3797c3926c
commit b7a1b81181
6 changed files with 19 additions and 21 deletions

View File

@ -69,8 +69,8 @@ DEFAULT_TIMEOUT = 4
_RECEIVER_REQUEST_TIMEOUT = 0.9
# devices may reply a lot slower, as the call has to go wireless to them and come back
_DEVICE_REQUEST_TIMEOUT = DEFAULT_TIMEOUT
# when pinging, be extra patient
_PING_TIMEOUT = DEFAULT_TIMEOUT * 2
# when pinging, be extra patient (no longer)
_PING_TIMEOUT = DEFAULT_TIMEOUT
#
# Exceptions that may be raised by this API.

View File

@ -134,7 +134,7 @@ class Device:
else:
self.path = info.path
self.handle = _hid.open_path(self.path)
self.online = True
self.online = None # a direct connected device might not be online (as reported by user)
self.product_id = info.product_id
self.bluetooth = info.bus_id == 0x0005
self.descriptor = _descriptors.get_btid(self.product_id

View File

@ -263,7 +263,7 @@ class FeaturesArray:
reply = self.device.request(0x0000, _pack('!H', FEATURE.FEATURE_SET))
if reply is None:
self.supported = False
return False # device might not be active so don't assume unsupported
else:
fs_index = ord(reply[0:1])
if fs_index:

View File

@ -174,6 +174,8 @@ def _process_device_notification(device, status, n):
else:
return _process_hidpp10_notification(device, status, n)
# These notifications are from the device itself, so it must be active
device.online = True
# At this point, we need to know the device's protocol, otherwise it's
# possible to not know how to handle it.
assert device.protocol is not None
@ -371,9 +373,7 @@ def _process_feature_notification(device, status, n, feature):
reason = 'powered on' if n.data[2] == 1 else None
if n.data[1] == 1: # device is asking for software reconfiguration so need to change status
alert = _ALERT.NONE
status.changed(active=True, alert=alert, reason=reason)
else:
_log.warn('%s: unknown WIRELESS %s', device, n)
status.changed(active=True, alert=alert, reason=reason, push=True)
else:
_log.warn('%s: unknown WIRELESS %s', device, n)

View File

@ -282,7 +282,7 @@ class DeviceStatus(dict):
self[KEYS.BATTERY_VOLTAGE] = None
self.changed()
def changed(self, active=None, alert=ALERT.NONE, reason=None, timestamp=None):
def changed(self, active=None, alert=ALERT.NONE, reason=None, push=False, timestamp=None):
assert self._changed_callback
d = self._device
# assert d # may be invalid when processing the 'unpaired' notification
@ -299,22 +299,19 @@ class DeviceStatus(dict):
if d.protocol < 2.0:
self[KEYS.NOTIFICATION_FLAGS] = d.enable_connection_notifications()
# If we've been inactive for a long time, forget anything
# about the battery. (This is probably unnecessary.)
if self.updated > 0 and timestamp - self.updated > _LONG_SLEEP:
self[KEYS.BATTERY_LEVEL] = None
self[KEYS.BATTERY_STATUS] = None
self[KEYS.BATTERY_CHARGING] = None
self[KEYS.BATTERY_VOLTAGE] = None
# battery information may have changed so try to read it now
self.read_battery(timestamp)
# Devices lose configuration when they are turned off,
# make sure they're up-to-date.
# Push settings for new devices (was_active is None),
# when devices request software reconfiguration
# and when devices become active if they don't have wireless device status feature,
if was_active is None or push or not was_active and (
not d.features or _hidpp20.FEATURE.WIRELESS_DEVICE_STATUS not in d.features
):
if _log.isEnabledFor(_INFO):
_log.info('%s pushing device settings %s', d, d.settings)
_settings.apply_all_settings(d)
# battery information may have changed so try to read it now
self.read_battery(timestamp)
else:
if was_active:
battery = self.get(KEYS.BATTERY_LEVEL)

View File

@ -78,8 +78,9 @@ class ReceiverListener(_listener.EventsListener):
assert status_changed_callback
self.status_changed_callback = status_changed_callback
_status.attach_to(receiver, self._status_changed)
if receiver.isDevice: # (wired) devices start as active
receiver.status.changed(True)
if receiver.isDevice: # ping (wired) devices to see if they are really online
if receiver.ping():
receiver.status.changed(True, reason='initialization')
def has_started(self):
if _log.isEnabledFor(_INFO):