receiver: delay device sending first messages

This commit is contained in:
Peter F. Patel-Schneider 2022-10-06 01:08:11 -04:00
parent 4a89a79a4d
commit b957217ea8
6 changed files with 41 additions and 23 deletions

View File

@ -393,9 +393,8 @@ class Device:
if enable: if enable:
set_flag_bits = ( set_flag_bits = (
hidpp10_constants.NOTIFICATION_FLAG.battery_status hidpp10_constants.NOTIFICATION_FLAG.battery_status
| hidpp10_constants.NOTIFICATION_FLAG.keyboard_illumination | hidpp10_constants.NOTIFICATION_FLAG.ui
| hidpp10_constants.NOTIFICATION_FLAG.wireless | hidpp10_constants.NOTIFICATION_FLAG.configuration_complete
| hidpp10_constants.NOTIFICATION_FLAG.software_present
) )
else: else:
set_flag_bits = 0 set_flag_bits = 0
@ -404,8 +403,8 @@ class Device:
logger.warning("%s: failed to %s device notifications", self, "enable" if enable else "disable") logger.warning("%s: failed to %s device notifications", self, "enable" if enable else "disable")
flag_bits = _hidpp10.get_notification_flags(self) flag_bits = _hidpp10.get_notification_flags(self)
flag_names = None if flag_bits is None else tuple(hidpp10_constants.NOTIFICATION_FLAG.flag_names(flag_bits))
if logger.isEnabledFor(logging.INFO): if logger.isEnabledFor(logging.INFO):
flag_names = None if flag_bits is None else tuple(hidpp10_constants.NOTIFICATION_FLAG.flag_names(flag_bits))
logger.info("%s: device notifications %s %s", self, "enabled" if enable else "disabled", flag_names) logger.info("%s: device notifications %s %s", self, "enabled" if enable else "disabled", flag_names)
return flag_bits if ok else None return flag_bits if ok else None
@ -416,10 +415,6 @@ class Device:
self.online = active self.online = active
was_active, self._active = self._active, active was_active, self._active = self._active, active
if active: if active:
if not was_active:
if self.protocol < 2.0: # Make sure to set notification flags on the device
self.notification_flags = self.enable_connection_notifications()
self.read_battery() # battery information may have changed so try to read it now
# Push settings for new devices when devices request software reconfiguration # Push settings for new devices when devices request software reconfiguration
# and when devices become active if they don't have wireless device status feature, # and when devices become active if they don't have wireless device status feature,
if ( if (
@ -431,6 +426,14 @@ class Device:
if logger.isEnabledFor(logging.INFO): if logger.isEnabledFor(logging.INFO):
logger.info("%s pushing device settings %s", self, self.settings) logger.info("%s pushing device settings %s", self, self.settings)
settings.apply_all_settings(self) settings.apply_all_settings(self)
if not was_active:
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.read_battery() # battery information may have changed so try to read it now
elif was_active and self.receiver: # need to set configuration pending flag in receiver
hidpp10.Hidpp10().set_configuration_pending_flags(self.receiver, 0xFF)
if logger.isEnabledFor(logging.DEBUG): if logger.isEnabledFor(logging.DEBUG):
logger.debug("device %d changed: active=%s %s", self.number, self._active, self.battery_info) logger.debug("device %d changed: active=%s %s", self.number, self._active, self.battery_info)
if self.status_callback is not None: if self.status_callback is not None:

View File

@ -189,6 +189,17 @@ class Hidpp10:
assert len(flags) == 3 assert len(flags) == 3
return _bytes2int(flags) return _bytes2int(flags)
def get_configuration_pending_flags(self, receiver):
assert not receiver.isDevice
result = read_register(receiver, REGISTERS.devices_configuration)
if result is not None:
return ord(result[:1])
def set_configuration_pending_flags(self, receiver, devices):
assert not receiver.isDevice
result = write_register(receiver, REGISTERS.devices_configuration, devices)
return result is not None
def parse_battery_status(register, reply): def parse_battery_status(register, reply):
if register == REGISTERS.battery_charge: if register == REGISTERS.battery_charge:

View File

@ -73,18 +73,16 @@ NOTIFICATION_FLAG = NamedInts(
battery_status=0x100000, # send battery charge notifications (0x07 or 0x0D) battery_status=0x100000, # send battery charge notifications (0x07 or 0x0D)
mouse_extra_buttons=0x080000, mouse_extra_buttons=0x080000,
roller_V=0x040000, roller_V=0x040000,
keyboard_sleep_raw=0x020000, # system control keys such as Sleep power_keys=0x020000, # system control keys such as Sleep
keyboard_multimedia_raw=0x010000, # consumer controls such as Mute and Calculator keyboard_multimedia_raw=0x010000, # consumer controls such as Mute and Calculator
# reserved_r1b4= 0x001000, # unknown, seen on a unifying receiver multi_touch=0x001000, # notify on multi-touch changes
reserved5=0x008000, software_present=0x000800, # software is controlling part of device behaviour
reserved4=0x004000, link_quality=0x000400, # notify on link quality changes
reserved3=0x002000, ui=0x000200, # notify on UI changes
reserved2=0x001000,
software_present=0x000800, # .. no idea
reserved1=0x000400,
keyboard_illumination=0x000200, # illumination brightness level changes (by pressing keys)
wireless=0x000100, # notify when the device wireless goes on/off-line wireless=0x000100, # notify when the device wireless goes on/off-line
mx_air_3d_gesture=0x000001, configuration_complete=0x000004,
voip_telephony=0x000002,
threed_gesture=0x000001,
) )
ERROR = NamedInts( ERROR = NamedInts(
@ -119,6 +117,7 @@ REGISTERS = NamedInts(
# only apply to devices # only apply to devices
mouse_button_flags=0x01, mouse_button_flags=0x01,
keyboard_hand_detection=0x01, keyboard_hand_detection=0x01,
devices_configuration=0x03,
battery_status=0x07, battery_status=0x07,
keyboard_fn_swap=0x09, keyboard_fn_swap=0x09,
battery_charge=0x0D, battery_charge=0x0D,

View File

@ -261,6 +261,8 @@ def _process_hidpp10_notification(device, n):
bool(flags & 0x80), bool(flags & 0x80),
) )
device.link_encrypted = link_encrypted device.link_encrypted = link_encrypted
if not link_established and device.receiver:
_hidpp10.set_configuration_pending_flags(device.receiver, 0xFF)
device.changed(active=link_established) device.changed(active=link_established)
return True return True

View File

@ -80,6 +80,7 @@ class Receiver:
self.notification_flags = None self.notification_flags = None
self.pairing = Pairing() self.pairing = Pairing()
self.initialize(product_info) self.initialize(product_info)
_hidpp10.set_configuration_pending_flags(self, 0xFF)
def initialize(self, product_info: dict): def initialize(self, product_info: dict):
# read the receiver information subregister, so we can find out max_devices # read the receiver information subregister, so we can find out max_devices
@ -131,11 +132,7 @@ class Receiver:
return False return False
if enable: if enable:
set_flag_bits = ( set_flag_bits = hidpp10_constants.NOTIFICATION_FLAG.wireless | hidpp10_constants.NOTIFICATION_FLAG.software_present
hidpp10_constants.NOTIFICATION_FLAG.battery_status
| hidpp10_constants.NOTIFICATION_FLAG.wireless
| hidpp10_constants.NOTIFICATION_FLAG.software_present
)
else: else:
set_flag_bits = 0 set_flag_bits = 0
ok = _hidpp10.set_notification_flags(self, set_flag_bits) ok = _hidpp10.set_notification_flags(self, set_flag_bits)

View File

@ -35,6 +35,9 @@ def _print_receiver(receiver):
print(" Device path :", receiver.path) print(" Device path :", receiver.path)
print(" USB id : 046d:%s" % receiver.product_id) print(" USB id : 046d:%s" % receiver.product_id)
print(" Serial :", receiver.serial) print(" Serial :", receiver.serial)
pending = _hidpp10.get_configuration_pending_flags(receiver)
if pending:
print(" C Pending : %02x" % pending)
if receiver.firmware: if receiver.firmware:
for f in receiver.firmware: for f in receiver.firmware:
print(" %-11s: %s" % (f.kind, f.version)) print(" %-11s: %s" % (f.kind, f.version))
@ -225,6 +228,9 @@ def _print_device(dev, num=None):
or feature == _hidpp20_constants.FEATURE.EXTENDED_ADJUSTABLE_REPORT_RATE or feature == _hidpp20_constants.FEATURE.EXTENDED_ADJUSTABLE_REPORT_RATE
): ):
print(" Report Rate: %s" % _hidpp20.get_polling_rate(dev)) print(" Report Rate: %s" % _hidpp20.get_polling_rate(dev))
elif feature == _hidpp20_constants.FEATURE.CONFIG_CHANGE:
response = dev.feature_request(_hidpp20_constants.FEATURE.CONFIG_CHANGE, 0x10)
print(" Configuration: %s" % response.hex())
elif feature == _hidpp20_constants.FEATURE.REMAINING_PAIRING: elif feature == _hidpp20_constants.FEATURE.REMAINING_PAIRING:
print(" Remaining Pairings: %d" % _hidpp20.get_remaining_pairing(dev)) print(" Remaining Pairings: %d" % _hidpp20.get_remaining_pairing(dev))
elif feature == _hidpp20_constants.FEATURE.ONBOARD_PROFILES: elif feature == _hidpp20_constants.FEATURE.ONBOARD_PROFILES: