Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hidpp10_constants.py: Remove dependency to NamedInts #25

Open
wants to merge 29 commits into
base: refactor_settings
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7e62bb0
Split up huge settings module
MattHag Nov 3, 2024
5959d6a
Refactor: Convert Kind to IntEnum
MattHag Nov 3, 2024
22fdae2
type hints: Introduce settings protocol
MattHag Nov 3, 2024
c633bda
Refactor: Remove diversion alias
MattHag Nov 3, 2024
49aa35e
Simplify settings UI class
MattHag Nov 3, 2024
6b44119
Enforce rules on RuleComponentUI subclasses
MattHag Nov 3, 2024
8f1d25f
settings: Add docstrings and type hint
MattHag Nov 3, 2024
5085084
Remove NamedInts: Convert Column to enum
MattHag Nov 4, 2024
ec588a5
Remove NamedInts: Convert Task to enum
MattHag Nov 4, 2024
649bcde
Add type hints
MattHag Nov 4, 2024
fd1aa2f
key flags: Move to module of use
MattHag Nov 4, 2024
f1c3e7c
Add type hints
MattHag Nov 4, 2024
5be1e10
Remove NamedInts: Convert KeyFlag to Flag
MattHag Nov 5, 2024
e04d17e
Remove NamedInts: Convert Spec to enum
MattHag Nov 5, 2024
e92e13f
Remove NamedInts: Convert ActionId to enum
MattHag Nov 5, 2024
61ef9b5
mapping flag: Move to module of use
MattHag Nov 5, 2024
cdf4b80
Remove NamedInts: Convert MappingFlag to flag
MattHag Nov 5, 2024
04f7957
Remove NamedInts: Convert PowerSwitchLocation to flag
MattHag Nov 5, 2024
32e0158
Remove NamedInts: Convert HorizontalScroll to enum
MattHag Nov 5, 2024
cf46f80
Remove NamedInts: Convert LedRampChoice to flag
MattHag Nov 5, 2024
c5a7de5
charge status: Refactor to enum and move to module of use
MattHag Nov 5, 2024
5300877
Remove NamedInts: Convert LedFormChoices to enum
MattHag Nov 5, 2024
65abb53
Fix KeyFlag conversion
MattHag Nov 5, 2024
c8d3040
Fixes on top of refactoring
MattHag Nov 5, 2024
c728e1d
Prepare refactoring of NotificationFlag
MattHag Nov 16, 2024
8eee66e
Remove NamedInts: Convert NotificationFlag to flag
MattHag Nov 16, 2024
5b48ffd
Remove NamedInts: Convert DeviceFeature to flag
MattHag Nov 16, 2024
5548897
refactor(logitech_receiver/hidpp10_constants.py): use InfoSubRegister…
Nov 20, 2024
d79346f
refactor(logitech_receiver/hidpp10_constants.py): remove dependency t…
Nov 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 21 additions & 23 deletions lib/logitech_receiver/descriptors.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
- the name or codename should be different from what the device reports
"""

from .hidpp10_constants import DEVICE_KIND
from .hidpp10_constants import DeviceKind
from .hidpp10_constants import Registers as Reg


Expand Down Expand Up @@ -71,15 +71,15 @@ def _D(
):
if kind is None:
kind = (
DEVICE_KIND.mouse
DeviceKind.MOUSE
if "Mouse" in name
else DEVICE_KIND.keyboard
else DeviceKind.KEYBOARD
if "Keyboard" in name
else DEVICE_KIND.numpad
else DeviceKind.NUMPAD
if "Number Pad" in name
else DEVICE_KIND.touchpad
else DeviceKind.TOUCHPAD
if "Touchpad" in name
else DEVICE_KIND.trackball
else DeviceKind.TRACKBALL
if "Trackball" in name
else None
)
Expand All @@ -92,11 +92,11 @@ def _D(
assert w[0:1] == "4", f"{name} has protocol {protocol:0.1f}, wpid {w}"
else:
if w[0:1] == "1":
assert kind == DEVICE_KIND.mouse, f"{name} has protocol {protocol:0.1f}, wpid {w}"
assert kind == DeviceKind.MOUSE, f"{name} has protocol {protocol:0.1f}, wpid {w}"
elif w[0:1] == "2":
assert kind in (
DEVICE_KIND.keyboard,
DEVICE_KIND.numpad,
DeviceKind.KEYBOARD,
DeviceKind.NUMPAD,
), f"{name} has protocol {protocol:0.1f}, wpid {w}"

device_descriptor = _DeviceDescriptor(
Expand Down Expand Up @@ -254,7 +254,7 @@ def get_btid(btid):
_D(
"VX Revolution",
codename="VX Revolution",
kind=DEVICE_KIND.mouse,
kind=DeviceKind.MOUSE,
protocol=1.0,
wpid=("1006", "100D", "0612"),
registers=(Reg.BATTERY_CHARGE,),
Expand All @@ -263,15 +263,15 @@ def get_btid(btid):
"MX Air",
codename="MX Air",
protocol=1.0,
kind=DEVICE_KIND.mouse,
kind=DeviceKind.MOUSE,
wpid=("1007", "100E"),
registers=Reg.BATTERY_CHARGE,
)
_D(
"MX Revolution",
codename="MX Revolution",
protocol=1.0,
kind=DEVICE_KIND.mouse,
kind=DeviceKind.MOUSE,
wpid=("1008", "100C"),
registers=(Reg.BATTERY_CHARGE,),
)
Expand Down Expand Up @@ -307,7 +307,7 @@ def get_btid(btid):
"MX 1100 Cordless Laser Mouse",
codename="MX 1100",
protocol=1.0,
kind=DEVICE_KIND.mouse,
kind=DeviceKind.MOUSE,
wpid="1014",
registers=(Reg.BATTERY_CHARGE,),
)
Expand Down Expand Up @@ -421,7 +421,7 @@ def get_btid(btid):
_D("MX518 Gaming Mouse", codename="MX518", usbid=0xC08E, interface=1)
_D("G703 Hero Gaming Mouse", codename="G703 Hero", usbid=0xC090)
_D("G903 Hero Gaming Mouse", codename="G903 Hero", usbid=0xC091)
_D(None, kind=DEVICE_KIND.mouse, usbid=0xC092, interface=1) # two mice share this ID
_D(None, kind=DeviceKind.MOUSE, usbid=0xC092, interface=1) # two mice share this ID
_D("M500S Mouse", codename="M500S", usbid=0xC093, interface=1)
# _D('G600 Gaming Mouse', codename='G600 Gaming', usbid=0xc24a, interface=1) # not an HID++ device
_D("G500s Gaming Mouse", codename="G500s Gaming", usbid=0xC24E, interface=1, protocol=1.0)
Expand All @@ -438,29 +438,27 @@ def get_btid(btid):

_D("Wireless Touchpad", codename="Wireless Touch", protocol=2.0, wpid="4011")
_D("Wireless Rechargeable Touchpad T650", codename="T650", protocol=2.0, wpid="4101")
_D(
"G Powerplay", codename="Powerplay", protocol=2.0, kind=DEVICE_KIND.touchpad, wpid="405F"
) # To override self-identification
_D("G Powerplay", codename="Powerplay", protocol=2.0, kind=DeviceKind.TOUCHPAD, wpid="405F") # To override self-identification

# Headset

_D("G533 Gaming Headset", codename="G533 Headset", protocol=2.0, interface=3, kind=DEVICE_KIND.headset, usbid=0x0A66)
_D("G535 Gaming Headset", codename="G535 Headset", protocol=2.0, interface=3, kind=DEVICE_KIND.headset, usbid=0x0AC4)
_D("G935 Gaming Headset", codename="G935 Headset", protocol=2.0, interface=3, kind=DEVICE_KIND.headset, usbid=0x0A87)
_D("G733 Gaming Headset", codename="G733 Headset", protocol=2.0, interface=3, kind=DEVICE_KIND.headset, usbid=0x0AB5)
_D("G533 Gaming Headset", codename="G533 Headset", protocol=2.0, interface=3, kind=DeviceKind.HEADSET, usbid=0x0A66)
_D("G535 Gaming Headset", codename="G535 Headset", protocol=2.0, interface=3, kind=DeviceKind.HEADSET, usbid=0x0AC4)
_D("G935 Gaming Headset", codename="G935 Headset", protocol=2.0, interface=3, kind=DeviceKind.HEADSET, usbid=0x0A87)
_D("G733 Gaming Headset", codename="G733 Headset", protocol=2.0, interface=3, kind=DeviceKind.HEADSET, usbid=0x0AB5)
_D(
"G733 Gaming Headset",
codename="G733 Headset New",
protocol=2.0,
interface=3,
kind=DEVICE_KIND.headset,
kind=DeviceKind.HEADSET,
usbid=0x0AFE,
)
_D(
"PRO X Wireless Gaming Headset",
codename="PRO Headset",
protocol=2.0,
interface=3,
kind=DEVICE_KIND.headset,
kind=DeviceKind.HEADSET,
usbid=0x0ABA,
)
34 changes: 16 additions & 18 deletions lib/logitech_receiver/hidpp10_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,28 @@
from enum import IntEnum
from typing import List

from .common import NamedInts

"""HID constants for HID++ 1.0.

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,
tablet=0x0A,
gamepad=0x0B,
joystick=0x0C,
headset=0x0D, # not from Logitech documentation
remote_control=0x0E, # for compatibility with HID++ 2.0
receiver=0x0F, # for compatibility with HID++ 2.0
)

