From db8741563b1603062fd6064de7ec8ad2ce6e7a0d Mon Sep 17 00:00:00 2001 From: Matthias Hagmann <16444067+MattHag@users.noreply.github.com> Date: Wed, 14 Feb 2024 20:41:49 +0100 Subject: [PATCH] logitech_receiver: Move hidpp20 constants into new module Related #1097 --- lib/logitech_receiver/hidpp10.py | 2 +- lib/logitech_receiver/hidpp20.py | 247 +------------------ lib/logitech_receiver/hidpp20_constants.py | 248 ++++++++++++++++++++ lib/logitech_receiver/notifications.py | 7 +- lib/logitech_receiver/settings.py | 10 +- lib/logitech_receiver/settings_templates.py | 19 +- lib/logitech_receiver/status.py | 4 +- lib/solaar/cli/show.py | 39 +-- 8 files changed, 296 insertions(+), 280 deletions(-) create mode 100644 lib/logitech_receiver/hidpp20_constants.py diff --git a/lib/logitech_receiver/hidpp10.py b/lib/logitech_receiver/hidpp10.py index 2a6873d1e3..55484e8e78 100644 --- a/lib/logitech_receiver/hidpp10.py +++ b/lib/logitech_receiver/hidpp10.py @@ -23,8 +23,8 @@ 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 +from .hidpp20_constants import BATTERY_STATUS, FIRMWARE_KIND logger = logging.getLogger(__name__) diff --git a/lib/logitech_receiver/hidpp20.py b/lib/logitech_receiver/hidpp20.py index 0d4b0c37a8..bd12ef18a5 100644 --- a/lib/logitech_receiver/hidpp20.py +++ b/lib/logitech_receiver/hidpp20.py @@ -36,6 +36,8 @@ from .common import bytes2int as _bytes2int from .common import crc16 as _crc16 from .common import int2bytes as _int2bytes +from .hidpp20_constants import (BATTERY_STATUS, CHARGE_LEVEL, CHARGE_STATUS, CHARGE_TYPE, DEVICE_KIND, ERROR, FEATURE, + FIRMWARE_KIND, GESTURE) from .i18n import _ logger = logging.getLogger(__name__) @@ -51,180 +53,6 @@ def hexint_presenter(dumper, data): # # -# /,/p}' | sort -t= -k2 -# additional features names taken from https://github.com/cvuchener/hidpp and -# https://github.com/Logitech/cpg-docs/tree/master/hidpp20 -"""Possible features available on a Logitech device. - -A particular device might not support all these features, and may support other -unknown features as well. -""" -FEATURE = _NamedInts( - ROOT=0x0000, - FEATURE_SET=0x0001, - FEATURE_INFO=0x0002, - # Common - DEVICE_FW_VERSION=0x0003, - DEVICE_UNIT_ID=0x0004, - DEVICE_NAME=0x0005, - DEVICE_GROUPS=0x0006, - DEVICE_FRIENDLY_NAME=0x0007, - KEEP_ALIVE=0x0008, - CONFIG_CHANGE=0x0020, - CRYPTO_ID=0x0021, - TARGET_SOFTWARE=0x0030, - WIRELESS_SIGNAL_STRENGTH=0x0080, - DFUCONTROL_LEGACY=0x00C0, - DFUCONTROL_UNSIGNED=0x00C1, - DFUCONTROL_SIGNED=0x00C2, - DFUCONTROL=0x00C3, - DFU=0x00D0, - BATTERY_STATUS=0x1000, - BATTERY_VOLTAGE=0x1001, - UNIFIED_BATTERY=0x1004, - CHARGING_CONTROL=0x1010, - LED_CONTROL=0x1300, - FORCE_PAIRING=0x1500, - GENERIC_TEST=0x1800, - DEVICE_RESET=0x1802, - OOBSTATE=0x1805, - CONFIG_DEVICE_PROPS=0x1806, - CHANGE_HOST=0x1814, - HOSTS_INFO=0x1815, - BACKLIGHT=0x1981, - BACKLIGHT2=0x1982, - BACKLIGHT3=0x1983, - ILLUMINATION=0x1990, - PRESENTER_CONTROL=0x1A00, - SENSOR_3D=0x1A01, - REPROG_CONTROLS=0x1B00, - REPROG_CONTROLS_V2=0x1B01, - REPROG_CONTROLS_V2_2=0x1B02, # LogiOptions 2.10.73 features.xml - REPROG_CONTROLS_V3=0x1B03, - REPROG_CONTROLS_V4=0x1B04, - REPORT_HID_USAGE=0x1BC0, - PERSISTENT_REMAPPABLE_ACTION=0x1C00, - WIRELESS_DEVICE_STATUS=0x1D4B, - REMAINING_PAIRING=0x1DF0, - FIRMWARE_PROPERTIES=0x1F1F, - ADC_MEASUREMENT=0x1F20, - # Mouse - LEFT_RIGHT_SWAP=0x2001, - SWAP_BUTTON_CANCEL=0x2005, - POINTER_AXIS_ORIENTATION=0x2006, - VERTICAL_SCROLLING=0x2100, - SMART_SHIFT=0x2110, - SMART_SHIFT_ENHANCED=0x2111, - HI_RES_SCROLLING=0x2120, - HIRES_WHEEL=0x2121, - LOWRES_WHEEL=0x2130, - THUMB_WHEEL=0x2150, - MOUSE_POINTER=0x2200, - ADJUSTABLE_DPI=0x2201, - EXTENDED_ADJUSTABLE_DPI=0x2202, - POINTER_SPEED=0x2205, - ANGLE_SNAPPING=0x2230, - SURFACE_TUNING=0x2240, - XY_STATS=0x2250, - WHEEL_STATS=0x2251, - HYBRID_TRACKING=0x2400, - # Keyboard - FN_INVERSION=0x40A0, - NEW_FN_INVERSION=0x40A2, - K375S_FN_INVERSION=0x40A3, - ENCRYPTION=0x4100, - LOCK_KEY_STATE=0x4220, - SOLAR_DASHBOARD=0x4301, - KEYBOARD_LAYOUT=0x4520, - KEYBOARD_DISABLE_KEYS=0x4521, - KEYBOARD_DISABLE_BY_USAGE=0x4522, - DUALPLATFORM=0x4530, - MULTIPLATFORM=0x4531, - KEYBOARD_LAYOUT_2=0x4540, - CROWN=0x4600, - # Touchpad - TOUCHPAD_FW_ITEMS=0x6010, - TOUCHPAD_SW_ITEMS=0x6011, - TOUCHPAD_WIN8_FW_ITEMS=0x6012, - TAP_ENABLE=0x6020, - TAP_ENABLE_EXTENDED=0x6021, - CURSOR_BALLISTIC=0x6030, - TOUCHPAD_RESOLUTION=0x6040, - TOUCHPAD_RAW_XY=0x6100, - TOUCHMOUSE_RAW_POINTS=0x6110, - TOUCHMOUSE_6120=0x6120, - GESTURE=0x6500, - GESTURE_2=0x6501, - # Gaming Devices - GKEY=0x8010, - MKEYS=0x8020, - MR=0x8030, - BRIGHTNESS_CONTROL=0x8040, - REPORT_RATE=0x8060, - EXTENDED_ADJUSTABLE_REPORT_RATE=0x8061, - COLOR_LED_EFFECTS=0x8070, - RGB_EFFECTS=0x8071, - PER_KEY_LIGHTING=0x8080, - PER_KEY_LIGHTING_V2=0x8081, - MODE_STATUS=0x8090, - ONBOARD_PROFILES=0x8100, - MOUSE_BUTTON_SPY=0x8110, - LATENCY_MONITORING=0x8111, - GAMING_ATTACHMENTS=0x8120, - FORCE_FEEDBACK=0x8123, - # Headsets - SIDETONE=0x8300, - EQUALIZER=0x8310, - HEADSET_OUT=0x8320, - # Fake features for Solaar internal use - MOUSE_GESTURE=0xFE00, -) -FEATURE._fallback = lambda x: 'unknown:%04X' % x - -FEATURE_FLAG = _NamedInts(internal=0x20, hidden=0x40, obsolete=0x80) - -DEVICE_KIND = _NamedInts( - keyboard=0x00, remote_control=0x01, numpad=0x02, mouse=0x03, touchpad=0x04, trackball=0x05, presenter=0x06, receiver=0x07 -) - -FIRMWARE_KIND = _NamedInts(Firmware=0x00, Bootloader=0x01, Hardware=0x02, Other=0x03) - -BATTERY_OK = lambda status: status not in (BATTERY_STATUS.invalid_battery, BATTERY_STATUS.thermal_error) - -BATTERY_STATUS = _NamedInts( - discharging=0x00, - recharging=0x01, - almost_full=0x02, - full=0x03, - slow_recharge=0x04, - invalid_battery=0x05, - thermal_error=0x06 -) - -ONBOARD_MODES = _NamedInts(MODE_NO_CHANGE=0x00, MODE_ONBOARD=0x01, MODE_HOST=0x02) - -CHARGE_STATUS = _NamedInts(charging=0x00, full=0x01, not_charging=0x02, error=0x07) - -CHARGE_LEVEL = _NamedInts(average=50, full=90, critical=5) - -CHARGE_TYPE = _NamedInts(standard=0x00, fast=0x01, slow=0x02) - -ERROR = _NamedInts( - unknown=0x01, - invalid_argument=0x02, - out_of_range=0x03, - hardware_error=0x04, - logitech_internal=0x05, - invalid_feature_index=0x06, - invalid_function=0x07, - busy=0x08, - unsupported=0x09 -) - -# -# -# - class FeaturesArray(dict): @@ -745,71 +573,6 @@ def _query_key(self, index: int): logger.warn(f"Key with index {index} was expected to exist but device doesn't report it.") -# Gesture Ids for feature GESTURE_2 -GESTURE = _NamedInts( - Tap1Finger=1, # task Left_Click - Tap2Finger=2, # task Right_Click - Tap3Finger=3, - Click1Finger=4, # task Left_Click - Click2Finger=5, # task Right_Click - Click3Finger=6, - DoubleTap1Finger=10, - DoubleTap2Finger=11, - DoubleTap3Finger=12, - Track1Finger=20, # action MovePointer - TrackingAcceleration=21, - TapDrag1Finger=30, # action Drag - TapDrag2Finger=31, # action SecondaryDrag - Drag3Finger=32, - TapGestures=33, # group all tap gestures under a single UI setting - FnClickGestureSuppression=34, # suppresses Tap and Edge gestures, toggled by Fn+Click - Scroll1Finger=40, # action ScrollOrPageXY / ScrollHorizontal - Scroll2Finger=41, # action ScrollOrPageXY / ScrollHorizontal - Scroll2FingerHoriz=42, # action ScrollHorizontal - Scroll2FingerVert=43, # action WheelScrolling - Scroll2FingerStateless=44, - NaturalScrolling=45, # affects native HID wheel reporting by gestures, not when diverted - Thumbwheel=46, # action WheelScrolling - VScrollInertia=48, - VScrollBallistics=49, - Swipe2FingerHoriz=50, # action PageScreen - Swipe3FingerHoriz=51, # action PageScreen - Swipe4FingerHoriz=52, # action PageScreen - Swipe3FingerVert=53, - Swipe4FingerVert=54, - LeftEdgeSwipe1Finger=60, - RightEdgeSwipe1Finger=61, - BottomEdgeSwipe1Finger=62, - TopEdgeSwipe1Finger=63, - LeftEdgeSwipe1Finger2=64, # task HorzScrollNoRepeatSet - RightEdgeSwipe1Finger2=65, # task 122 ?? - BottomEdgeSwipe1Finger2=66, # - TopEdgeSwipe1Finger2=67, # task 121 ?? - LeftEdgeSwipe2Finger=70, - RightEdgeSwipe2Finger=71, - BottomEdgeSwipe2Finger=72, - TopEdgeSwipe2Finger=73, - Zoom2Finger=80, # action Zoom - Zoom2FingerPinch=81, # ZoomBtnInSet - Zoom2FingerSpread=82, # ZoomBtnOutSet - Zoom3Finger=83, - Zoom2FingerStateless=84, # action Zoom - TwoFingersPresent=85, - Rotate2Finger=87, - Finger1=90, - Finger2=91, - Finger3=92, - Finger4=93, - Finger5=94, - Finger6=95, - Finger7=96, - Finger8=97, - Finger9=98, - Finger10=99, - DeviceSpecificRawData=100, -) -GESTURE._fallback = lambda x: 'unknown:%04X' % x - # Param Ids for feature GESTURE_2 PARAM = _NamedInts( ExtraCapabilities=1, # not suitable for use @@ -911,9 +674,11 @@ def _offset_mask(self, index): # offset and mask else: return (None, None) - enable_offset_mask = lambda gesture: gesture._offset_mask(gesture.index) + def enable_offset_mask(gesture): + return gesture._offset_mask(gesture.index) - diversion_offset_mask = lambda gesture: gesture._offset_mask(gesture.diversion_index) + def diversion_offset_mask(gesture): + return gesture._offset_mask(gesture.diversion_index) def enabled(self): # is the gesture enabled? if self._enabled is None and self.index is not None: diff --git a/lib/logitech_receiver/hidpp20_constants.py b/lib/logitech_receiver/hidpp20_constants.py new file mode 100644 index 0000000000..72cc5e272b --- /dev/null +++ b/lib/logitech_receiver/hidpp20_constants.py @@ -0,0 +1,248 @@ +from .common import NamedInts + +# /,/p}' | sort -t= -k2 +# additional features names taken from https://github.com/cvuchener/hidpp and +# https://github.com/Logitech/cpg-docs/tree/master/hidpp20 +"""Possible features available on a Logitech device. + +A particular device might not support all these features, and may support other +unknown features as well. +""" +FEATURE = NamedInts( + ROOT=0x0000, + FEATURE_SET=0x0001, + FEATURE_INFO=0x0002, + # Common + DEVICE_FW_VERSION=0x0003, + DEVICE_UNIT_ID=0x0004, + DEVICE_NAME=0x0005, + DEVICE_GROUPS=0x0006, + DEVICE_FRIENDLY_NAME=0x0007, + KEEP_ALIVE=0x0008, + CONFIG_CHANGE=0x0020, + CRYPTO_ID=0x0021, + TARGET_SOFTWARE=0x0030, + WIRELESS_SIGNAL_STRENGTH=0x0080, + DFUCONTROL_LEGACY=0x00C0, + DFUCONTROL_UNSIGNED=0x00C1, + DFUCONTROL_SIGNED=0x00C2, + DFUCONTROL=0x00C3, + DFU=0x00D0, + BATTERY_STATUS=0x1000, + BATTERY_VOLTAGE=0x1001, + UNIFIED_BATTERY=0x1004, + CHARGING_CONTROL=0x1010, + LED_CONTROL=0x1300, + FORCE_PAIRING=0x1500, + GENERIC_TEST=0x1800, + DEVICE_RESET=0x1802, + OOBSTATE=0x1805, + CONFIG_DEVICE_PROPS=0x1806, + CHANGE_HOST=0x1814, + HOSTS_INFO=0x1815, + BACKLIGHT=0x1981, + BACKLIGHT2=0x1982, + BACKLIGHT3=0x1983, + ILLUMINATION=0x1990, + PRESENTER_CONTROL=0x1A00, + SENSOR_3D=0x1A01, + REPROG_CONTROLS=0x1B00, + REPROG_CONTROLS_V2=0x1B01, + REPROG_CONTROLS_V2_2=0x1B02, # LogiOptions 2.10.73 features.xml + REPROG_CONTROLS_V3=0x1B03, + REPROG_CONTROLS_V4=0x1B04, + REPORT_HID_USAGE=0x1BC0, + PERSISTENT_REMAPPABLE_ACTION=0x1C00, + WIRELESS_DEVICE_STATUS=0x1D4B, + REMAINING_PAIRING=0x1DF0, + FIRMWARE_PROPERTIES=0x1F1F, + ADC_MEASUREMENT=0x1F20, + # Mouse + LEFT_RIGHT_SWAP=0x2001, + SWAP_BUTTON_CANCEL=0x2005, + POINTER_AXIS_ORIENTATION=0x2006, + VERTICAL_SCROLLING=0x2100, + SMART_SHIFT=0x2110, + SMART_SHIFT_ENHANCED=0x2111, + HI_RES_SCROLLING=0x2120, + HIRES_WHEEL=0x2121, + LOWRES_WHEEL=0x2130, + THUMB_WHEEL=0x2150, + MOUSE_POINTER=0x2200, + ADJUSTABLE_DPI=0x2201, + EXTENDED_ADJUSTABLE_DPI=0x2202, + POINTER_SPEED=0x2205, + ANGLE_SNAPPING=0x2230, + SURFACE_TUNING=0x2240, + XY_STATS=0x2250, + WHEEL_STATS=0x2251, + HYBRID_TRACKING=0x2400, + # Keyboard + FN_INVERSION=0x40A0, + NEW_FN_INVERSION=0x40A2, + K375S_FN_INVERSION=0x40A3, + ENCRYPTION=0x4100, + LOCK_KEY_STATE=0x4220, + SOLAR_DASHBOARD=0x4301, + KEYBOARD_LAYOUT=0x4520, + KEYBOARD_DISABLE_KEYS=0x4521, + KEYBOARD_DISABLE_BY_USAGE=0x4522, + DUALPLATFORM=0x4530, + MULTIPLATFORM=0x4531, + KEYBOARD_LAYOUT_2=0x4540, + CROWN=0x4600, + # Touchpad + TOUCHPAD_FW_ITEMS=0x6010, + TOUCHPAD_SW_ITEMS=0x6011, + TOUCHPAD_WIN8_FW_ITEMS=0x6012, + TAP_ENABLE=0x6020, + TAP_ENABLE_EXTENDED=0x6021, + CURSOR_BALLISTIC=0x6030, + TOUCHPAD_RESOLUTION=0x6040, + TOUCHPAD_RAW_XY=0x6100, + TOUCHMOUSE_RAW_POINTS=0x6110, + TOUCHMOUSE_6120=0x6120, + GESTURE=0x6500, + GESTURE_2=0x6501, + # Gaming Devices + GKEY=0x8010, + MKEYS=0x8020, + MR=0x8030, + BRIGHTNESS_CONTROL=0x8040, + REPORT_RATE=0x8060, + EXTENDED_ADJUSTABLE_REPORT_RATE=0x8061, + COLOR_LED_EFFECTS=0x8070, + RGB_EFFECTS=0x8071, + PER_KEY_LIGHTING=0x8080, + PER_KEY_LIGHTING_V2=0x8081, + MODE_STATUS=0x8090, + ONBOARD_PROFILES=0x8100, + MOUSE_BUTTON_SPY=0x8110, + LATENCY_MONITORING=0x8111, + GAMING_ATTACHMENTS=0x8120, + FORCE_FEEDBACK=0x8123, + # Headsets + SIDETONE=0x8300, + EQUALIZER=0x8310, + HEADSET_OUT=0x8320, + # Fake features for Solaar internal use + MOUSE_GESTURE=0xFE00, +) +FEATURE._fallback = lambda x: 'unknown:%04X' % x + +FEATURE_FLAG = NamedInts(internal=0x20, hidden=0x40, obsolete=0x80) + +DEVICE_KIND = NamedInts( + keyboard=0x00, remote_control=0x01, numpad=0x02, mouse=0x03, touchpad=0x04, trackball=0x05, presenter=0x06, receiver=0x07 +) + +FIRMWARE_KIND = NamedInts(Firmware=0x00, Bootloader=0x01, Hardware=0x02, Other=0x03) + + +def BATTERY_OK(status): + return status not in (BATTERY_STATUS.invalid_battery, BATTERY_STATUS.thermal_error) + + +BATTERY_STATUS = NamedInts( + discharging=0x00, + recharging=0x01, + almost_full=0x02, + full=0x03, + slow_recharge=0x04, + invalid_battery=0x05, + thermal_error=0x06 +) + +ONBOARD_MODES = NamedInts(MODE_NO_CHANGE=0x00, MODE_ONBOARD=0x01, MODE_HOST=0x02) + +CHARGE_STATUS = NamedInts(charging=0x00, full=0x01, not_charging=0x02, error=0x07) + +CHARGE_LEVEL = NamedInts(average=50, full=90, critical=5) + +CHARGE_TYPE = NamedInts(standard=0x00, fast=0x01, slow=0x02) + +ERROR = NamedInts( + unknown=0x01, + invalid_argument=0x02, + out_of_range=0x03, + hardware_error=0x04, + logitech_internal=0x05, + invalid_feature_index=0x06, + invalid_function=0x07, + busy=0x08, + unsupported=0x09 +) + +# Gesture Ids for feature GESTURE_2 +GESTURE = NamedInts( + Tap1Finger=1, # task Left_Click + Tap2Finger=2, # task Right_Click + Tap3Finger=3, + Click1Finger=4, # task Left_Click + Click2Finger=5, # task Right_Click + Click3Finger=6, + DoubleTap1Finger=10, + DoubleTap2Finger=11, + DoubleTap3Finger=12, + Track1Finger=20, # action MovePointer + TrackingAcceleration=21, + TapDrag1Finger=30, # action Drag + TapDrag2Finger=31, # action SecondaryDrag + Drag3Finger=32, + TapGestures=33, # group all tap gestures under a single UI setting + FnClickGestureSuppression=34, # suppresses Tap and Edge gestures, toggled by Fn+Click + Scroll1Finger=40, # action ScrollOrPageXY / ScrollHorizontal + Scroll2Finger=41, # action ScrollOrPageXY / ScrollHorizontal + Scroll2FingerHoriz=42, # action ScrollHorizontal + Scroll2FingerVert=43, # action WheelScrolling + Scroll2FingerStateless=44, + NaturalScrolling=45, # affects native HID wheel reporting by gestures, not when diverted + Thumbwheel=46, # action WheelScrolling + VScrollInertia=48, + VScrollBallistics=49, + Swipe2FingerHoriz=50, # action PageScreen + Swipe3FingerHoriz=51, # action PageScreen + Swipe4FingerHoriz=52, # action PageScreen + Swipe3FingerVert=53, + Swipe4FingerVert=54, + LeftEdgeSwipe1Finger=60, + RightEdgeSwipe1Finger=61, + BottomEdgeSwipe1Finger=62, + TopEdgeSwipe1Finger=63, + LeftEdgeSwipe1Finger2=64, # task HorzScrollNoRepeatSet + RightEdgeSwipe1Finger2=65, # task 122 ?? + BottomEdgeSwipe1Finger2=66, # + TopEdgeSwipe1Finger2=67, # task 121 ?? + LeftEdgeSwipe2Finger=70, + RightEdgeSwipe2Finger=71, + BottomEdgeSwipe2Finger=72, + TopEdgeSwipe2Finger=73, + Zoom2Finger=80, # action Zoom + Zoom2FingerPinch=81, # ZoomBtnInSet + Zoom2FingerSpread=82, # ZoomBtnOutSet + Zoom3Finger=83, + Zoom2FingerStateless=84, # action Zoom + TwoFingersPresent=85, + Rotate2Finger=87, + Finger1=90, + Finger2=91, + Finger3=92, + Finger4=93, + Finger5=94, + Finger6=95, + Finger7=96, + Finger8=97, + Finger9=98, + Finger10=99, + DeviceSpecificRawData=100, +) +GESTURE._fallback = lambda x: 'unknown:%04X' % x + +# Param Ids for feature GESTURE_2 +PARAM = NamedInts( + ExtraCapabilities=1, # not suitable for use + PixelZone=2, # 4 2-byte integers, left, bottom, width, height; pixels + RatioZone=3, # 4 bytes, left, bottom, width, height; unit 1/240 pad size + ScaleFactor=4, # 2-byte integer, with 256 as normal scale +) +PARAM._fallback = lambda x: 'unknown:%04X' % x diff --git a/lib/logitech_receiver/notifications.py b/lib/logitech_receiver/notifications.py index 4dbb3db375..da94bb11d6 100644 --- a/lib/logitech_receiver/notifications.py +++ b/lib/logitech_receiver/notifications.py @@ -25,6 +25,7 @@ from . import diversion as _diversion from . import hidpp10 as _hidpp10 from . import hidpp20 as _hidpp20 +from . import hidpp20_constants as _hidpp20_constants from . import settings_templates as _st from .base import DJ_MESSAGE_ID as _DJ_MESSAGE_ID from .common import strhex as _strhex @@ -35,7 +36,7 @@ logger = logging.getLogger(__name__) _R = _hidpp10.REGISTERS -_F = _hidpp20.FEATURE +_F = _hidpp20_constants.FEATURE # # @@ -351,14 +352,14 @@ def _process_feature_notification(device, status, n, feature): charge, lux, adc = _unpack('!BHH', n.data[:5]) # guesstimate the battery voltage, emphasis on 'guess' # status_text = '%1.2fV' % (adc * 2.67793237653 / 0x0672) - status_text = _hidpp20.BATTERY_STATUS.discharging + status_text = _hidpp20_constants.BATTERY_STATUS.discharging if n.address == 0x00: status[_K.LIGHT_LEVEL] = None status.set_battery_info(charge, None, status_text, None) elif n.address == 0x10: status[_K.LIGHT_LEVEL] = lux if lux > 200: - status_text = _hidpp20.BATTERY_STATUS.recharging + status_text = _hidpp20_constants.BATTERY_STATUS.recharging status.set_battery_info(charge, None, status_text, None) elif n.address == 0x20: if logger.isEnabledFor(logging.DEBUG): diff --git a/lib/logitech_receiver/settings.py b/lib/logitech_receiver/settings.py index 5bc136b389..23f17d7334 100644 --- a/lib/logitech_receiver/settings.py +++ b/lib/logitech_receiver/settings.py @@ -22,7 +22,7 @@ from struct import unpack as _unpack from time import sleep as _sleep -from . import hidpp20 as _hidpp20 +from . import hidpp20_constants as _hidpp20_constants from .common import NamedInt as _NamedInt from .common import NamedInts as _NamedInts from .common import bytes2int as _bytes2int @@ -1416,7 +1416,7 @@ def read(self, device): # need to return bytes, as if read from device def write(self, device, data_bytes): def handler(device, n): # Called on notification events from the device - if n.sub_id < 0x40 and device.features.get_feature(n.sub_id) == _hidpp20.FEATURE.REPROG_CONTROLS_V4: + if n.sub_id < 0x40 and device.features.get_feature(n.sub_id) == _hidpp20_constants.FEATURE.REPROG_CONTROLS_V4: if n.address == 0x00: cids = _unpack('!HHHH', n.data[:8]) if not self.pressed and int(self.key.key) in cids: # trigger key pressed @@ -1478,11 +1478,11 @@ def __init__(self, device, name=''): self.keys = [] # the keys that can initiate processing self.initiating_key = None # the key that did initiate processing self.active = False - self.feature_offset = device.features[_hidpp20.FEATURE.REPROG_CONTROLS_V4] + self.feature_offset = device.features[_hidpp20_constants.FEATURE.REPROG_CONTROLS_V4] assert self.feature_offset is not False def handler(self, device, n): # Called on notification events from the device - if n.sub_id < 0x40 and device.features.get_feature(n.sub_id) == _hidpp20.FEATURE.REPROG_CONTROLS_V4: + if n.sub_id < 0x40 and device.features.get_feature(n.sub_id) == _hidpp20_constants.FEATURE.REPROG_CONTROLS_V4: if n.address == 0x00: cids = _unpack('!HHHH', n.data[:8]) ## generalize to list of keys @@ -1550,7 +1550,7 @@ def key_action(self, key): # acction to take when some other diverted key is pr def apply_all_settings(device): - if device.features and _hidpp20.FEATURE.HIRES_WHEEL in device.features: + if device.features and _hidpp20_constants.FEATURE.HIRES_WHEEL in device.features: _sleep(0.2) # delay to try to get out of race condition with Linux HID++ driver persister = getattr(device, 'persister', None) sensitives = persister.get('_sensitive', {}) if persister else {} diff --git a/lib/logitech_receiver/settings_templates.py b/lib/logitech_receiver/settings_templates.py index 2dd600604b..e6144fe191 100644 --- a/lib/logitech_receiver/settings_templates.py +++ b/lib/logitech_receiver/settings_templates.py @@ -25,6 +25,7 @@ from . import hidpp10_constants as _hidpp10_constants from . import hidpp20 as _hidpp20 +from . import hidpp20_constants as _hidpp20_constants from . import special_keys as _special_keys from .common import NamedInt as _NamedInt from .common import NamedInts as _NamedInts @@ -55,9 +56,9 @@ _DK = _hidpp10_constants.DEVICE_KIND _R = _hidpp10_constants.REGISTERS -_F = _hidpp20.FEATURE +_F = _hidpp20_constants.FEATURE -_GG = _hidpp20.GESTURE +_GG = _hidpp20_constants.GESTURE _GP = _hidpp20.PARAM # Setting classes are used to control the settings that the Solaar GUI shows and manipulates. @@ -510,8 +511,8 @@ class _rw_class(_FeatureRW): # no longer needed - set Onboard Profiles to disab def write(self, device, data_bytes): # Host mode is required for report rate to be adjustable - if _hidpp20.get_onboard_mode(device) != _hidpp20.ONBOARD_MODES.MODE_HOST: - _hidpp20.set_onboard_mode(device, _hidpp20.ONBOARD_MODES.MODE_HOST) + if _hidpp20.get_onboard_mode(device) != _hidpp20_constants.ONBOARD_MODES.MODE_HOST: + _hidpp20.set_onboard_mode(device, _hidpp20_constants.ONBOARD_MODES.MODE_HOST) return super().write(device, data_bytes) class validator_class(_ChoicesV): @@ -556,8 +557,8 @@ def read(self, device, data_bytes=b''): def write(self, device, data_bytes): # Host mode is required for report rate to be adjustable - if _hidpp20.get_onboard_mode(device) != _hidpp20.ONBOARD_MODES.MODE_HOST: - _hidpp20.set_onboard_mode(device, _hidpp20.ONBOARD_MODES.MODE_HOST) + if _hidpp20.get_onboard_mode(device) != _hidpp20_constants.ONBOARD_MODES.MODE_HOST: + _hidpp20.set_onboard_mode(device, _hidpp20_constants.ONBOARD_MODES.MODE_HOST) return super().write(device, data_bytes) class validator_class(_ChoicesV): @@ -805,7 +806,7 @@ def release_action(self): logger.info('mouse gesture notification %s', self.data) payload = _pack('!' + (len(self.data) * 'h'), *self.data) notification = _HIDPP_Notification(0, 0, 0, 0, payload) - _process_notification(self.device, self.device.status, notification, _hidpp20.FEATURE.MOUSE_GESTURE) + _process_notification(self.device, self.device.status, notification, _F.MOUSE_GESTURE) self.fsmState = 'idle' def move_action(self, dx, dy): @@ -1195,7 +1196,7 @@ class Gesture2Gestures(_BitFieldOMSetting): feature = _F.GESTURE_2 rw_options = {'read_fnid': 0x10, 'write_fnid': 0x20} validator_options = {'om_method': _hidpp20.Gesture.enable_offset_mask} - choices_universe = _hidpp20.GESTURE + choices_universe = _hidpp20_constants.GESTURE _labels = _GESTURE2_GESTURES_LABELS class validator_class(_BitFieldOMV): @@ -1213,7 +1214,7 @@ class Gesture2Divert(_BitFieldOMSetting): feature = _F.GESTURE_2 rw_options = {'read_fnid': 0x30, 'write_fnid': 0x40} validator_options = {'om_method': _hidpp20.Gesture.diversion_offset_mask} - choices_universe = _hidpp20.GESTURE + choices_universe = _hidpp20_constants.GESTURE _labels = _GESTURE2_GESTURES_LABELS class validator_class(_BitFieldOMV): diff --git a/lib/logitech_receiver/status.py b/lib/logitech_receiver/status.py index 324a5a09d0..03e4d2ff4e 100644 --- a/lib/logitech_receiver/status.py +++ b/lib/logitech_receiver/status.py @@ -218,8 +218,8 @@ def set_battery_info(self, level, nextLevel, status, voltage, timestamp=None): old_voltage, self[KEYS.BATTERY_VOLTAGE] = self.get(KEYS.BATTERY_VOLTAGE), voltage charging = status in ( - _hidpp20_constants.BATTERY_STATUS.recharging, _hidpp20_constants.BATTERY_STATUS.almost_full, _hidpp20_constants.BATTERY_STATUS.full, - _hidpp20_constants.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 diff --git a/lib/solaar/cli/show.py b/lib/solaar/cli/show.py index fad81e9fc6..5500e1e783 100644 --- a/lib/solaar/cli/show.py +++ b/lib/solaar/cli/show.py @@ -20,13 +20,14 @@ 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 hidpp20_constants as _hidpp20_constants from logitech_receiver import receiver as _receiver from logitech_receiver import settings_templates as _settings_templates from logitech_receiver.common import NamedInt as _NamedInt from logitech_receiver.common import strhex as _strhex from solaar import NAME, __version__ -_F = _hidpp20.FEATURE +_F = _hidpp20_constants.FEATURE def _print_receiver(receiver): @@ -142,11 +143,11 @@ def _print_device(dev, num=None): for feature, index in dev.features.enumerate(): flags = dev.request(0x0000, feature.bytes(2)) flags = 0 if flags is None else ord(flags[1:2]) - flags = _hidpp20.FEATURE_FLAG.flag_names(flags) + flags = _hidpp20_constants.FEATURE_FLAG.flag_names(flags) version = dev.features.get_feature_version(int(feature)) version = version if version else 0 print(' %2d: %-22s {%04X} V%s %s ' % (index, feature, feature, version, ', '.join(flags))) - if feature == _hidpp20.FEATURE.HIRES_WHEEL: + if feature == _hidpp20_constants.FEATURE.HIRES_WHEEL: wheel = _hidpp20.get_hires_wheel(dev) if wheel: multi, has_invert, has_switch, inv, res, target, ratchet = wheel @@ -163,7 +164,7 @@ def _print_device(dev, num=None): print(' HID++ notification') else: print(' HID notification') - elif feature == _hidpp20.FEATURE.MOUSE_POINTER: + elif feature == _hidpp20_constants.FEATURE.MOUSE_POINTER: mouse_pointer = _hidpp20.get_mouse_pointer_info(dev) if mouse_pointer: print(' DPI: %s' % mouse_pointer['dpi']) @@ -176,13 +177,13 @@ def _print_device(dev, num=None): print(' Provide vertical tuning, trackball') else: print(' No vertical tuning, standard mice') - elif feature == _hidpp20.FEATURE.VERTICAL_SCROLLING: + elif feature == _hidpp20_constants.FEATURE.VERTICAL_SCROLLING: vertical_scrolling_info = _hidpp20.get_vertical_scrolling_info(dev) if vertical_scrolling_info: print(' Roller type: %s' % vertical_scrolling_info['roller']) print(' Ratchet per turn: %s' % vertical_scrolling_info['ratchet']) print(' Scroll lines: %s' % vertical_scrolling_info['lines']) - elif feature == _hidpp20.FEATURE.HI_RES_SCROLLING: + elif feature == _hidpp20_constants.FEATURE.HI_RES_SCROLLING: scrolling_mode, scrolling_resolution = _hidpp20.get_hi_res_scrolling_info(dev) if scrolling_mode: print(' Hi-res scrolling enabled') @@ -190,30 +191,30 @@ def _print_device(dev, num=None): print(' Hi-res scrolling disabled') if scrolling_resolution: print(' Hi-res scrolling multiplier: %s' % scrolling_resolution) - elif feature == _hidpp20.FEATURE.POINTER_SPEED: + elif feature == _hidpp20_constants.FEATURE.POINTER_SPEED: pointer_speed = _hidpp20.get_pointer_speed_info(dev) if pointer_speed: print(' Pointer Speed: %s' % pointer_speed) - elif feature == _hidpp20.FEATURE.LOWRES_WHEEL: + elif feature == _hidpp20_constants.FEATURE.LOWRES_WHEEL: wheel_status = _hidpp20.get_lowres_wheel_status(dev) if wheel_status: print(' Wheel Reports: %s' % wheel_status) - elif feature == _hidpp20.FEATURE.NEW_FN_INVERSION: + elif feature == _hidpp20_constants.FEATURE.NEW_FN_INVERSION: inversion = _hidpp20.get_new_fn_inversion(dev) if inversion: inverted, default_inverted = inversion print(' Fn-swap:', 'enabled' if inverted else 'disabled') print(' Fn-swap default:', 'enabled' if default_inverted else 'disabled') - elif feature == _hidpp20.FEATURE.HOSTS_INFO: + elif feature == _hidpp20_constants.FEATURE.HOSTS_INFO: host_names = _hidpp20.get_host_names(dev) for host, (paired, name) in host_names.items(): print(' Host %s (%s): %s' % (host, 'paired' if paired else 'unpaired', name)) - elif feature == _hidpp20.FEATURE.DEVICE_NAME: + elif feature == _hidpp20_constants.FEATURE.DEVICE_NAME: print(' Name: %s' % _hidpp20.get_name(dev)) print(' Kind: %s' % _hidpp20.get_kind(dev)) - elif feature == _hidpp20.FEATURE.DEVICE_FRIENDLY_NAME: + elif feature == _hidpp20_constants.FEATURE.DEVICE_FRIENDLY_NAME: print(' Friendly Name: %s' % _hidpp20.get_friendly_name(dev)) - elif feature == _hidpp20.FEATURE.DEVICE_FW_VERSION: + elif feature == _hidpp20_constants.FEATURE.DEVICE_FW_VERSION: for fw in _hidpp20.get_firmware(dev): extras = _strhex(fw.extras) if fw.extras else '' print(' Firmware: %s %s %s %s' % (fw.kind, fw.name, fw.version, extras)) @@ -221,12 +222,12 @@ def _print_device(dev, num=None): if ids: unitId, modelId, tid_map = ids print(' Unit ID: %s Model ID: %s Transport IDs: %s' % (unitId, modelId, tid_map)) - elif feature == _hidpp20.FEATURE.REPORT_RATE or feature == _hidpp20.FEATURE.EXTENDED_ADJUSTABLE_REPORT_RATE: + elif feature == _hidpp20_constants.FEATURE.REPORT_RATE or feature == _hidpp20_constants.FEATURE.EXTENDED_ADJUSTABLE_REPORT_RATE: print(' Report Rate: %s' % _hidpp20.get_polling_rate(dev)) - elif feature == _hidpp20.FEATURE.REMAINING_PAIRING: + elif feature == _hidpp20_constants.FEATURE.REMAINING_PAIRING: print(' Remaining Pairings: %d' % _hidpp20.get_remaining_pairing(dev)) - elif feature == _hidpp20.FEATURE.ONBOARD_PROFILES: - if _hidpp20.get_onboard_mode(dev) == _hidpp20.ONBOARD_MODES.MODE_HOST: + elif feature == _hidpp20_constants.FEATURE.ONBOARD_PROFILES: + if _hidpp20.get_onboard_mode(dev) == _hidpp20_constants.ONBOARD_MODES.MODE_HOST: mode = 'Host' else: mode = 'On-Board' @@ -252,9 +253,9 @@ def _print_device(dev, num=None): print(' Has %d reprogrammable keys:' % len(dev.keys)) for k in dev.keys: # TODO: add here additional variants for other REPROG_CONTROLS - if dev.keys.keyversion == _hidpp20.FEATURE.REPROG_CONTROLS_V2: + if dev.keys.keyversion == _hidpp20_constants.FEATURE.REPROG_CONTROLS_V2: print(' %2d: %-26s => %-27s %s' % (k.index, k.key, k.default_task, ', '.join(k.flags))) - if dev.keys.keyversion == _hidpp20.FEATURE.REPROG_CONTROLS_V4: + if dev.keys.keyversion == _hidpp20_constants.FEATURE.REPROG_CONTROLS_V4: print(' %2d: %-26s, default: %-27s => %-26s' % (k.index, k.key, k.default_task, k.mapped_to)) gmask_fmt = ','.join(k.group_mask) gmask_fmt = gmask_fmt if gmask_fmt else 'empty'