# # # from __future__ import absolute_import, division, print_function, unicode_literals from .common import (strhex as _strhex, NamedInts as _NamedInts, FirmwareInfo as _FirmwareInfo) from . import settings as _settings from .hidpp20 import FIRMWARE_KIND # # constants # DEVICE_KIND = _NamedInts( keyboard=0x01, mouse=0x02, numpad=0x03, presenter=0x04, trackball=0x08, touchpad=0x09) 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) NOTIFICATION_FLAG = _NamedInts( battery_status=0x100000, wireless=0x000100, software_present=0x0000800) 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) # # # class SmoothScroll_Setting(_settings.Setting): def __init__(self, register): super(SmoothScroll_Setting, self).__init__('smooth-scroll', _settings.KIND.toggle, 'Smooth Scrolling', 'High-sensitivity mode for vertical scroll with the wheel.') assert register is not None self.register = register def read(self, cached=True): if (self._value is None or not cached) and self._device: ss = self.read_register() if ss: self._value = (ss[:1] == b'\x40') return self._value def write(self, value): if self._device: reply = self.write_register(0x40 if bool(value) else 0x00) self._value = None if reply: return self.read() class MouseDPI_Setting(_settings.Setting): def __init__(self, register, choices): super(MouseDPI_Setting, self).__init__('dpi', _settings.KIND.choice, 'Sensitivity (DPI)', choices=choices) assert choices assert isinstance(choices, _NamedInts) assert register is not None self.register = register def read(self, cached=True): if (self._value is None or not cached) and self._device: dpi = self.read_register() if dpi: value = ord(dpi[:1]) self._value = self.choices[value] assert self._value is not None return self._value def write(self, value): if self._device: choice = self.choices[value] if choice is None: raise ValueError(repr(value)) reply = self.write_register(value) self._value = None if reply: return self.read() # # functions # def get_battery(device): """Reads a device's battery level, if provided by the HID++ 1.0 protocol.""" if 'battery' in device.registers: register = device.registers['battery'] reply = device.request(0x8100 + (register & 0xFF)) if reply: charge = ord(reply[:1]) status = ord(reply[2:3]) & 0xF0 status = ('discharging' if status == 0x30 else 'charging' if status == 0x50 else 'fully charged' if status == 0x90 else None) return charge, status def get_serial(device): if device.kind is None: dev_id = 0x03 receiver = device else: dev_id = 0x30 + device.number - 1 receiver = device.receiver serial = receiver.request(0x83B5, dev_id) if serial: return _strhex(serial[1:5]) def get_firmware(device): firmware = [] reply = device.request(0x81F1, 0x01) if reply: fw_version = _strhex(reply[1:3]) fw_version = '%s.%s' % (fw_version[0:2], fw_version[2:4]) reply = device.request(0x81F1, 0x02) if reply: fw_version += '.B' + _strhex(reply[1:3]) fw = _FirmwareInfo(FIRMWARE_KIND.Firmware, '', fw_version, None) firmware.append(fw) reply = device.request(0x81F1, 0x04) if reply: bl_version = _strhex(reply[1:3]) bl_version = '%s.%s' % (bl_version[0:2], bl_version[2:4]) bl = _FirmwareInfo(FIRMWARE_KIND.Bootloader, '', bl_version, None) firmware.append(bl) return tuple(firmware)