Fix WIRELESS_DEVICE_STATUS reconfiguration: push settings and ack with proper cookie
When a device sends WIRELESS_DEVICE_STATUS with config_needed=1, the host should re-push settings and acknowledge via ConfigChange SetComplete. The existing code relied on the push flag in changed(), but operator precedence caused push=True to be ignored for devices that have the WIRELESS_DEVICE_STATUS feature — the exact devices that send this notification. Handle the reconfiguration entirely in the notification handler: explicitly push settings and ack, rather than trying to overload the changed() condition. Also replace hardcoded cookie 0x11 with proper GetCookie/SetComplete protocol: read the device's current configuration cookie and echo it back, per the ConfigChange (0x0020) specification.
This commit is contained in:
parent
ad96dd395b
commit
a194fd285f
|
|
@ -437,6 +437,11 @@ class Device:
|
|||
if self.online and self.protocol >= 2.0:
|
||||
_hidpp20.config_change(self, configuration_, no_reply=no_reply)
|
||||
|
||||
def signal_configuration_complete(self):
|
||||
"""Read the device's config cookie and echo it back via SetComplete to ack end of configuration."""
|
||||
if self.online and self.protocol >= 2.0:
|
||||
_hidpp20.set_configuration_complete(self)
|
||||
|
||||
def reset(self, no_reply=False):
|
||||
self.set_configuration(0, no_reply)
|
||||
|
||||
|
|
@ -541,7 +546,7 @@ class Device:
|
|||
if self.protocol < 2.0: # Make sure to set notification flags on the device
|
||||
self.notification_flags = self.enable_connection_notifications()
|
||||
else:
|
||||
self.set_configuration(0x11) # signal end of configuration
|
||||
self.signal_configuration_complete()
|
||||
self.read_battery() # battery information may have changed so try to read it now
|
||||
elif was_active and self.receiver and not isinstance(self.receiver, CenturionReceiver):
|
||||
hidpp10.set_configuration_pending_flags(self.receiver, 0xFF)
|
||||
|
|
|
|||
|
|
@ -2051,7 +2051,26 @@ class Hidpp20:
|
|||
return struct.unpack("!B", result[:1])[0]
|
||||
return None
|
||||
|
||||
def get_configuration_cookie(self, device: Device):
|
||||
"""ConfigChange (0x0020) GetCookie — read the device's current configuration cookie."""
|
||||
response = device.feature_request(SupportedFeature.CONFIG_CHANGE, 0x00)
|
||||
return response[:2] if response else None
|
||||
|
||||
def set_configuration_complete(self, device: Device, cookie=None, no_reply=False):
|
||||
"""ConfigChange (0x0020) SetComplete — acknowledge host has synced with device configuration.
|
||||
|
||||
If cookie is None, reads the current cookie and increments it to mark
|
||||
a new sync point, so future cookie changes indicate device-side drift."""
|
||||
if cookie is None:
|
||||
cookie = self.get_configuration_cookie(device)
|
||||
if cookie and len(cookie) >= 2:
|
||||
value = (cookie[0] << 8 | cookie[1]) + 1 & 0xFFFF
|
||||
cookie = bytes([value >> 8, value & 0xFF])
|
||||
if cookie and len(cookie) >= 2:
|
||||
return device.feature_request(SupportedFeature.CONFIG_CHANGE, 0x10, cookie[0], cookie[1], no_reply=no_reply)
|
||||
|
||||
def config_change(self, device: Device, configuration, no_reply=False):
|
||||
"""Deprecated — use set_configuration_complete() instead."""
|
||||
return device.feature_request(SupportedFeature.CONFIG_CHANGE, 0x10, configuration, no_reply=no_reply)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ from . import diversion
|
|||
from . import hidpp10
|
||||
from . import hidpp10_constants
|
||||
from . import hidpp20
|
||||
from . import settings
|
||||
from . import settings_templates
|
||||
from .common import Alert
|
||||
from .common import BatteryStatus
|
||||
|
|
@ -324,7 +325,9 @@ def _process_feature_notification(device: Device, notification: HIDPPNotificatio
|
|||
reason = "powered on" if notification.data[2] == 1 else None
|
||||
if notification.data[1] == 1: # device is asking for software reconfiguration so need to change status
|
||||
alert = Alert.NONE
|
||||
device.changed(active=True, alert=alert, reason=reason, push=True)
|
||||
device.changed(active=True, alert=alert, reason=reason)
|
||||
settings.apply_all_settings(device)
|
||||
device.signal_configuration_complete()
|
||||
else:
|
||||
logger.warning("%s: unknown WIRELESS %s", device, notification)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue