logitech_receiver: Move hidpp10 constants into new module

Related #1097
This commit is contained in:
Matthias Hagmann 2024-02-14 20:36:42 +01:00 committed by Peter F. Patel-Schneider
parent e8fdbeee8e
commit 2fcab65486
10 changed files with 201 additions and 192 deletions

View File

@ -24,8 +24,8 @@
# - the device uses a USB interface other than 2
# - the name or codename should be different from what the device reports
from .hidpp10 import DEVICE_KIND as _DK
from .hidpp10 import REGISTERS as _R
from .hidpp10_constants import DEVICE_KIND as _DK
from .hidpp10_constants import REGISTERS as _R
#
#

View File

@ -30,16 +30,18 @@ from . import base as _base
from . import descriptors as _descriptors
from . import exceptions
from . import hidpp10 as _hidpp10
from . import hidpp10_constants as _hidpp10_constants
from . import hidpp20 as _hidpp20
from . import hidpp20_constants as _hidpp20_constants
from .common import strhex as _strhex
from .settings_templates import check_feature_settings as _check_feature_settings
logger = logging.getLogger(__name__)
_R = _hidpp10.REGISTERS
_IR = _hidpp10.INFO_SUBREGISTERS
_R = _hidpp10_constants.REGISTERS
_IR = _hidpp10_constants.INFO_SUBREGISTERS
KIND_MAP = {kind: _hidpp10.DEVICE_KIND[str(kind)] for kind in _hidpp20.DEVICE_KIND}
KIND_MAP = {kind: _hidpp10_constants.DEVICE_KIND[str(kind)] for kind in _hidpp20_constants.DEVICE_KIND}
#
#
@ -124,14 +126,14 @@ class Device:
if receiver.receiver_kind == '27Mhz': # 27 Mhz receiver
self.wpid = '00' + _strhex(link_notification.data[2:3])
kind = receiver.get_kind_from_index(number)
self._kind = _hidpp10.DEVICE_KIND[kind]
self._kind = _hidpp10_constants.DEVICE_KIND[kind]
elif receiver.receiver_kind == '27Mhz': # 27 Mhz receiver doesn't have pairing registers
self.wpid = _hid.find_paired_node_wpid(receiver.path, number)
if not self.wpid:
logger.error('Unable to get wpid from udev for device %d of %s', number, receiver)
raise exceptions.NoSuchDevice(number=number, receiver=receiver, error='Not present 27Mhz device')
kind = receiver.get_kind_from_index(number)
self._kind = _hidpp10.DEVICE_KIND[kind]
self._kind = _hidpp10_constants.DEVICE_KIND[kind]
else: # get information from pairing registers
self.online = True
self.update_pairing_information()
@ -415,10 +417,10 @@ class Device:
if enable:
set_flag_bits = (
_hidpp10.NOTIFICATION_FLAG.battery_status
| _hidpp10.NOTIFICATION_FLAG.keyboard_illumination
| _hidpp10.NOTIFICATION_FLAG.wireless
| _hidpp10.NOTIFICATION_FLAG.software_present
_hidpp10_constants.NOTIFICATION_FLAG.battery_status
| _hidpp10_constants.NOTIFICATION_FLAG.keyboard_illumination
| _hidpp10_constants.NOTIFICATION_FLAG.wireless
| _hidpp10_constants.NOTIFICATION_FLAG.software_present
)
else:
set_flag_bits = 0
@ -427,7 +429,7 @@ class Device:
logger.warning('%s: failed to %s device notifications', self, 'enable' if enable else 'disable')
flag_bits = _hidpp10.get_notification_flags(self)
flag_names = None if flag_bits is None else tuple(_hidpp10.NOTIFICATION_FLAG.flag_names(flag_bits))
flag_names = None if flag_bits is None else tuple(_hidpp10_constants.NOTIFICATION_FLAG.flag_names(flag_bits))
if logger.isEnabledFor(logging.INFO):
logger.info('%s: device notifications %s %s', self, 'enabled' if enable else 'disabled', flag_names)
return flag_bits if ok else None

View File

@ -20,164 +20,14 @@ import logging
from .common import BATTERY_APPROX as _BATTERY_APPROX
from .common import FirmwareInfo as _FirmwareInfo
from .common import NamedInts as _NamedInts
from .common import bytes2int as _bytes2int
from .common import int2bytes as _int2bytes
from .common import strhex as _strhex
from .hidpp20 import BATTERY_STATUS, FIRMWARE_KIND
from .hidpp10_constants import REGISTERS
logger = logging.getLogger(__name__)
#
# Constants - most of them as defined by the official Logitech HID++ 1.0
# documentation, some of them guessed.
#
DEVICE_KIND = _NamedInts(
unknown=0x00,
keyboard=0x01,
mouse=0x02,
numpad=0x03,
presenter=0x04,
remote=0x07,
trackball=0x08,
touchpad=0x09,
headset=0x0D, # not from Logitech documentation
remote_control=0x0E, # for compatibility with HID++ 2.0
receiver=0x0F # for compatibility with HID++ 2.0
)
POWER_SWITCH_LOCATION = _NamedInts(
base=0x01,
top_case=0x02,
edge_of_top_right_corner=0x03,
top_left_corner=0x05,
bottom_left_corner=0x06,
top_right_corner=0x07,
bottom_right_corner=0x08,
top_edge=0x09,
right_edge=0x0A,
left_edge=0x0B,
bottom_edge=0x0C
)
# Some flags are used both by devices and receivers. The Logitech documentation
# mentions that the first and last (third) byte are used for devices while the
# second is used for the receiver. In practise, the second byte is also used for
# some device-specific notifications (keyboard illumination level). Do not
# simply set all notification bits if the software does not support it. For
# example, enabling keyboard_sleep_raw makes the Sleep key a no-operation unless
# the software is updated to handle that event.
# Observations:
# - wireless and software present were seen on receivers, reserved_r1b4 as well
# - the rest work only on devices as far as we can tell right now
# In the future would be useful to have separate enums for receiver and device notification flags,
# but right now we don't know enough.
# additional flags taken from https://drive.google.com/file/d/0BxbRzx7vEV7eNDBheWY0UHM5dEU/view?usp=sharing
NOTIFICATION_FLAG = _NamedInts(
numpad_numerical_keys=0x800000,
f_lock_status=0x400000,
roller_H=0x200000,
battery_status=0x100000, # send battery charge notifications (0x07 or 0x0D)
mouse_extra_buttons=0x080000,
roller_V=0x040000,
keyboard_sleep_raw=0x020000, # system control keys such as Sleep
keyboard_multimedia_raw=0x010000, # consumer controls such as Mute and Calculator
# reserved_r1b4= 0x001000, # unknown, seen on a unifying receiver
reserved5=0x008000,
reserved4=0x004000,
reserved3=0x002000,
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
mx_air_3d_gesture=0x000001,
)
ERROR = _NamedInts(
invalid_SubID__command=0x01,
invalid_address=0x02,
invalid_value=0x03,
connection_request_failed=0x04,
too_many_devices=0x05,
already_exists=0x06,
busy=0x07,
unknown_device=0x08,
resource_error=0x09,
request_unavailable=0x0A,
unsupported_parameter_value=0x0B,
wrong_pin_code=0x0C
)
PAIRING_ERRORS = _NamedInts(device_timeout=0x01, device_not_supported=0x02, too_many_devices=0x03, sequence_timeout=0x06)
BOLT_PAIRING_ERRORS = _NamedInts(device_timeout=0x01, failed=0x02)
"""Known registers.
Devices usually have a (small) sub-set of these. Some registers are only
applicable to certain device kinds (e.g. smooth_scroll only applies to mice."""
REGISTERS = _NamedInts(
# only apply to receivers
receiver_connection=0x02,
receiver_pairing=0xB2,
devices_activity=0x2B3,
receiver_info=0x2B5,
bolt_device_discovery=0xC0,
bolt_pairing=0x2C1,
bolt_uniqueId=0x02FB,
# only apply to devices
mouse_button_flags=0x01,
keyboard_hand_detection=0x01,
battery_status=0x07,
keyboard_fn_swap=0x09,
battery_charge=0x0D,
keyboard_illumination=0x17,
three_leds=0x51,
mouse_dpi=0x63,
# apply to both
notifications=0x00,
firmware=0xF1,
# notifications
passkey_request_notification=0x4D,
passkey_pressed_notification=0x4E,
device_discovery_notification=0x4F,
discovery_status_notification=0x53,
pairing_status_notification=0x54,
)
# Subregisters for receiver_info register
INFO_SUBREGISTERS = _NamedInts(
serial_number=0x01, # not found on many receivers
fw_version=0x02,
receiver_information=0x03,
pairing_information=0x20, # 0x2N, by connected device
extended_pairing_information=0x30, # 0x3N, by connected device
device_name=0x40, # 0x4N, by connected device
bolt_pairing_information=0x50, # 0x5N, by connected device
bolt_device_name=0x60, # 0x6N01, by connected device,
)
# Flags taken from https://drive.google.com/file/d/0BxbRzx7vEV7eNDBheWY0UHM5dEU/view?usp=sharing
DEVICE_FEATURES = _NamedInts(
reserved1=0x010000,
special_buttons=0x020000,
enhanced_key_usage=0x040000,
fast_fw_rev=0x080000,
reserved2=0x100000,
reserved3=0x200000,
scroll_accel=0x400000,
buttons_control_resolution=0x800000,
inhibit_lock_key_sound=0x000001,
reserved4=0x000002,
mx_air_3d_engine=0x000004,
host_control_leds=0x000008,
reserved5=0x000010,
reserved6=0x000020,
reserved7=0x000040,
reserved8=0x000080,
)
#
# functions
#

View File

@ -0,0 +1,151 @@
from .common import NamedInts
#
# Constants - most of them as defined by the official Logitech HID++ 1.0
# documentation, some of them guessed.
#
DEVICE_KIND = NamedInts(
unknown=0x00,
keyboard=0x01,
mouse=0x02,
numpad=0x03,
presenter=0x04,
remote=0x07,
trackball=0x08,
touchpad=0x09,
headset=0x0D, # not from Logitech documentation
remote_control=0x0E, # for compatibility with HID++ 2.0
receiver=0x0F # for compatibility with HID++ 2.0
)
POWER_SWITCH_LOCATION = NamedInts(
base=0x01,
top_case=0x02,
edge_of_top_right_corner=0x03,
top_left_corner=0x05,
bottom_left_corner=0x06,
top_right_corner=0x07,
bottom_right_corner=0x08,
top_edge=0x09,
right_edge=0x0A,
left_edge=0x0B,
bottom_edge=0x0C
)
# Some flags are used both by devices and receivers. The Logitech documentation
# mentions that the first and last (third) byte are used for devices while the
# second is used for the receiver. In practise, the second byte is also used for
# some device-specific notifications (keyboard illumination level). Do not
# simply set all notification bits if the software does not support it. For
# example, enabling keyboard_sleep_raw makes the Sleep key a no-operation unless
# the software is updated to handle that event.
# Observations:
# - wireless and software present were seen on receivers, reserved_r1b4 as well
# - the rest work only on devices as far as we can tell right now
# In the future would be useful to have separate enums for receiver and device notification flags,
# but right now we don't know enough.
# additional flags taken from https://drive.google.com/file/d/0BxbRzx7vEV7eNDBheWY0UHM5dEU/view?usp=sharing
NOTIFICATION_FLAG = NamedInts(
numpad_numerical_keys=0x800000,
f_lock_status=0x400000,
roller_H=0x200000,
battery_status=0x100000, # send battery charge notifications (0x07 or 0x0D)
mouse_extra_buttons=0x080000,
roller_V=0x040000,
keyboard_sleep_raw=0x020000, # system control keys such as Sleep
keyboard_multimedia_raw=0x010000, # consumer controls such as Mute and Calculator
# reserved_r1b4= 0x001000, # unknown, seen on a unifying receiver
reserved5=0x008000,
reserved4=0x004000,
reserved3=0x002000,
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
mx_air_3d_gesture=0x000001,
)
ERROR = NamedInts(
invalid_SubID__command=0x01,
invalid_address=0x02,
invalid_value=0x03,
connection_request_failed=0x04,
too_many_devices=0x05,
already_exists=0x06,
busy=0x07,
unknown_device=0x08,
resource_error=0x09,
request_unavailable=0x0A,
unsupported_parameter_value=0x0B,
wrong_pin_code=0x0C
)
PAIRING_ERRORS = NamedInts(device_timeout=0x01, device_not_supported=0x02, too_many_devices=0x03, sequence_timeout=0x06)
BOLT_PAIRING_ERRORS = NamedInts(device_timeout=0x01, failed=0x02)
"""Known registers.
Devices usually have a (small) sub-set of these. Some registers are only
applicable to certain device kinds (e.g. smooth_scroll only applies to mice."""
REGISTERS = NamedInts(
# only apply to receivers
receiver_connection=0x02,
receiver_pairing=0xB2,
devices_activity=0x2B3,
receiver_info=0x2B5,
bolt_device_discovery=0xC0,
bolt_pairing=0x2C1,
bolt_uniqueId=0x02FB,
# only apply to devices
mouse_button_flags=0x01,
keyboard_hand_detection=0x01,
battery_status=0x07,
keyboard_fn_swap=0x09,
battery_charge=0x0D,
keyboard_illumination=0x17,
three_leds=0x51,
mouse_dpi=0x63,
# apply to both
notifications=0x00,
firmware=0xF1,
# notifications
passkey_request_notification=0x4D,
passkey_pressed_notification=0x4E,
device_discovery_notification=0x4F,
discovery_status_notification=0x53,
pairing_status_notification=0x54,
)
# Subregisters for receiver_info register
INFO_SUBREGISTERS = NamedInts(
serial_number=0x01, # not found on many receivers
fw_version=0x02,
receiver_information=0x03,
pairing_information=0x20, # 0x2N, by connected device
extended_pairing_information=0x30, # 0x3N, by connected device
device_name=0x40, # 0x4N, by connected device
bolt_pairing_information=0x50, # 0x5N, by connected device
bolt_device_name=0x60, # 0x6N01, by connected device,
)
# Flags taken from https://drive.google.com/file/d/0BxbRzx7vEV7eNDBheWY0UHM5dEU/view?usp=sharing
DEVICE_FEATURES = NamedInts(
reserved1=0x010000,
special_buttons=0x020000,
enhanced_key_usage=0x040000,
fast_fw_rev=0x080000,
reserved2=0x100000,
reserved3=0x200000,
scroll_accel=0x400000,
buttons_control_resolution=0x800000,
inhibit_lock_key_sound=0x000001,
reserved4=0x000002,
mx_air_3d_engine=0x000004,
host_control_leds=0x000008,
reserved5=0x000010,
reserved6=0x000020,
reserved7=0x000040,
reserved8=0x000080,
)

View File

@ -173,7 +173,8 @@ class Receiver:
if not wpid:
logger.error('Unable to get wpid from udev for device %d of %s', n, self)
raise exceptions.NoSuchDevice(number=n, receiver=self, error='Not present 27Mhz device')
kind = _hidpp10.DEVICE_KIND[self.get_kind_from_index(n)]
kind = _hidpp10_constants.DEVICE_KIND[self.get_kind_from_index(n)]
elif not self.receiver_kind == 'unifying': # unifying protocol not supported, may be an old Nano receiver
device_info = self.read_register(_R.receiver_info, 0x04)
if device_info:
@ -197,7 +198,7 @@ class Receiver:
return '?', power_switch
pair_info = self.read_register(_R.receiver_info, _IR.extended_pairing_information + n - 1)
if pair_info:
power_switch = _hidpp10.POWER_SWITCH_LOCATION[ord(pair_info[9:10]) & 0x0F]
power_switch = _hidpp10_constants.POWER_SWITCH_LOCATION[ord(pair_info[9:10]) & 0x0F]
else: # some Nano receivers?
pair_info = self.read_register(0x2D5)
if pair_info:

View File

@ -26,7 +26,7 @@ from time import time as _time
from traceback import format_exc as _format_exc
from . import descriptors as _descriptors
from . import hidpp10 as _hidpp10
from . import hidpp10_constants as _hidpp10_constants
from . import hidpp20 as _hidpp20
from . import special_keys as _special_keys
from .base import _HIDPP_Notification as _HIDPP_Notification
@ -58,8 +58,8 @@ from .special_keys import DISABLE as _DKEY
logger = logging.getLogger(__name__)
_DK = _hidpp10.DEVICE_KIND
_R = _hidpp10.REGISTERS
_DK = _hidpp10_constants.DEVICE_KIND
_R = _hidpp10_constants.REGISTERS
_F = _hidpp20.FEATURE
_GG = _hidpp20.GESTURE

View File

@ -19,7 +19,8 @@
import logging
from . import hidpp10 as _hidpp10
from . import hidpp20 as _hidpp20
from . import hidpp10_constants as _hidpp10_constants
from . import hidpp20_constants as _hidpp20_constants
from . import settings as _settings
from .common import BATTERY_APPROX as _BATTERY_APPROX
from .common import NamedInt as _NamedInt
@ -28,7 +29,7 @@ from .i18n import _, ngettext
logger = logging.getLogger(__name__)
_R = _hidpp10.REGISTERS
_R = _hidpp10_constants.REGISTERS
#
#
@ -154,11 +155,11 @@ class DeviceStatus(dict):
# Some notifications may come with no battery level info, just
# charging state info, so do our best to infer a level (even if it is just the last level)
# It is not always possible to do this well
if status == _hidpp20.BATTERY_STATUS.full:
if status == _hidpp20_constants.BATTERY_STATUS.full:
level = _BATTERY_APPROX.full
elif status in (_hidpp20.BATTERY_STATUS.almost_full, _hidpp20.BATTERY_STATUS.recharging):
elif status in (_hidpp20_constants.BATTERY_STATUS.almost_full, _hidpp20_constants.BATTERY_STATUS.recharging):
level = _BATTERY_APPROX.good
elif status == _hidpp20.BATTERY_STATUS.slow_recharge:
elif status == _hidpp20_constants.BATTERY_STATUS.slow_recharge:
level = _BATTERY_APPROX.low
else:
level = self.get(KEYS.BATTERY_LEVEL)
@ -172,15 +173,15 @@ class DeviceStatus(dict):
old_voltage, self[KEYS.BATTERY_VOLTAGE] = self.get(KEYS.BATTERY_VOLTAGE), voltage
charging = status in (
_hidpp20.BATTERY_STATUS.recharging, _hidpp20.BATTERY_STATUS.almost_full, _hidpp20.BATTERY_STATUS.full,
_hidpp20.BATTERY_STATUS.slow_recharge
_hidpp20_constants.BATTERY_STATUS.recharging, _hidpp20_constants.BATTERY_STATUS.almost_full, _hidpp20_constants.BATTERY_STATUS.full,
_hidpp20_constants.BATTERY_STATUS.slow_recharge
)
old_charging, self[KEYS.BATTERY_CHARGING] = self.get(KEYS.BATTERY_CHARGING), charging
changed = old_level != level or old_status != status or old_charging != charging or old_voltage != voltage
alert, reason = ALERT.NONE, None
if _hidpp20.BATTERY_OK(status) and (level is None or level > _BATTERY_ATTENTION_LEVEL):
if _hidpp20_constants.BATTERY_OK(status) and (level is None or level > _BATTERY_ATTENTION_LEVEL):
self[KEYS.ERROR] = None
else:
logger.warning('%s: battery %d%%, ALERT %s', self._device, level, status)
@ -238,7 +239,7 @@ class DeviceStatus(dict):
# 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
not d.features or _hidpp20_constants.FEATURE.WIRELESS_DEVICE_STATUS not in d.features
):
if logger.isEnabledFor(logging.INFO):
logger.info('%s pushing device settings %s', d, d.settings)

View File

@ -20,10 +20,11 @@ from time import time as _timestamp
from logitech_receiver import base as _base
from logitech_receiver import hidpp10 as _hidpp10
from logitech_receiver import hidpp10_constants as _hidpp10_constants
from logitech_receiver import notifications as _notifications
from logitech_receiver import status as _status
_R = _hidpp10.REGISTERS
_R = _hidpp10_constants.REGISTERS
def run(receivers, args, find_receiver, _ignore):
@ -42,8 +43,8 @@ def run(receivers, args, find_receiver, _ignore):
# check if it's necessary to set the notification flags
old_notification_flags = _hidpp10.get_notification_flags(receiver) or 0
if not (old_notification_flags & _hidpp10.NOTIFICATION_FLAG.wireless):
_hidpp10.set_notification_flags(receiver, old_notification_flags | _hidpp10.NOTIFICATION_FLAG.wireless)
if not (old_notification_flags & _hidpp10_constants.NOTIFICATION_FLAG.wireless):
_hidpp10.set_notification_flags(receiver, old_notification_flags | _hidpp10_constants.NOTIFICATION_FLAG.wireless)
# get all current devices
known_devices = [dev.number for dev in receiver]
@ -85,7 +86,9 @@ def run(receivers, args, find_receiver, _ignore):
kind = receiver.status.device_kind
print(f'Bolt Pairing: discovered {name}')
receiver.pair_device(
address=address, authentication=authentication, entropy=20 if kind == _hidpp10.DEVICE_KIND.keyboard else 10
address=address,
authentication=authentication,
entropy=20 if kind == _hidpp10_constants.DEVICE_KIND.keyboard else 10
)
pairing_start = _timestamp()
patience = 5 # the discovering notification may come slightly later, so be patient
@ -121,7 +124,7 @@ def run(receivers, args, find_receiver, _ignore):
if n:
receiver.handle.notifications_hook(n)
if not (old_notification_flags & _hidpp10.NOTIFICATION_FLAG.wireless):
if not (old_notification_flags & _hidpp10_constants.NOTIFICATION_FLAG.wireless):
# only clear the flags if they weren't set before, otherwise a
# concurrently running Solaar app might stop working properly
_hidpp10.set_notification_flags(receiver, old_notification_flags)

View File

@ -17,11 +17,11 @@
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from logitech_receiver import base as _base
from logitech_receiver import hidpp10 as _hidpp10
from logitech_receiver import hidpp10_constants as _hidpp10_constants
from logitech_receiver.common import strhex as _strhex
from solaar.cli.show import _print_device, _print_receiver
_R = _hidpp10.REGISTERS
_R = _hidpp10_constants.REGISTERS
def run(receivers, args, find_receiver, _ignore):
@ -90,9 +90,9 @@ def run(receivers, args, find_receiver, _ignore):
last = None
for sub in range(0, 0xFF):
rgst = _base.request(receiver.handle, 0xFF, 0x8100 | reg, sub, return_error=True)
if isinstance(rgst, int) and rgst == _hidpp10.ERROR.invalid_address:
if isinstance(rgst, int) and rgst == _hidpp10_constants.ERROR.invalid_address:
break
elif isinstance(rgst, int) and rgst == _hidpp10.ERROR.invalid_value:
elif isinstance(rgst, int) and rgst == _hidpp10_constants.ERROR.invalid_value:
continue
else:
if not isinstance(last, bytes) or not isinstance(rgst, bytes) or last != rgst:
@ -104,9 +104,9 @@ def run(receivers, args, find_receiver, _ignore):
last = None
for sub in range(0, 0xFF):
rgst = _base.request(receiver.handle, 0xFF, 0x8100 | (0x200 + reg), sub, return_error=True)
if isinstance(rgst, int) and rgst == _hidpp10.ERROR.invalid_address:
if isinstance(rgst, int) and rgst == _hidpp10_constants.ERROR.invalid_address:
break
elif isinstance(rgst, int) and rgst == _hidpp10.ERROR.invalid_value:
elif isinstance(rgst, int) and rgst == _hidpp10_constants.ERROR.invalid_value:
continue
else:
if not isinstance(last, bytes) or not isinstance(rgst, bytes) or last != rgst:

View File

@ -18,6 +18,7 @@
from logitech_receiver import exceptions
from logitech_receiver import hidpp10 as _hidpp10
from logitech_receiver import hidpp10_constants as _hidpp10_constants
from logitech_receiver import hidpp20 as _hidpp20
from logitech_receiver import receiver as _receiver
from logitech_receiver import settings_templates as _settings_templates
@ -46,12 +47,12 @@ def _print_receiver(receiver):
notification_flags = _hidpp10.get_notification_flags(receiver)
if notification_flags is not None:
if notification_flags:
notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags)
notification_names = _hidpp10_constants.NOTIFICATION_FLAG.flag_names(notification_flags)
print(' Notifications: %s (0x%06X)' % (', '.join(notification_names), notification_flags))
else:
print(' Notifications: (none)')
activity = receiver.read_register(_hidpp10.REGISTERS.devices_activity)
activity = receiver.read_register(_hidpp10_constants.REGISTERS.devices_activity)
if activity:
activity = [(d, ord(activity[d - 1:d])) for d in range(1, receiver.max_devices)]
activity_text = ', '.join(('%d=%d' % (d, a)) for d, a in activity if a > 0)
@ -122,14 +123,14 @@ def _print_device(dev, num=None):
notification_flags = _hidpp10.get_notification_flags(dev)
if notification_flags is not None:
if notification_flags:
notification_names = _hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags)
notification_names = _hidpp10_constants.NOTIFICATION_FLAG.flag_names(notification_flags)
print(' Notifications: %s (0x%06X).' % (', '.join(notification_names), notification_flags))
else:
print(' Notifications: (none).')
device_features = _hidpp10.get_device_features(dev)
if device_features is not None:
if device_features:
device_features_names = _hidpp10.DEVICE_FEATURES.flag_names(device_features)
device_features_names = _hidpp10_constants.DEVICE_FEATURES.flag_names(device_features)
print(' Features: %s (0x%06X)' % (', '.join(device_features_names), device_features))
else:
print(' Features: (none)')