Skip to content

Commit

Permalink
device: move hidpp constants to new module
Browse files Browse the repository at this point in the history
  • Loading branch information
pfps committed Feb 16, 2024
1 parent c9b0646 commit 86c370f
Show file tree
Hide file tree
Showing 22 changed files with 487 additions and 470 deletions.
17 changes: 1 addition & 16 deletions lib/logitech_receiver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,12 @@
## You should have received a copy of the GNU General Public License along
## with this program; if not, write to the Free Software Foundation, Inc.,
## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""Low-level interface for devices connected through a Logitech Universal
Receiver (UR).
"""Low-level interface for devices using the Logitech HID++ protocols.
Uses the HID api exposed through hidapi.py, a Python thin layer over a native
implementation.
Incomplete. Based on a bit of documentation, trial-and-error, and guesswork.
References:
http://julien.danjou.info/blog/2012/logitech-k750-linux-support
http://6xq.net/git/lars/lshidpp.git/plain/doc/
"""

import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.root.level)
# if logging.root.level > logging.DEBUG:
# logger.addHandler(logging.NullHandler())
# logger.propagate = 0

del logging

__version__ = '0.9'
15 changes: 8 additions & 7 deletions lib/logitech_receiver/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

import hidapi as _hid

from . import hidpp10 as _hidpp10
from . import hidpp as _hidpp
from . import hidpp20 as _hidpp20
from .base_usb import ALL as _RECEIVER_USB_IDS
from .common import KwException as _KwException
Expand Down Expand Up @@ -489,15 +489,15 @@ def request(handle, devnumber, request_id, *params, no_reply=False, return_error
if logger.isEnabledFor(logging.DEBUG):
logger.debug(
'(%s) device 0x%02X error on request {%04X}: %d = %s', handle, devnumber, request_id, error,
_hidpp10.ERROR[error]
_hidpp.HIDPP_ERROR[error]
)
return _hidpp10.ERROR[error] if return_error else None
return _hidpp.HIDPP_ERROR[error] if return_error else None
if reply_data[:1] == b'\xFF' and reply_data[1:3] == request_data[:2]:
# a HID++ 2.0 feature call returned with an error
error = ord(reply_data[3:4])
logger.error(
'(%s) device %d error on feature request {%04X}: %d = %s', handle, devnumber, request_id, error,
_hidpp20.ERROR[error]
_hidpp.HIDPP20_ERROR[error]
)
raise _hidpp20.FeatureCallError(number=devnumber, request=request_id, error=error, params=params)

Expand Down Expand Up @@ -574,11 +574,12 @@ def ping(handle, devnumber, long_message=False):
if report_id == HIDPP_SHORT_MESSAGE_ID and reply_data[:1] == b'\x8F' and \
reply_data[1:3] == request_data[:2]: # error response
error = ord(reply_data[3:4])
if error == _hidpp10.ERROR.invalid_SubID__command: # a valid reply from a HID++ 1.0 device
if error == _hidpp.HIDPP_ERROR.invalid_SubID__command: # a valid reply from a HID++ 1.0 device
return 1.0
if error == _hidpp10.ERROR.resource_error or error == _hidpp10.ERROR.connection_request_failed:
if error == _hidpp.HIDPP_ERROR.resource_error or \
error == _hidpp.HIDPP_ERROR.connection_request_failed:
return # device unreachable
if error == _hidpp10.ERROR.unknown_device: # no paired device with that number
if error == _hidpp.HIDPP_ERROR.unknown_device: # no paired device with that number
logger.error('(%s) device %d error on ping request: unknown device', handle, devnumber)
raise NoSuchDevice(number=devnumber, request=request_id)

Expand Down
4 changes: 2 additions & 2 deletions lib/logitech_receiver/descriptors.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 .hidpp import DEVICE_KIND as _DK
from .hidpp import REGISTERS as _R

#
#
Expand Down
26 changes: 12 additions & 14 deletions lib/logitech_receiver/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,16 @@

from . import base as _base
from . import descriptors as _descriptors
from . import hidpp as _hidpp
from . import hidpp10 as _hidpp10
from . import hidpp20 as _hidpp20
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

KIND_MAP = {kind: _hidpp10.DEVICE_KIND[str(kind)] for kind in _hidpp20.DEVICE_KIND}
_R = _hidpp.REGISTERS
_IR = _hidpp.INFO_SUBREGISTERS

#
#
Expand Down Expand Up @@ -80,7 +79,7 @@ def __init__(
self.online = self.descriptor = None

self.wpid = None # the Wireless PID is unique per device model
self._kind = None # mouse, keyboard, etc (see _hidpp10.DEVICE_KIND)
self._kind = None # mouse, keyboard, etc (see _hidpp.DEVICE_KIND)
self._codename = None # Unifying peripherals report a codename.
self._name = None # the full name of the model
self._protocol = None # HID++ protocol version, 1.0 or 2.0
Expand Down Expand Up @@ -123,14 +122,14 @@ def __init__(
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 = _hidpp.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 _base.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 = _hidpp.DEVICE_KIND[kind]
else: # get information from pairing registers
self.online = True
self.update_pairing_information()
Expand Down Expand Up @@ -261,8 +260,7 @@ def kind(self):
if not self._kind:
self.update_pairing_information()
if not self._kind and self.protocol >= 2.0:
kind = _hidpp20.get_kind(self)
self._kind = KIND_MAP[kind] if kind else None
self._kind = _hidpp20.get_kind(self)
return self._kind or '?'

@property
Expand Down Expand Up @@ -414,10 +412,10 @@ def enable_connection_notifications(self, enable=True):

if enable:
set_flag_bits = (
_hidpp10.NOTIFICATION_FLAG.battery_status
| _hidpp10.NOTIFICATION_FLAG.keyboard_illumination
| _hidpp10.NOTIFICATION_FLAG.wireless
| _hidpp10.NOTIFICATION_FLAG.software_present
_hidpp.NOTIFICATION_FLAG.battery_status
| _hidpp.NOTIFICATION_FLAG.keyboard_illumination
| _hidpp.NOTIFICATION_FLAG.wireless
| _hidpp.NOTIFICATION_FLAG.software_present
)
else:
set_flag_bits = 0
Expand All @@ -426,7 +424,7 @@ def enable_connection_notifications(self, enable=True):
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(_hidpp.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
Expand Down
2 changes: 1 addition & 1 deletion lib/logitech_receiver/diversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
from yaml import safe_load_all as _yaml_safe_load_all

from .common import NamedInt
from .hidpp20 import FEATURE as _F
from .hidpp import FEATURE as _F
from .special_keys import CONTROL as _CONTROL

gi.require_version('Gdk', '3.0') # isort:skip
Expand Down
Loading

0 comments on commit 86c370f

Please sign in to comment.