Solaar/lib/logitech_receiver/descriptors.py

378 lines
17 KiB
Python

## Copyright (C) 2012-2013 Daniel Pavel
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## 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.
#
# Devices (not receivers) known to Solaar.
# Solaar can handle many recent devices without having any entry here.
# An entry should only be added to fix problems, such as
# - the device's device ID or WPID falls outside the range that Solaar searches
# - the device uses a USB interface other than 2
# - the name or codename should be different from what the device reports
from .hidpp10_constants import DEVICE_KIND as _DK
from .hidpp10_constants import REGISTERS as _R
#
#
#
class _DeviceDescriptor:
def __init__(
self,
name=None,
kind=None,
wpid=None,
codename=None,
protocol=None,
registers=None,
usbid=None,
interface=None,
btid=None,
):
self.name = name
self.kind = kind
self.wpid = wpid
self.codename = codename
self.protocol = protocol
self.registers = registers
self.usbid = usbid
self.interface = interface
self.btid = btid
self.settings = None
DEVICES_WPID = {}
DEVICES = {}
def _D(
name,
codename=None,
kind=None,
wpid=None,
protocol=None,
registers=None,
settings=None,
usbid=None,
interface=None,
btid=None,
):
if kind is None:
kind = (
_DK.mouse
if "Mouse" in name
else _DK.keyboard
if "Keyboard" in name
else _DK.numpad
if "Number Pad" in name
else _DK.touchpad
if "Touchpad" in name
else _DK.trackball
if "Trackball" in name
else None
)
assert kind is not None, f"descriptor for {name} does not have kind set"
if protocol is not None:
if wpid:
for w in wpid if isinstance(wpid, tuple) else (wpid,):
if protocol > 1.0:
assert w[0:1] == "4", f"{name} has protocol {protocol:0.1f}, wpid {w}"
else:
if w[0:1] == "1":
assert kind == _DK.mouse, f"{name} has protocol {protocol:0.1f}, wpid {w}"
elif w[0:1] == "2":
assert kind in (_DK.keyboard, _DK.numpad), f"{name} has protocol {protocol:0.1f}, wpid {w}"
device_descriptor = _DeviceDescriptor(
name=name,
kind=kind,
wpid=wpid,
codename=codename,
protocol=protocol,
registers=registers,
usbid=usbid,
interface=interface,
btid=btid,
)
if usbid:
found = get_usbid(usbid)
assert found is None, f"duplicate usbid in device descriptors: {found}"
if btid:
found = get_btid(btid)
assert found is None, f"duplicate btid in device descriptors: {found}"
assert codename not in DEVICES, f"duplicate codename in device descriptors: {DEVICES[codename]}"
if codename:
DEVICES[codename] = device_descriptor
if wpid:
for w in wpid if isinstance(wpid, tuple) else (wpid,):
assert w not in DEVICES_WPID, f"duplicate wpid in device descriptors: {DEVICES_WPID[w]}"
DEVICES_WPID[w] = device_descriptor
def get_wpid(wpid):
return DEVICES_WPID.get(wpid)
def get_codename(codename):
return DEVICES.get(codename)
def get_usbid(usbid):
if isinstance(usbid, str):
usbid = int(usbid, 16)
found = next((x for x in DEVICES.values() if x.usbid == usbid), None)
return found
def get_btid(btid):
if isinstance(btid, str):
btid = int(btid, 16)
found = next((x for x in DEVICES.values() if x.btid == btid), None)
return found
# Some HID++1.0 registers and HID++2.0 features can be discovered at run-time,
# so they are not specified here.
#
# State registers (battery, leds, some features, etc) are only used by
# HID++ 1.0 devices, while HID++ 2.0 devices use features for the same
# functionalities.
# Well-known registers (in hex):
# * 00 - notification flags (all devices)
# 01 - mice: smooth scrolling
# 07 - battery status
# 09 - keyboards: FN swap (if it has the FN key)
# 0D - battery charge
# a device may have either the 07 or 0D register available;
# no known device uses both
# 51 - leds
# 63 - mice: DPI
# * F1 - firmware info
# Some registers appear to be universally supported, no matter the HID++ version
# (marked with *). The rest may or may not be supported, and their values may or
# may not mean the same thing across different devices.
# The 'codename' and 'kind' fields are usually guessed from the device name,
# but in some cases (like the Logitech Cube) that heuristic fails and they have
# to be specified.
#
# The 'protocol' and 'wpid' fields are optional (they can be discovered at
# runtime), but specifying them here speeds up device discovery and reduces the
# USB traffic Solaar has to do to fully identify peripherals.
#
# The 'registers' field indicates read-only registers, specifying a state. These
# are valid (AFAIK) only to HID++ 1.0 devices.
# The 'settings' field indicates a read/write register; based on them Solaar
# generates, at runtime, the settings controls in the device panel.
# Solaar now sets up this field in settings_templates.py to eliminate a imports loop.
# HID++ 1.0 devices may only have register-based settings; HID++ 2.0 devices may only have
# feature-based settings.
# Devices are organized by kind
# Within kind devices are sorted by wpid, then by usbid, then by btid, with missing values sorted later
# Keyboards
_D("Wireless Keyboard EX110", codename="EX110", protocol=1.0, wpid="0055", registers=(_R.battery_status,))
_D("Wireless Keyboard S510", codename="S510", protocol=1.0, wpid="0056", registers=(_R.battery_status,))
_D("Wireless Wave Keyboard K550", codename="K550", protocol=1.0, wpid="0060", registers=(_R.battery_status,))
_D("Wireless Keyboard EX100", codename="EX100", protocol=1.0, wpid="0065", registers=(_R.battery_status,))
_D("Wireless Keyboard MK300", codename="MK300", protocol=1.0, wpid="0068", registers=(_R.battery_status,))
_D("Number Pad N545", codename="N545", protocol=1.0, wpid="2006", registers=(_R.battery_status,))
_D("Wireless Compact Keyboard K340", codename="K340", protocol=1.0, wpid="2007", registers=(_R.battery_status,))
_D("Wireless Keyboard MK700", codename="MK700", protocol=1.0, wpid="2008", registers=(_R.battery_status,))
_D("Wireless Wave Keyboard K350", codename="K350", protocol=1.0, wpid="200A", registers=(_R.battery_status,))
_D("Wireless Keyboard MK320", codename="MK320", protocol=1.0, wpid="200F", registers=(_R.battery_status,))
_D(
"Wireless Illuminated Keyboard K800",
codename="K800",
protocol=1.0,
wpid="2010",
registers=(_R.battery_status, _R.three_leds),
)
_D("Wireless Keyboard K520", codename="K520", protocol=1.0, wpid="2011", registers=(_R.battery_status,))
_D("Wireless Solar Keyboard K750", codename="K750", protocol=2.0, wpid="4002")
_D("Wireless Keyboard K270 (unifying)", codename="K270", protocol=2.0, wpid="4003")
_D("Wireless Keyboard K360", codename="K360", protocol=2.0, wpid="4004")
_D("Wireless Keyboard K230", codename="K230", protocol=2.0, wpid="400D")
_D("Wireless Touch Keyboard K400", codename="K400", protocol=2.0, wpid=("400E", "4024"))
_D("Wireless Keyboard MK270", codename="MK270", protocol=2.0, wpid="4023")
_D("Illuminated Living-Room Keyboard K830", codename="K830", protocol=2.0, wpid="4032")
_D("Wireless Touch Keyboard K400 Plus", codename="K400 Plus", protocol=2.0, wpid="404D")
_D("Wireless Multi-Device Keyboard K780", codename="K780", protocol=4.5, wpid="405B")
_D("Wireless Keyboard K375s", codename="K375s", protocol=2.0, wpid="4061")
_D("Craft Advanced Keyboard", codename="Craft", protocol=4.5, wpid="4066", btid=0xB350)
_D("Wireless Illuminated Keyboard K800 new", codename="K800 new", protocol=4.5, wpid="406E")
_D("Wireless Keyboard K470", codename="K470", protocol=4.5, wpid="4075")
_D("MX Keys Keyboard", codename="MX Keys", protocol=4.5, wpid="408A", btid=0xB35B)
_D("G915 TKL LIGHTSPEED Wireless RGB Mechanical Gaming Keyboard", codename="G915 TKL", protocol=4.2, wpid="408E", usbid=0xC343)
_D("Illuminated Keyboard", codename="Illuminated", protocol=1.0, usbid=0xC318, interface=1)
_D("G213 Prodigy Gaming Keyboard", codename="G213", usbid=0xC336, interface=1)
_D("G512 RGB Mechanical Gaming Keyboard", codename="G512", usbid=0xC33C, interface=1)
_D("G815 Mechanical Keyboard", codename="G815", usbid=0xC33F, interface=1)
_D("diNovo Edge Keyboard", codename="diNovo", protocol=1.0, wpid="C714")
_D("K845 Mechanical Keyboard", codename="K845", usbid=0xC341, interface=3)
# Mice
_D("LX5 Cordless Mouse", codename="LX5", protocol=1.0, wpid="0036", registers=(_R.battery_status,))
_D("LX7 Cordless Laser Mouse", codename="LX7", protocol=1.0, wpid="0039", registers=(_R.battery_status,))
_D("Wireless Wave Mouse M550", codename="M550", protocol=1.0, wpid="003C", registers=(_R.battery_status,))
_D("Wireless Mouse EX100", codename="EX100m", protocol=1.0, wpid="003F", registers=(_R.battery_status,))
_D("Wireless Mouse M30", codename="M30", protocol=1.0, wpid="0085", registers=(_R.battery_status,))
_D("MX610 Laser Cordless Mouse", codename="MX610", protocol=1.0, wpid="1001", registers=(_R.battery_status,))
_D("G7 Cordless Laser Mouse", codename="G7", protocol=1.0, wpid="1002", registers=(_R.battery_status,))
_D("V400 Laser Cordless Mouse", codename="V400", protocol=1.0, wpid="1003", registers=(_R.battery_status,))
_D("MX610 Left-Handled Mouse", codename="MX610L", protocol=1.0, wpid="1004", registers=(_R.battery_status,))
_D("V450 Laser Cordless Mouse", codename="V450", protocol=1.0, wpid="1005", registers=(_R.battery_status,))
_D(
"VX Revolution",
codename="VX Revolution",
kind=_DK.mouse,
protocol=1.0,
wpid=("1006", "100D", "0612"),
registers=(_R.battery_charge,),
)
_D("MX Air", codename="MX Air", protocol=1.0, kind=_DK.mouse, wpid=("1007", "100E"), registers=(_R.battery_charge,))
_D(
"MX Revolution",
codename="MX Revolution",
protocol=1.0,
kind=_DK.mouse,
wpid=("1008", "100C"),
registers=(_R.battery_charge,),
)
_D("MX620 Laser Cordless Mouse", codename="MX620", protocol=1.0, wpid=("100A", "1016"), registers=(_R.battery_charge,))
_D("VX Nano Cordless Laser Mouse", codename="VX Nano", protocol=1.0, wpid=("100B", "100F"), registers=(_R.battery_charge,))
_D("V450 Nano Cordless Laser Mouse", codename="V450 Nano", protocol=1.0, wpid="1011", registers=(_R.battery_charge,))
_D("V550 Nano Cordless Laser Mouse", codename="V550 Nano", protocol=1.0, wpid="1013", registers=(_R.battery_charge,))
_D(
"MX 1100 Cordless Laser Mouse",
codename="MX 1100",
protocol=1.0,
kind=_DK.mouse,
wpid="1014",
registers=(_R.battery_charge,),
)
_D("Anywhere Mouse MX", codename="Anywhere MX", protocol=1.0, wpid="1017", registers=(_R.battery_charge,))
_D("Performance Mouse MX", codename="Performance MX", protocol=1.0, wpid="101A", registers=(_R.battery_status, _R.three_leds))
_D("Marathon Mouse M705 (M-R0009)", codename="M705 (M-R0009)", protocol=1.0, wpid="101B", registers=(_R.battery_charge,))
_D("Wireless Mouse M350", codename="M350", protocol=1.0, wpid="101C", registers=(_R.battery_charge,))
_D("Wireless Mouse M505", codename="M505/B605", protocol=1.0, wpid="101D", registers=(_R.battery_charge,))
_D("Wireless Mouse M305", codename="M305", protocol=1.0, wpid="101F", registers=(_R.battery_status,))
_D("Wireless Mouse M215", codename="M215", protocol=1.0, wpid="1020")
_D(
"G700 Gaming Mouse",
codename="G700",
protocol=1.0,
wpid="1023",
usbid=0xC06B,
interface=1,
registers=(
_R.battery_status,
_R.three_leds,
),
)
_D("Wireless Mouse M310", codename="M310", protocol=1.0, wpid="1024", registers=(_R.battery_status,))
_D("Wireless Mouse M510", codename="M510", protocol=1.0, wpid="1025", registers=(_R.battery_status,))
_D("Fujitsu Sonic Mouse", codename="Sonic", protocol=1.0, wpid="1029")
_D(
"G700s Gaming Mouse",
codename="G700s",
protocol=1.0,
wpid="102A",
usbid=0xC07C,
interface=1,
registers=(
_R.battery_status,
_R.three_leds,
),
)
_D("Couch Mouse M515", codename="M515", protocol=2.0, wpid="4007")
_D("Wireless Mouse M175", codename="M175", protocol=2.0, wpid="4008")
_D("Wireless Mouse M325", codename="M325", protocol=2.0, wpid="400A")
_D("Wireless Mouse M525", codename="M525", protocol=2.0, wpid="4013")
_D("Wireless Mouse M345", codename="M345", protocol=2.0, wpid="4017")
_D("Wireless Mouse M187", codename="M187", protocol=2.0, wpid="4019")
_D("Touch Mouse M600", codename="M600", protocol=2.0, wpid="401A")
_D("Wireless Mouse M150", codename="M150", protocol=2.0, wpid="4022")
_D("Wireless Mouse M185", codename="M185", protocol=2.0, wpid="4038")
_D("Wireless Mouse MX Master", codename="MX Master", protocol=4.5, wpid="4041", btid=0xB012)
_D("Anywhere Mouse MX 2", codename="Anywhere MX 2", protocol=4.5, wpid="404A")
_D("Wireless Mouse M510", codename="M510v2", protocol=2.0, wpid="4051")
_D("Wireless Mouse M185 new", codename="M185n", protocol=4.5, wpid="4054")
_D("Wireless Mouse M185/M235/M310", codename="M185/M235/M310", protocol=4.5, wpid="4055")
_D("Wireless Mouse MX Master 2S", codename="MX Master 2S", protocol=4.5, wpid="4069", btid=0xB019)
_D("Multi Device Silent Mouse M585/M590", codename="M585/M590", protocol=4.5, wpid="406B")
_D(
"Marathon Mouse M705 (M-R0073)",
codename="M705 (M-R0073)",
protocol=4.5,
wpid="406D",
)
_D("MX Vertical Wireless Mouse", codename="MX Vertical", protocol=4.5, wpid="407B", btid=0xB020, usbid=0xC08A)
_D("Wireless Mouse Pebble M350", codename="Pebble", protocol=2.0, wpid="4080")
_D("MX Master 3 Wireless Mouse", codename="MX Master 3", protocol=4.5, wpid="4082", btid=0xB023)
_D("PRO X Wireless", kind="mouse", codename="PRO X", wpid="4093", usbid=0xC094)
_D("G9 Laser Mouse", codename="G9", usbid=0xC048, interface=1, protocol=1.0)
_D("G9x Laser Mouse", codename="G9x", usbid=0xC066, interface=1, protocol=1.0)
_D("G502 Gaming Mouse", codename="G502", usbid=0xC07D, interface=1)
_D("G402 Gaming Mouse", codename="G402", usbid=0xC07E, interface=1)
_D("G900 Chaos Spectrum Gaming Mouse", codename="G900", usbid=0xC081)
_D("G403 Gaming Mouse", codename="G403", usbid=0xC082)
_D("G903 Lightspeed Gaming Mouse", codename="G903", usbid=0xC086)
_D("G703 Lightspeed Gaming Mouse", codename="G703", usbid=0xC087)
_D("GPro Gaming Mouse", codename="GPro", usbid=0xC088)
_D("G502 SE Hero Gaming Mouse", codename="G502 Hero", usbid=0xC08B, interface=1)
_D("G502 Lightspeed Gaming Mouse", codename="G502 Lightspeed", usbid=0xC08D)
_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=_DK.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)
_D("G502 Proteus Spectrum Optical Mouse", codename="G502 Proteus Spectrum", usbid=0xC332, interface=1)
_D("Logitech PRO Gaming Keyboard", codename="PRO Gaming Keyboard", usbid=0xC339, interface=1)
_D("Logitech MX Revolution Mouse M-RCL 124", codename="M-RCL 124", btid=0xB007, interface=1)
# Trackballs
_D("Wireless Trackball M570", codename="M570")
# Touchpads
_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=_DK.touchpad, wpid="405F") # To override self-identification
# Headset
_D("G533 Gaming Headset", codename="G533 Headset", protocol=2.0, interface=3, kind=_DK.headset, usbid=0x0A66)
_D("G535 Gaming Headset", codename="G535 Headset", protocol=2.0, interface=3, kind=_DK.headset, usbid=0x0AC4)
_D("G935 Gaming Headset", codename="G935 Headset", protocol=2.0, interface=3, kind=_DK.headset, usbid=0x0A87)
_D("G733 Gaming Headset", codename="G733 Headset", protocol=2.0, interface=3, kind=_DK.headset, usbid=0x0AB5)
_D("G733 Gaming Headset", codename="G733 Headset New", protocol=2.0, interface=3, kind=_DK.headset, usbid=0x0AFE)
_D("PRO X Wireless Gaming Headset", codename="PRO Headset", protocol=2.0, interface=3, kind=_DK.headset, usbid=0x0ABA)