receiver: add support for Bolt receiver (no pairing yet)

This commit is contained in:
Peter F. Patel-Schneider 2021-11-02 09:45:52 -04:00
parent 2c3578a776
commit 886df1daaf
4 changed files with 50 additions and 6 deletions

View File

@ -39,12 +39,24 @@ from .i18n import _
_DRIVER = ('hid-generic', 'generic-usb', 'logitech-djreceiver')
_bolt_receiver = lambda product_id: {
'vendor_id': 0x046d,
'product_id': product_id,
'usb_interface': 2,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Bolt Receiver'),
'receiver_kind': 'bolt',
'max_devices': 6,
'may_unpair': True
}
_unifying_receiver = lambda product_id: {
'vendor_id': 0x046d,
'product_id': product_id,
'usb_interface': 2,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Unifying Receiver')
'name': _('Unifying Receiver'),
'receiver_kind': 'unifying'
}
_nano_receiver = lambda product_id: {
@ -53,6 +65,7 @@ _nano_receiver = lambda product_id: {
'usb_interface': 1,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Nano Receiver'),
'receiver_kind': 'nano',
'may_unpair': False,
're_pairs': True
}
@ -63,6 +76,7 @@ _nano_receiver_no_unpair = lambda product_id: {
'usb_interface': 1,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Nano Receiver'),
'receiver_kind': 'nano',
'may_unpair': False,
'unpair': False,
're_pairs': True
@ -74,6 +88,7 @@ _nano_receiver_max2 = lambda product_id: {
'usb_interface': 1,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Nano Receiver'),
'receiver_kind': 'nano',
'max_devices': 2,
'may_unpair': False,
're_pairs': True
@ -85,6 +100,7 @@ _nano_receiver_maxn = lambda product_id, max: {
'usb_interface': 1,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Nano Receiver'),
'receiver_kind': 'nano',
'max_devices': max,
'may_unpair': False,
're_pairs': True
@ -95,7 +111,8 @@ _lenovo_receiver = lambda product_id: {
'product_id': product_id,
'usb_interface': 1,
'hid_driver': _DRIVER, # noqa: F821
'name': _('Nano Receiver')
'name': _('Nano Receiver'),
'receiver_kind': 'nano'
}
_lightspeed_receiver = lambda product_id: {
@ -112,12 +129,16 @@ _ex100_receiver = lambda product_id: {
'usb_interface': 1,
'hid_driver': _DRIVER, # noqa: F821
'name': _('EX100 Receiver 27 Mhz'),
'receiver_kind': '27Mhz',
'max_devices': 4,
'may_unpair': False,
're_pairs': True,
'ex100_27mhz_wpid_fix': True
}
# Bolt receivers (marked with the yellow lightning bolt logo)
BOLT_RECEIVER_C548 = _bolt_receiver(0xc548)
# standard Unifying receivers (marked with the orange Unifying logo)
UNIFYING_RECEIVER_C52B = _unifying_receiver(0xc52b)
UNIFYING_RECEIVER_C532 = _unifying_receiver(0xc532)
@ -151,6 +172,7 @@ LIGHTSPEED_RECEIVER_C541 = _lightspeed_receiver(0xc541)
LIGHTSPEED_RECEIVER_C547 = _lightspeed_receiver(0xc547)
ALL = (
BOLT_RECEIVER_C548,
UNIFYING_RECEIVER_C52B,
UNIFYING_RECEIVER_C532,
NANO_RECEIVER_ADVANCED,

View File

@ -143,6 +143,7 @@ INFO_SUBREGISTERS = _NamedInts(
pairing_information=0x20, # 0x2N, by connected device
extended_pairing_information=0x30, # 0x3N, by connected device
device_name=0x40, # 0x4N, by connected device
bolt_pairing_information=0x50, # 0x5N, by connected device
)
# Flags taken from https://drive.google.com/file/d/0BxbRzx7vEV7eNDBheWY0UHM5dEU/view?usp=sharing

View File

@ -59,8 +59,12 @@ class Receiver:
product_info = _product_information(self.product_id)
if not product_info:
raise Exception('Unknown receiver type', self.product_id)
self.receiver_kind = product_info.get('receiver_kind', 'unknown')
# read the serial immediately, so we can find out max_devices
if self.receiver_kind == 'bolt':
serial_reply = None
else:
serial_reply = self.read_register(_R.receiver_info, _IR.receiver_information)
if serial_reply:
self.serial = _strhex(serial_reply[1:5])
@ -73,7 +77,7 @@ class Receiver:
self.may_unpair = product_info['unpair']
else:
self.may_unpair = self.write_register(_R.receiver_pairing) is None
else: # handle receivers that don't have a serial number specially (i.e., c534)
else: # handle receivers that don't have a serial number specially (i.e., c534 and Bolt receivers)
self.serial = None
self.max_devices = product_info.get('max_devices', 1)
self.may_unpair = product_info.get('may_unpair', False)
@ -138,6 +142,8 @@ class Receiver:
return flag_bits
def device_codename(self, n):
if self.receiver_kind == 'bolt':
return
codename = self.read_register(_R.receiver_info, _IR.device_name + n - 1)
if codename:
codename_length = ord(codename[1:2])
@ -145,6 +151,14 @@ class Receiver:
return codename.decode('ascii')
def device_pairing_information(self, n):
if self.receiver_kind == 'bolt':
pair_info = self.read_register(_R.receiver_info, _IR.bolt_pairing_information + n)
if pair_info:
wpid = _strhex(pair_info[3:4]) + _strhex(pair_info[2:3])
kind = _hidpp10.DEVICE_KIND[ord(pair_info[1:2]) & 0x0F]
return wpid, kind, 0
else:
return '0000', _hidpp10.DEVICE_KIND[0], 0
pair_info = self.read_register(_R.receiver_info, _IR.pairing_information + n - 1)
polling_rate = 0
if pair_info: # may be either a Unifying receiver, or an Unifying-ready receiver
@ -168,8 +182,15 @@ class Receiver:
return wpid, kind, polling_rate
def device_extended_pairing_information(self, n):
pair_info = self.read_register(_R.receiver_info, _IR.extended_pairing_information + n - 1)
power_switch = '(unknown)'
if self.receiver_kind == 'bolt':
pair_info = self.read_register(_R.receiver_info, _IR.bolt_pairing_information + n)
if pair_info:
serial = _strhex(pair_info[4:8])
return serial, power_switch
else:
return '?', power_switch
pair_info = self.read_register(_R.receiver_info, _IR.extended_pairing_information + n - 1)
if pair_info:
power_switch = _hidpp10.POWER_SWITCH_LOCATION[ord(pair_info[9:10]) & 0x0F]
else: # some Nano receivers?

View File

@ -224,7 +224,7 @@ class ReceiverListener(_listener.EventsListener):
return
elif n.sub_id == 0x41:
if not already_known:
if n.address == 0x0A:
if n.address == 0x0A and not self.receiver.receiver_kind == 'bolt':
# some Nanos send a notification even if no new pairing - check that there really is a device there
if self.receiver.read_register(_R.receiver_info, _IR.pairing_information + n.devnumber - 1) is None:
return