receiver: determine remaining pairings (if receiver has this) and display in solaar show and main window

This commit is contained in:
Peter F. Patel-Schneider 2020-02-08 14:08:13 -05:00 committed by Filipe Laíns
parent 1ab03d4c9f
commit 546ccb7ac2
4 changed files with 49 additions and 17 deletions

View File

@ -25,6 +25,11 @@ from __future__ import absolute_import, division, print_function, unicode_litera
_DRIVER = ('hid-generic', 'generic-usb', 'logitech-djreceiver')
# 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
## 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?
_unifying_receiver = lambda product_id: {
'vendor_id':0x046d,
@ -42,6 +47,17 @@ _nano_receiver = lambda product_id: {
'name':'Nano Receiver'
}
_nano_receiver_max2 = lambda product_id: {
'vendor_id':0x046d,
'product_id':product_id,
'usb_interface':1,
'hid_driver':_DRIVER,
'name':'Nano Receiver',
'max_devices': 2,
'may_unpair': False,
're_pairs': True
}
_lenovo_receiver = lambda product_id: {
'vendor_id':0x17ef,
'product_id':product_id,
@ -75,7 +91,7 @@ NANO_RECEIVER_C525 = _nano_receiver(0xc525)
NANO_RECEIVER_C526 = _nano_receiver(0xc526)
NANO_RECEIVER_C52e = _nano_receiver(0xc52e)
NANO_RECEIVER_C531 = _nano_receiver(0xc531)
NANO_RECEIVER_C534 = _nano_receiver(0xc534)
NANO_RECEIVER_C534 = _nano_receiver_max2(0xc534)
NANO_RECEIVER_6042 = _lenovo_receiver(0x6042)
# Lightspeed receivers

View File

@ -334,29 +334,31 @@ class Receiver(object):
self.path = device_info.path
# USB product id, used for some Nano receivers
self.product_id = device_info.product_id
# read the serial immediately, so we can find out max_devices
# this will tell us if it's a Unifying or Nano receiver
if self.product_id != 'c534':
serial_reply = self.read_register(_R.receiver_info, 0x03)
assert serial_reply
self.serial = _strhex(serial_reply[1:5])
self.max_devices = ord(serial_reply[6:7])
else:
self.serial = None
self.max_devices = 6
product_info = _product_information(self.product_id)
if not product_info:
raise Exception("unknown receiver type", self.product_id)
self.name = product_info.get('name','')
self._str = '<%s(%s,%s%s)>' % (self.name.replace(' ', ''), self.path, '' if isinstance(self.handle, int) else 'T', self.handle)
# read the serial immediately, so we can find out max_devices
# this will tell us if it's a Unifying or Nano receiver
serial_reply = self.read_register(_R.receiver_info, 0x03)
if serial_reply :
self.serial = _strhex(serial_reply[1:5])
self.max_devices = ord(serial_reply[6:7])
# TODO _properly_ figure out which receivers do and which don't support unpairing
# This code supposes that receivers that don't unpair support a pairing request for device index 0
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)
self.serial = None
self.max_devices = product_info.get('max_devices',1)
self.may_unpair = product_info.get('may_unpair',False)
self.name = product_info.get('name','')
self.re_pairs = product_info.get('re_pairs',False)
self._str = '<%s(%s,%s%s)>' % (self.name.replace(' ', ''), self.path, '' if isinstance(self.handle, int) else 'T', self.handle)
self._firmware = None
self._devices = {}
self._remaining_pairings = None
def close(self):
handle, self.handle = self.handle, None
@ -372,6 +374,15 @@ class Receiver(object):
self._firmware = _hidpp10.get_firmware(self)
return self._firmware
# how many pairings remain (None for unknown, -1 for unlimited)
def remaining_pairings(self,cache=True):
if self._remaining_pairings is None or not cache :
ps = self.read_register(_R.receiver_connection)
if ps is not None:
ps = ord(ps[2:3])
self._remaining_pairings = ps-5 if ps >= 5 else -1
return self._remaining_pairings
def enable_notifications(self, enable=True):
"""Enable or disable device (dis)connection notifications on this
receiver."""

View File

@ -38,6 +38,8 @@ def _print_receiver(receiver):
print (' %-11s: %s' % (f.kind, f.version))
print (' Has', paired_count, 'paired device(s) out of a maximum of %d.' % receiver.max_devices)
if receiver.remaining_pairings() and receiver.remaining_pairings() >= 0 :
print (' Has %d successful pairing(s) remaining.' % receiver.remaining_pairings() )
notification_flags = _hidpp10.get_notification_flags(receiver)
if notification_flags is not None:

View File

@ -572,6 +572,9 @@ def _update_receiver_panel(receiver, panel, buttons, full=False):
paired_text += '\n\n<small>%s</small>' % ngettext('Up to %(max_count)s device can be paired to this receiver.', 'Up to %(max_count)s devices can be paired to this receiver.', receiver.max_devices) % { 'max_count': receiver.max_devices }
elif(devices_count > 0):
paired_text += '\n\n<small>%s</small>' % _('Only one device can be paired to this receiver.')
pairings = receiver.remaining_pairings(False)
if ( pairings is not None and pairings >= 0 ) :
paired_text += '\n<small>%s</small>' % _('This receiver has %d pairing(s) remaining.') % pairings
panel._count.set_markup(paired_text)