class DeviceKind(IntEnum):
UNKNOWN = 0x00
KEYBOARD = 0x01
MOUSE = 0x02
NUMPAD = 0x03
PRESENTER = 0x04
REMOTE = 0x07
TRACKBALL = 0x08
TOUCHPAD = 0x09
TABLET = 0x0A
GAMEPAD = 0x0B
JOYSTICK = 0x0C
HEADSET = 0x0D # not from Logitech documentation
REMOTE_CONTROL = 0x0E # for compatibility with HID++ 2.0
RECEIVER = 0x0F # for compatibility with HID++ 2.0


class PowerSwitchLocation(IntEnum):
Expand Down
20 changes: 18 additions & 2 deletions lib/logitech_receiver/hidpp20.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@

from . import common
from . import exceptions
from . import hidpp10_constants
from . import special_keys
from .common import Battery
from .common import BatteryLevelApproximation
from .common import BatteryStatus
from .common import FirmwareKind
from .common import NamedInt
from .common import NamedInts
from .hidpp20_constants import DEVICE_KIND
from .hidpp20_constants import ChargeLevel
from .hidpp20_constants import ChargeType
Expand All @@ -55,7 +55,23 @@

FixedBytes5 = bytes

KIND_MAP = {kind: hidpp10_constants.DEVICE_KIND[str(kind)] for kind in DEVICE_KIND}
HIDPP10_DEVICE_KIND = NamedInts(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rloutrel Can you avoid this? It just reintroduces the NamedInts in another place.

unknown=0x00,
keyboard=0x01,
mouse=0x02,
numpad=0x03,
presenter=0x04,
remote=0x07,
trackball=0x08,
touchpad=0x09,
tablet=0x0A,
gamepad=0x0B,
joystick=0x0C,
headset=0x0D, # not from Logitech documentation
remote_control=0x0E, # for compatibility with HID++ 2.0
receiver=0x0F, # for compatibility with HID++ 2.0
)
KIND_MAP = {kind: HIDPP10_DEVICE_KIND[str(kind)] for kind in DEVICE_KIND}


