receiver: add support for Bolt receiver (no pairing yet)
This commit is contained in:
parent
2c3578a776
commit
886df1daaf
|
@ -39,12 +39,24 @@ from .i18n import _
|
||||||
|
|
||||||
_DRIVER = ('hid-generic', 'generic-usb', 'logitech-djreceiver')
|
_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: {
|
_unifying_receiver = lambda product_id: {
|
||||||
'vendor_id': 0x046d,
|
'vendor_id': 0x046d,
|
||||||
'product_id': product_id,
|
'product_id': product_id,
|
||||||
'usb_interface': 2,
|
'usb_interface': 2,
|
||||||
'hid_driver': _DRIVER, # noqa: F821
|
'hid_driver': _DRIVER, # noqa: F821
|
||||||
'name': _('Unifying Receiver')
|
'name': _('Unifying Receiver'),
|
||||||
|
'receiver_kind': 'unifying'
|
||||||
}
|
}
|
||||||
|
|
||||||
_nano_receiver = lambda product_id: {
|
_nano_receiver = lambda product_id: {
|
||||||
|
@ -53,6 +65,7 @@ _nano_receiver = lambda product_id: {
|
||||||
'usb_interface': 1,
|
'usb_interface': 1,
|
||||||
'hid_driver': _DRIVER, # noqa: F821
|
'hid_driver': _DRIVER, # noqa: F821
|
||||||
'name': _('Nano Receiver'),
|
'name': _('Nano Receiver'),
|
||||||
|
'receiver_kind': 'nano',
|
||||||
'may_unpair': False,
|
'may_unpair': False,
|
||||||
're_pairs': True
|
're_pairs': True
|
||||||
}
|
}
|
||||||
|
@ -63,6 +76,7 @@ _nano_receiver_no_unpair = lambda product_id: {
|
||||||
'usb_interface': 1,
|
'usb_interface': 1,
|
||||||
'hid_driver': _DRIVER, # noqa: F821
|
'hid_driver': _DRIVER, # noqa: F821
|
||||||
'name': _('Nano Receiver'),
|
'name': _('Nano Receiver'),
|
||||||
|
'receiver_kind': 'nano',
|
||||||
'may_unpair': False,
|
'may_unpair': False,
|
||||||
'unpair': False,
|
'unpair': False,
|
||||||
're_pairs': True
|
're_pairs': True
|
||||||
|
@ -74,6 +88,7 @@ _nano_receiver_max2 = lambda product_id: {
|
||||||
'usb_interface': 1,
|
'usb_interface': 1,
|
||||||
'hid_driver': _DRIVER, # noqa: F821
|
'hid_driver': _DRIVER, # noqa: F821
|
||||||
'name': _('Nano Receiver'),
|
'name': _('Nano Receiver'),
|
||||||
|
'receiver_kind': 'nano',
|
||||||
'max_devices': 2,
|
'max_devices': 2,
|
||||||
'may_unpair': False,
|
'may_unpair': False,
|
||||||
're_pairs': True
|
're_pairs': True
|
||||||
|
@ -85,6 +100,7 @@ _nano_receiver_maxn = lambda product_id, max: {
|
||||||
'usb_interface': 1,
|
'usb_interface': 1,
|
||||||
'hid_driver': _DRIVER, # noqa: F821
|
'hid_driver': _DRIVER, # noqa: F821
|
||||||
'name': _('Nano Receiver'),
|
'name': _('Nano Receiver'),
|
||||||
|
'receiver_kind': 'nano',
|
||||||
'max_devices': max,
|
'max_devices': max,
|
||||||
'may_unpair': False,
|
'may_unpair': False,
|
||||||
're_pairs': True
|
're_pairs': True
|
||||||
|
@ -95,7 +111,8 @@ _lenovo_receiver = lambda product_id: {
|
||||||
'product_id': product_id,
|
'product_id': product_id,
|
||||||
'usb_interface': 1,
|
'usb_interface': 1,
|
||||||
'hid_driver': _DRIVER, # noqa: F821
|
'hid_driver': _DRIVER, # noqa: F821
|
||||||
'name': _('Nano Receiver')
|
'name': _('Nano Receiver'),
|
||||||
|
'receiver_kind': 'nano'
|
||||||
}
|
}
|
||||||
|
|
||||||
_lightspeed_receiver = lambda product_id: {
|
_lightspeed_receiver = lambda product_id: {
|
||||||
|
@ -112,12 +129,16 @@ _ex100_receiver = lambda product_id: {
|
||||||
'usb_interface': 1,
|
'usb_interface': 1,
|
||||||
'hid_driver': _DRIVER, # noqa: F821
|
'hid_driver': _DRIVER, # noqa: F821
|
||||||
'name': _('EX100 Receiver 27 Mhz'),
|
'name': _('EX100 Receiver 27 Mhz'),
|
||||||
|
'receiver_kind': '27Mhz',
|
||||||
'max_devices': 4,
|
'max_devices': 4,
|
||||||
'may_unpair': False,
|
'may_unpair': False,
|
||||||
're_pairs': True,
|
're_pairs': True,
|
||||||
'ex100_27mhz_wpid_fix': 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)
|
# standard Unifying receivers (marked with the orange Unifying logo)
|
||||||
UNIFYING_RECEIVER_C52B = _unifying_receiver(0xc52b)
|
UNIFYING_RECEIVER_C52B = _unifying_receiver(0xc52b)
|
||||||
UNIFYING_RECEIVER_C532 = _unifying_receiver(0xc532)
|
UNIFYING_RECEIVER_C532 = _unifying_receiver(0xc532)
|
||||||
|
@ -151,6 +172,7 @@ LIGHTSPEED_RECEIVER_C541 = _lightspeed_receiver(0xc541)
|
||||||
LIGHTSPEED_RECEIVER_C547 = _lightspeed_receiver(0xc547)
|
LIGHTSPEED_RECEIVER_C547 = _lightspeed_receiver(0xc547)
|
||||||
|
|
||||||
ALL = (
|
ALL = (
|
||||||
|
BOLT_RECEIVER_C548,
|
||||||
UNIFYING_RECEIVER_C52B,
|
UNIFYING_RECEIVER_C52B,
|
||||||
UNIFYING_RECEIVER_C532,
|
UNIFYING_RECEIVER_C532,
|
||||||
NANO_RECEIVER_ADVANCED,
|
NANO_RECEIVER_ADVANCED,
|
||||||
|
|
|
@ -143,6 +143,7 @@ INFO_SUBREGISTERS = _NamedInts(
|
||||||
pairing_information=0x20, # 0x2N, by connected device
|
pairing_information=0x20, # 0x2N, by connected device
|
||||||
extended_pairing_information=0x30, # 0x3N, by connected device
|
extended_pairing_information=0x30, # 0x3N, by connected device
|
||||||
device_name=0x40, # 0x4N, 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
|
# Flags taken from https://drive.google.com/file/d/0BxbRzx7vEV7eNDBheWY0UHM5dEU/view?usp=sharing
|
||||||
|
|
|
@ -59,8 +59,12 @@ class Receiver:
|
||||||
product_info = _product_information(self.product_id)
|
product_info = _product_information(self.product_id)
|
||||||
if not product_info:
|
if not product_info:
|
||||||
raise Exception('Unknown receiver type', self.product_id)
|
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
|
# 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)
|
serial_reply = self.read_register(_R.receiver_info, _IR.receiver_information)
|
||||||
if serial_reply:
|
if serial_reply:
|
||||||
self.serial = _strhex(serial_reply[1:5])
|
self.serial = _strhex(serial_reply[1:5])
|
||||||
|
@ -73,7 +77,7 @@ class Receiver:
|
||||||
self.may_unpair = product_info['unpair']
|
self.may_unpair = product_info['unpair']
|
||||||
else:
|
else:
|
||||||
self.may_unpair = self.write_register(_R.receiver_pairing) is None
|
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.serial = None
|
||||||
self.max_devices = product_info.get('max_devices', 1)
|
self.max_devices = product_info.get('max_devices', 1)
|
||||||
self.may_unpair = product_info.get('may_unpair', False)
|
self.may_unpair = product_info.get('may_unpair', False)
|
||||||
|
@ -138,6 +142,8 @@ class Receiver:
|
||||||
return flag_bits
|
return flag_bits
|
||||||
|
|
||||||
def device_codename(self, n):
|
def device_codename(self, n):
|
||||||
|
if self.receiver_kind == 'bolt':
|
||||||
|
return
|
||||||
codename = self.read_register(_R.receiver_info, _IR.device_name + n - 1)
|
codename = self.read_register(_R.receiver_info, _IR.device_name + n - 1)
|
||||||
if codename:
|
if codename:
|
||||||
codename_length = ord(codename[1:2])
|
codename_length = ord(codename[1:2])
|
||||||
|
@ -145,6 +151,14 @@ class Receiver:
|
||||||
return codename.decode('ascii')
|
return codename.decode('ascii')
|
||||||
|
|
||||||
def device_pairing_information(self, n):
|
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)
|
pair_info = self.read_register(_R.receiver_info, _IR.pairing_information + n - 1)
|
||||||
polling_rate = 0
|
polling_rate = 0
|
||||||
if pair_info: # may be either a Unifying receiver, or an Unifying-ready receiver
|
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
|
return wpid, kind, polling_rate
|
||||||
|
|
||||||
def device_extended_pairing_information(self, n):
|
def device_extended_pairing_information(self, n):
|
||||||
pair_info = self.read_register(_R.receiver_info, _IR.extended_pairing_information + n - 1)
|
|
||||||
power_switch = '(unknown)'
|
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:
|
if pair_info:
|
||||||
power_switch = _hidpp10.POWER_SWITCH_LOCATION[ord(pair_info[9:10]) & 0x0F]
|
power_switch = _hidpp10.POWER_SWITCH_LOCATION[ord(pair_info[9:10]) & 0x0F]
|
||||||
else: # some Nano receivers?
|
else: # some Nano receivers?
|
||||||
|
|
|
@ -224,7 +224,7 @@ class ReceiverListener(_listener.EventsListener):
|
||||||
return
|
return
|
||||||
elif n.sub_id == 0x41:
|
elif n.sub_id == 0x41:
|
||||||
if not already_known:
|
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
|
# 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:
|
if self.receiver.read_register(_R.receiver_info, _IR.pairing_information + n.devnumber - 1) is None:
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue