222 lines
7.4 KiB
Python
222 lines
7.4 KiB
Python
# -*- python-mode -*-
|
|
# -*- coding: UTF-8 -*-
|
|
|
|
## 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.
|
|
|
|
## According to Logitech, they use the following product IDs (as of September 2020)
|
|
## USB product IDs for receivers: 0xC526 - 0xC5xx
|
|
## Wireless PIDs for hidpp10 devices: 0x2006 - 0x2019
|
|
## Wireless PIDs for hidpp20 devices: 0x4002 - 0x4097, 0x4101 - 0x4102
|
|
## USB product IDs for hidpp20 devices: 0xC07D - 0xC093, 0xC32B - 0xC344
|
|
## Bluetooth product IDs (for hidpp20 devices): 0xB012 - 0xB0xx, 0xB32A - 0xB3xx
|
|
|
|
# USB ids of Logitech wireless receivers.
|
|
# Only receivers supporting the HID++ protocol can go in here.
|
|
|
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
|
|
from .descriptors import DEVICES as _DEVICES
|
|
|
|
# max_devices is only used for receivers that do not support reading from _R.receiver_info offset 0x03, default to 1
|
|
# may_unpair is only used for receivers that do not support reading from _R.receiver_info offset 0x03, default to False
|
|
# unpair is for receivers that do support reading from _R.receiver_info offset 0x03, no default
|
|
## should this last be changed so that may_unpair is used for all receivers? writing to _R.receiver_pairing doesn't seem right
|
|
# re_pairs determines whether a receiver pairs by replacing existing pairings, default to False
|
|
## currently only one receiver is so marked - should there be more?
|
|
# ex100_27mhz_wpid_fix enable workarounds for EX100 and possible other old 27Mhz receivers
|
|
|
|
_DRIVER = ('hid-generic', 'generic-usb', 'logitech-djreceiver')
|
|
|
|
_unifying_receiver = lambda product_id: {
|
|
'vendor_id': 0x046d,
|
|
'product_id': product_id,
|
|
'usb_interface': 2,
|
|
'hid_driver': _DRIVER, # noqa: F821
|
|
'name': 'Unifying Receiver'
|
|
}
|
|
|
|
_nano_receiver = lambda product_id: {
|
|
'vendor_id': 0x046d,
|
|
'product_id': product_id,
|
|
'usb_interface': 1,
|
|
'hid_driver': _DRIVER, # noqa: F821
|
|
'name': 'Nano Receiver',
|
|
'may_unpair': False,
|
|
're_pairs': True
|
|
}
|
|
|
|
_nano_receiver_no_unpair = lambda product_id: {
|
|
'vendor_id': 0x046d,
|
|
'product_id': product_id,
|
|
'usb_interface': 1,
|
|
'hid_driver': _DRIVER, # noqa: F821
|
|
'name': 'Nano Receiver',
|
|
'may_unpair': False,
|
|
'unpair': False,
|
|
're_pairs': True
|
|
}
|
|
|
|
_nano_receiver_max2 = lambda product_id: {
|
|
'vendor_id': 0x046d,
|
|
'product_id': product_id,
|
|
'usb_interface': 1,
|
|
'hid_driver': _DRIVER, # noqa: F821
|
|
'name': 'Nano Receiver',
|
|
'max_devices': 2,
|
|
'may_unpair': False,
|
|
're_pairs': True
|
|
}
|
|
|
|
_nano_receiver_maxn = lambda product_id, max: {
|
|
'vendor_id': 0x046d,
|
|
'product_id': product_id,
|
|
'usb_interface': 1,
|
|
'hid_driver': _DRIVER, # noqa: F821
|
|
'name': 'Nano Receiver',
|
|
'max_devices': max,
|
|
'may_unpair': False,
|
|
're_pairs': True
|
|
}
|
|
|
|
_lenovo_receiver = lambda product_id: {
|
|
'vendor_id': 0x17ef,
|
|
'product_id': product_id,
|
|
'usb_interface': 1,
|
|
'hid_driver': _DRIVER, # noqa: F821
|
|
'name': 'Nano Receiver'
|
|
}
|
|
|
|
_lightspeed_receiver = lambda product_id: {
|
|
'vendor_id': 0x046d,
|
|
'product_id': product_id,
|
|
'usb_interface': 2,
|
|
'hid_driver': _DRIVER, # noqa: F821
|
|
'name': 'Lightspeed Receiver'
|
|
}
|
|
|
|
_ex100_receiver = lambda product_id: {
|
|
'vendor_id': 0x046d,
|
|
'product_id': product_id,
|
|
'usb_interface': 1,
|
|
'hid_driver': _DRIVER, # noqa: F821
|
|
'name': 'EX100 Receiver 27 Mhz',
|
|
'max_devices': 4,
|
|
'may_unpair': False,
|
|
're_pairs': True,
|
|
'ex100_27mhz_wpid_fix': True
|
|
}
|
|
|
|
# standard Unifying receivers (marked with the orange Unifying logo)
|
|
UNIFYING_RECEIVER_C52B = _unifying_receiver(0xc52b)
|
|
UNIFYING_RECEIVER_C532 = _unifying_receiver(0xc532)
|
|
|
|
# Nano receviers that support the Unifying protocol
|
|
NANO_RECEIVER_ADVANCED = _nano_receiver(0xc52f)
|
|
|
|
# ex100 old style receiver pre-unifyimg protocol
|
|
EX100_27MHZ_RECEIVER_C517 = _ex100_receiver(0xc517)
|
|
|
|
# Nano receivers that don't support the Unifying protocol
|
|
NANO_RECEIVER_C518 = _nano_receiver(0xc518)
|
|
NANO_RECEIVER_C51A = _nano_receiver(0xc51a)
|
|
NANO_RECEIVER_C51B = _nano_receiver(0xc51b)
|
|
NANO_RECEIVER_C521 = _nano_receiver(0xc521)
|
|
NANO_RECEIVER_C525 = _nano_receiver(0xc525)
|
|
NANO_RECEIVER_C526 = _nano_receiver(0xc526)
|
|
NANO_RECEIVER_C52e = _nano_receiver_no_unpair(0xc52e)
|
|
NANO_RECEIVER_C531 = _nano_receiver(0xc531)
|
|
NANO_RECEIVER_C534 = _nano_receiver_max2(0xc534)
|
|
NANO_RECEIVER_C537 = _nano_receiver(0xc537)
|
|
NANO_RECEIVER_6042 = _lenovo_receiver(0x6042)
|
|
|
|
# Lightspeed receivers
|
|
LIGHTSPEED_RECEIVER_C539 = _lightspeed_receiver(0xc539)
|
|
LIGHTSPEED_RECEIVER_C53a = _lightspeed_receiver(0xc53a)
|
|
LIGHTSPEED_RECEIVER_C53f = _lightspeed_receiver(0xc53f)
|
|
LIGHTSPEED_RECEIVER_C53d = _lightspeed_receiver(0xc53d)
|
|
LIGHTSPEED_RECEIVER_C545 = _lightspeed_receiver(0xc545)
|
|
LIGHTSPEED_RECEIVER_C541 = _lightspeed_receiver(0xc541)
|
|
LIGHTSPEED_RECEIVER_C547 = _lightspeed_receiver(0xc547)
|
|
|
|
ALL = (
|
|
UNIFYING_RECEIVER_C52B,
|
|
UNIFYING_RECEIVER_C532,
|
|
NANO_RECEIVER_ADVANCED,
|
|
EX100_27MHZ_RECEIVER_C517,
|
|
NANO_RECEIVER_C518,
|
|
NANO_RECEIVER_C51A,
|
|
NANO_RECEIVER_C51B,
|
|
NANO_RECEIVER_C521,
|
|
NANO_RECEIVER_C525,
|
|
NANO_RECEIVER_C526,
|
|
NANO_RECEIVER_C52e,
|
|
NANO_RECEIVER_C531,
|
|
NANO_RECEIVER_C534,
|
|
NANO_RECEIVER_C537,
|
|
NANO_RECEIVER_6042,
|
|
LIGHTSPEED_RECEIVER_C539,
|
|
LIGHTSPEED_RECEIVER_C53a,
|
|
LIGHTSPEED_RECEIVER_C53f,
|
|
LIGHTSPEED_RECEIVER_C53d,
|
|
LIGHTSPEED_RECEIVER_C545,
|
|
LIGHTSPEED_RECEIVER_C541,
|
|
LIGHTSPEED_RECEIVER_C547,
|
|
)
|
|
|
|
_wired_device = lambda product_id, interface: {
|
|
'vendor_id': 0x046d,
|
|
'product_id': product_id,
|
|
'bus_id': 0x3,
|
|
'usb_interface': interface,
|
|
'isDevice': True
|
|
}
|
|
|
|
_bt_device = lambda product_id: {'vendor_id': 0x046d, 'product_id': product_id, 'bus_id': 0x5, 'isDevice': True}
|
|
|
|
DEVICES = []
|
|
|
|
for _ignore, d in _DEVICES.items():
|
|
if d.usbid:
|
|
DEVICES.append(_wired_device(d.usbid, d.interface if d.interface else 2))
|
|
if d.btid:
|
|
DEVICES.append(_bt_device(d.btid))
|
|
|
|
|
|
def other_device_check(bus_id, vendor_id, product_id):
|
|
"""Check whether product is a Logitech USB-connected or Bluetooth device based on bus, vendor, and product IDs
|
|
This allows Solaar to support receiverless HID++ 2.0 devices that it knows nothing about"""
|
|
if vendor_id != 0x46d: # Logitech
|
|
return
|
|
if bus_id == 0x3: # USB
|
|
if (product_id >= 0xC07D and product_id <= 0xC093 or product_id >= 0xC32B and product_id <= 0xC344):
|
|
return _wired_device(product_id, 2)
|
|
elif bus_id == 0x5: # Bluetooth
|
|
if (product_id >= 0xB012 and product_id <= 0xB0FF or product_id >= 0xB32A and product_id <= 0xB3FF):
|
|
return _bt_device(product_id)
|
|
|
|
|
|
def product_information(usb_id):
|
|
if isinstance(usb_id, str):
|
|
usb_id = int(usb_id, 16)
|
|
for r in ALL:
|
|
if usb_id == r.get('product_id'):
|
|
return r
|
|
return {}
|
|
|
|
|
|
del _DRIVER, _unifying_receiver, _nano_receiver, _lenovo_receiver, _lightspeed_receiver
|