class Device(Protocol):
Expand Down
32 changes: 15 additions & 17 deletions lib/logitech_receiver/receiver.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from . import exceptions
from . import hidpp10
from . import hidpp10_constants
from .base import HIDPPNotification
from .common import Alert
from .common import Notification
from .device import Device
Expand Down Expand Up @@ -202,12 +203,12 @@ def notify_devices(self):
if not self.write_register(Registers.RECEIVER_CONNECTION, 0x02):
logger.warning("%s: failed to trigger device link notifications", self)

def notification_information(self, number, notification):
def notification_information(self, number, notification: HIDPPNotification):
"""Extract information from unifying-style notification"""
assert notification.address != 0x02
online = not bool(notification.data[0] & 0x40)
encrypted = bool(notification.data[0] & 0x20) or notification.address == 0x10
kind = hidpp10_constants.DEVICE_KIND[notification.data[0] & 0x0F]
kind = hidpp10_constants.DeviceKind(notification.data[0] & 0x0F)
wpid = (notification.data[2:3] + notification.data[1:2]).hex().upper()
return online, encrypted, wpid, kind

Expand All @@ -219,14 +220,14 @@ def device_pairing_information(self, n: int) -> dict:
pair_info = self.read_register(Registers.RECEIVER_INFO, InfoSubRegisters.PAIRING_INFORMATION + n - 1)
if pair_info: # a receiver that uses Unifying-style pairing registers
wpid = pair_info[3:5].hex().upper()
kind = hidpp10_constants.DEVICE_KIND[pair_info[7] & 0x0F]
kind = hidpp10_constants.DeviceKind(pair_info[7] & 0x0F)
polling_rate = str(pair_info[2]) + "ms"
elif not self.receiver_kind == "unifying": # may be an old Nano receiver
device_info = self.read_register(Registers.RECEIVER_INFO, 0x04) # undocumented
if device_info:
logger.warning("using undocumented register for device wpid")
wpid = device_info[3:5].hex().upper()
kind = hidpp10_constants.DEVICE_KIND[0x00] # unknown kind
kind = hidpp10_constants.DeviceKind.UNKNOWN
else:
raise exceptions.NoSuchDevice(number=n, receiver=self, error="read pairing information - non-unifying")
else:
Expand Down Expand Up @@ -423,7 +424,7 @@ def device_pairing_information(self, n: int) -> dict:
pair_info = self.read_register(Registers.RECEIVER_INFO, InfoSubRegisters.BOLT_PAIRING_INFORMATION + n)
if pair_info:
wpid = (pair_info[3:4] + pair_info[2:3]).hex().upper()
kind = hidpp10_constants.DEVICE_KIND[pair_info[1] & 0x0F]
kind = hidpp10_constants.DeviceKind(pair_info[1] & 0x0F)
serial = pair_info[4:8].hex().upper()
return {"wpid": wpid, "kind": kind, "polling": None, "serial": serial, "power_switch": "(unknown)"}
else:
Expand Down Expand Up @@ -482,7 +483,7 @@ def notification_information(self, number, notification):
assert notification.address == 0x02
online = True
encrypted = bool(notification.data[0] & 0x80)
kind = hidpp10_constants.DEVICE_KIND[_get_kind_from_index(self, number)]
kind = _get_kind_from_index(self, number)
wpid = "00" + notification.data[2:3].hex().upper()
return online, encrypted, wpid, kind

Expand All @@ -492,25 +493,22 @@ def device_pairing_information(self, number: int) -> dict:
if not wpid:
logger.error("Unable to get wpid from udev for device %d of %s", number, self)
raise exceptions.NoSuchDevice(number=number, receiver=self, error="Not present 27Mhz device")
kind = hidpp10_constants.DEVICE_KIND[_get_kind_from_index(self, number)]
kind = _get_kind_from_index(self, number)
return {"wpid": wpid, "kind": kind, "polling": "", "serial": None, "power_switch": "(unknown)"}


def _get_kind_from_index(receiver, index):
def _get_kind_from_index(receiver, index) -> hidpp10_constants.DeviceKind:
"""Get device kind from 27Mhz device index"""
# From drivers/hid/hid-logitech-dj.c
if index == 1: # mouse
kind = 2
elif index == 2: # mouse
kind = 2
elif index == 3: # keyboard
kind = 1
elif index == 4: # numpad
kind = 3
if index in [1, 2]:
return hidpp10_constants.DeviceKind.MOUSE
elif index == 3:
return hidpp10_constants.DeviceKind.KEYBOARD
elif index == 4:
return hidpp10_constants.DeviceKind.NUMPAD
else: # unknown device number on 27Mhz receiver
logger.error("failed to calculate device kind for device %d of %s", index, receiver)
raise exceptions.NoSuchDevice(number=index, receiver=receiver, error="Unknown 27Mhz device number")
return kind


receiver_class_mapping = {
Expand Down
2 changes: 1 addition & 1 deletion lib/solaar/cli/pair.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def notifications_hook(self, n):
receiver.pair_device(
address=address,
authentication=authentication,
entropy=20 if kind == hidpp10_constants.DEVICE_KIND.keyboard else 10,
entropy=20 if kind == hidpp10_constants.DeviceKind.KEYBOARD else 10,
)
pairing_start = time()
patience = 5 # the discovering notification may come slightly later, so be patient
Expand Down
2 changes: 1 addition & 1 deletion lib/solaar/ui/pair_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def _check_lock_state(assistant, receiver, count):
return True
elif receiver.pairing.discovering and receiver.pairing.device_address and receiver.pairing.device_name:
add = receiver.pairing.device_address
ent = 20 if receiver.pairing.device_kind == hidpp10_constants.DEVICE_KIND.keyboard else 10
ent = 20 if receiver.pairing.device_kind == hidpp10_constants.DeviceKind.KEYBOARD else 10
if receiver.pair_device(address=add, authentication=receiver.pairing.device_authentication, entropy=ent):
return True
else:
Expand Down
Loading