improved support for some Nano receivers
This commit is contained in:
parent
790fc7c04b
commit
c3b73964d5
|
@ -67,9 +67,10 @@ class DeviceUnreachable(_KwException):
|
|||
#
|
||||
|
||||
# vendor_id, product_id, usb interface number, hid driver
|
||||
DEVICE_UNIFYING_RECEIVER = (0x046d, 0xc52b, 2, 'logitech-djreceiver')
|
||||
DEVICE_UNIFYING_RECEIVER_2 = (0x046d, 0xc532, 2, 'logitech-djreceiver')
|
||||
DEVICE_NANO_RECEIVER = (0x046d, 0xc526, 1, 'hid-generic')
|
||||
DEVICE_UNIFYING_RECEIVER = (0x046d, 0xc52b, 2, 'logitech-djreceiver')
|
||||
DEVICE_UNIFYING_RECEIVER_2 = (0x046d, 0xc532, 2, 'logitech-djreceiver')
|
||||
DEVICE_NANO_RECEIVER = (0x046d, 0xc52f, 1, 'hid-generic')
|
||||
DEVICE_VXNANO_RECEIVER = (0x046d, 0xc526, 1, 'hid-generic')
|
||||
|
||||
|
||||
def receivers():
|
||||
|
@ -78,8 +79,10 @@ def receivers():
|
|||
yield d
|
||||
for d in _hid.enumerate(*DEVICE_UNIFYING_RECEIVER_2):
|
||||
yield d
|
||||
#for d in _hid.enumerate(*DEVICE_NANO_RECEIVER):
|
||||
# yield d
|
||||
for d in _hid.enumerate(*DEVICE_NANO_RECEIVER):
|
||||
yield d
|
||||
for d in _hid.enumerate(*DEVICE_VXNANO_RECEIVER):
|
||||
yield d
|
||||
|
||||
|
||||
def notify_on_receivers(callback):
|
||||
|
@ -87,7 +90,8 @@ def notify_on_receivers(callback):
|
|||
_hid.monitor_async(callback,
|
||||
DEVICE_UNIFYING_RECEIVER,
|
||||
DEVICE_UNIFYING_RECEIVER_2,
|
||||
# DEVICE_NANO_RECEIVER,
|
||||
DEVICE_NANO_RECEIVER,
|
||||
DEVICE_VXNANO_RECEIVER,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -51,11 +51,11 @@ def check_features(device, already_known):
|
|||
#
|
||||
|
||||
_DeviceDescriptor = namedtuple('_DeviceDescriptor',
|
||||
['name', 'kind', 'codename', 'registers', 'settings'])
|
||||
['name', 'kind', 'product_id', 'codename', 'registers', 'settings'])
|
||||
|
||||
DEVICES = {}
|
||||
|
||||
def _D(name, codename=None, kind=None, registers=None, settings=None):
|
||||
def _D(name, codename=None, kind=None, product_id=None, registers=None, settings=None):
|
||||
if kind is None:
|
||||
kind = (_hidpp10.DEVICE_KIND.mouse if 'Mouse' in name
|
||||
else _hidpp10.DEVICE_KIND.keyboard if 'Keyboard' in name
|
||||
|
@ -68,7 +68,9 @@ def _D(name, codename=None, kind=None, registers=None, settings=None):
|
|||
codename = name.split(' ')[-1]
|
||||
assert codename is not None
|
||||
|
||||
DEVICES[codename] = _DeviceDescriptor(name, kind, codename, registers, settings)
|
||||
DEVICES[codename] = _DeviceDescriptor(name, kind, product_id, codename, registers, settings)
|
||||
if product_id:
|
||||
DEVICES[product_id] = DEVICES[codename]
|
||||
|
||||
#
|
||||
#
|
||||
|
@ -133,6 +135,13 @@ _D('Wireless Illuminated Keyboard K800',
|
|||
|
||||
# Mice
|
||||
|
||||
# _D('VX Nano Cordless Laser Mouse', product_id='c526', codename='VXNano',
|
||||
# registers={'battery_charge': 0x0D},
|
||||
# settings=[
|
||||
# _register_smooth_scroll(0x01, true_value=0x40, mask=0x40),
|
||||
# ],
|
||||
# )
|
||||
|
||||
_D('Wireless Mouse M315')
|
||||
_D('Wireless Mouse M325')
|
||||
_D('Wireless Mouse M505')
|
||||
|
@ -154,7 +163,7 @@ _D('Marathon Mouse M705',
|
|||
)
|
||||
_D('Zone Touch Mouse T400')
|
||||
_D('Touch Mouse T620')
|
||||
_D('Logitech Cube', kind='mouse')
|
||||
_D('Logitech Cube', kind=_hidpp10.DEVICE_KIND.mouse)
|
||||
_D('Anywhere Mouse MX', codename='Anywhere MX',
|
||||
# registers={'battery_charge': 0x0D},
|
||||
# settings=[
|
||||
|
|
|
@ -153,7 +153,7 @@ def get_serial(device):
|
|||
|
||||
|
||||
def get_firmware(device):
|
||||
firmware = []
|
||||
firmware = [None, None]
|
||||
|
||||
reply = device.request(0x81F1, 0x01)
|
||||
if reply:
|
||||
|
@ -163,23 +163,17 @@ def get_firmware(device):
|
|||
if reply:
|
||||
fw_version += '.B' + _strhex(reply[1:3])
|
||||
fw = _FirmwareInfo(FIRMWARE_KIND.Firmware, '', fw_version, None)
|
||||
firmware.append(fw)
|
||||
|
||||
if device.kind is None and device.max_devices == 1:
|
||||
# Nano receiver
|
||||
return firmware
|
||||
if device.kind is not None and not device._unifying:
|
||||
# Nano device
|
||||
return firmware
|
||||
firmware[0] = fw
|
||||
|
||||
reply = device.request(0x81F1, 0x04)
|
||||
if reply:
|
||||
bl_version = _strhex(reply[1:3])
|
||||
bl_version = '%s.%s' % (bl_version[0:2], bl_version[2:4])
|
||||
bl = _FirmwareInfo(FIRMWARE_KIND.Bootloader, '', bl_version, None)
|
||||
firmware.append(bl)
|
||||
firmware[1] = bl
|
||||
|
||||
return tuple(firmware)
|
||||
if any(firmware):
|
||||
return tuple(f for f in firmware if f)
|
||||
|
||||
|
||||
def get_notification_flags(device):
|
||||
|
|
|
@ -32,19 +32,40 @@ class PairedDevice(object):
|
|||
assert number > 0 and number <= receiver.max_devices
|
||||
self.number = number
|
||||
|
||||
self._unifying = receiver.max_devices > 1
|
||||
self._protocol = None if self._unifying else 1.0
|
||||
self._wpid = None
|
||||
self._power_switch = None
|
||||
self._polling_rate = None if self._unifying else 0
|
||||
self.wpid = None
|
||||
self.polling_rate = 0
|
||||
|
||||
self._kind = None
|
||||
self._codename = None
|
||||
self._name = None
|
||||
self._kind = None
|
||||
self._serial = None if self._unifying else receiver.serial
|
||||
|
||||
self._protocol = None if self.receiver.unifying_supported else 1.0
|
||||
self._power_switch = None if self.receiver.unifying_supported else '(unknown)'
|
||||
self._serial = None if self.receiver.unifying_supported else self.receiver.serial
|
||||
|
||||
if self.receiver.unifying_supported:
|
||||
pair_info = self.receiver.request(0x83B5, 0x20 + self.number - 1)
|
||||
if pair_info:
|
||||
self.wpid = _strhex(pair_info[3:5])
|
||||
kind = ord(pair_info[7:8]) & 0x0F
|
||||
self._kind = _hidpp10.DEVICE_KIND[kind]
|
||||
self.polling_rate = ord(pair_info[2:3])
|
||||
# else:
|
||||
# # guesswork...
|
||||
# descriptor = _descriptors.DEVICES.get(self.receiver.product_id)
|
||||
# if descriptor:
|
||||
# self._kind = descriptor.kind
|
||||
# self._codename = descriptor.codename
|
||||
# self._name = descriptor.name
|
||||
|
||||
# device_info = self.receiver.request(0x83B5, 0x04)
|
||||
# if device_info:
|
||||
# self.wpid = _strhex(device_info[3:5])
|
||||
|
||||
self._firmware = None
|
||||
self._keys = None
|
||||
|
||||
self.features = _hidpp20.FeaturesArray(self) if self._unifying else None
|
||||
self.features = _hidpp20.FeaturesArray(self) if self.receiver.unifying_supported else None
|
||||
self._registers = None
|
||||
self._settings = None
|
||||
|
||||
|
@ -55,66 +76,36 @@ class PairedDevice(object):
|
|||
# _log.debug("device %d protocol %s", self.number, self._protocol)
|
||||
return self._protocol or 0
|
||||
|
||||
@property
|
||||
def wpid(self):
|
||||
if self._wpid is None:
|
||||
if self._unifying:
|
||||
pair_info = self.receiver.request(0x83B5, 0x20 + self.number - 1)
|
||||
if pair_info:
|
||||
self._wpid = _strhex(pair_info[3:5])
|
||||
if self._kind is None:
|
||||
kind = ord(pair_info[7:8]) & 0x0F
|
||||
self._kind = _hidpp10.DEVICE_KIND[kind]
|
||||
if self._polling_rate is None:
|
||||
self._polling_rate = ord(pair_info[2:3])
|
||||
else:
|
||||
# guesswork...
|
||||
device_info = self.receiver.request(0x83B5, 0x04)
|
||||
self.wpid = _strhex(device_info[3:5])
|
||||
return self._wpid
|
||||
|
||||
@property
|
||||
def polling_rate(self):
|
||||
if self._polling_rate is None:
|
||||
if self._unifying:
|
||||
self.wpid, 0
|
||||
else:
|
||||
self._polling_rate = 0
|
||||
return self._polling_rate
|
||||
|
||||
@property
|
||||
def power_switch_location(self):
|
||||
if self._power_switch is None:
|
||||
if self._unifying:
|
||||
ps = self.receiver.request(0x83B5, 0x30 + self.number - 1)
|
||||
if ps:
|
||||
ps = ord(ps[9:10]) & 0x0F
|
||||
self._power_switch = _hidpp10.POWER_SWITCH_LOCATION[ps]
|
||||
ps = self.receiver.request(0x83B5, 0x30 + self.number - 1)
|
||||
if ps:
|
||||
ps = ord(ps[9:10]) & 0x0F
|
||||
self._power_switch = _hidpp10.POWER_SWITCH_LOCATION[ps]
|
||||
return self._power_switch
|
||||
|
||||
@property
|
||||
def codename(self):
|
||||
if self._codename is None:
|
||||
if self._unifying:
|
||||
codename = self.receiver.request(0x83B5, 0x40 + self.number - 1)
|
||||
if codename:
|
||||
self._codename = codename[2:].rstrip(b'\x00').decode('utf-8')
|
||||
# _log.debug("device %d codename %s", self.number, self._codename)
|
||||
codename = self.receiver.request(0x83B5, 0x40 + self.number - 1)
|
||||
if codename:
|
||||
self._codename = codename[2:].rstrip(b'\x00').decode('utf-8')
|
||||
# _log.debug("device %d codename %s", self.number, self._codename)
|
||||
return self._codename
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
if self._name is None:
|
||||
if self._unifying:
|
||||
if self.codename in _descriptors.DEVICES:
|
||||
self._name, self._kind = _descriptors.DEVICES[self._codename][:2]
|
||||
elif self.protocol >= 2.0:
|
||||
self._name = _hidpp20.get_name(self)
|
||||
if self.codename in _descriptors.DEVICES:
|
||||
self._name, self._kind = _descriptors.DEVICES[self._codename][:2]
|
||||
elif self.protocol >= 2.0:
|
||||
self._name = _hidpp20.get_name(self)
|
||||
return self._name or self.codename or '?'
|
||||
|
||||
@property
|
||||
def kind(self):
|
||||
if self._kind is None and self._unifying:
|
||||
if self._kind is None and self.receiver.unifying_supported:
|
||||
pair_info = self.receiver.request(0x83B5, 0x20 + self.number - 1)
|
||||
if pair_info:
|
||||
kind = ord(pair_info[7:8]) & 0x0F
|
||||
|
@ -146,7 +137,7 @@ class PairedDevice(object):
|
|||
@property
|
||||
def keys(self):
|
||||
if self._keys is None:
|
||||
if self._unifying:
|
||||
if self.protocol >= 2.0:
|
||||
self._keys = _hidpp20.get_keys(self) or ()
|
||||
return self._keys
|
||||
|
||||
|
@ -201,7 +192,7 @@ class PairedDevice(object):
|
|||
return _base.request(self.receiver.handle, self.number, request_id, *params)
|
||||
|
||||
def feature_request(self, feature, function=0x00, *params):
|
||||
if self._unifying:
|
||||
if self.protocol >= 2.0:
|
||||
return _hidpp20.feature_request(self, feature, function, *params)
|
||||
|
||||
def ping(self):
|
||||
|
@ -236,15 +227,18 @@ class Receiver(object):
|
|||
number = 0xFF
|
||||
kind = None
|
||||
|
||||
def __init__(self, handle, path=None):
|
||||
def __init__(self, handle, device_info):
|
||||
assert handle
|
||||
self.handle = handle
|
||||
assert path
|
||||
self.path = path
|
||||
assert device_info
|
||||
self.path = device_info.path
|
||||
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
|
||||
serial_reply = self.request(0x83B5, 0x03)
|
||||
assert serial_reply
|
||||
self._serial = _strhex(serial_reply[1:5])
|
||||
self.serial = _strhex(serial_reply[1:5])
|
||||
self.max_devices = ord(serial_reply[6:7])
|
||||
|
||||
if self.max_devices == 1:
|
||||
|
@ -255,6 +249,9 @@ class Receiver(object):
|
|||
raise Exception("unknown receiver type")
|
||||
self._str = '<%s(%s,%s%s)>' % (self.name.replace(' ', ''), self.path, '' if type(self.handle) == int else 'T', self.handle)
|
||||
|
||||
old_equad_reply = self.request(0x83B5, 0x04)
|
||||
self.unifying_supported = old_equad_reply is None
|
||||
|
||||
self._firmware = None
|
||||
self._devices = {}
|
||||
|
||||
|
@ -266,13 +263,6 @@ class Receiver(object):
|
|||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
@property
|
||||
def serial(self):
|
||||
assert self._serial
|
||||
# if self._serial is None and self.handle:
|
||||
# self._serial = _hidpp10.get_serial(self)
|
||||
return self._serial
|
||||
|
||||
@property
|
||||
def firmware(self):
|
||||
if self._firmware is None and self.handle:
|
||||
|
@ -308,21 +298,13 @@ class Receiver(object):
|
|||
def register_new_device(self, number):
|
||||
if self._devices.get(number) is not None:
|
||||
raise IndexError("%s: device number %d already registered" % (self, number))
|
||||
|
||||
dev = PairedDevice(self, number)
|
||||
# create a device object, but only use it if the receiver knows about it
|
||||
|
||||
# Nano receiver
|
||||
if self.max_devices == 1 and number == 1:
|
||||
# the Nano receiver does not provide the wpid
|
||||
_log.info("%s: found Nano device %d (%s)", self, number, dev.serial)
|
||||
# dev._wpid = self.serial + ':1'
|
||||
self._devices[number] = dev
|
||||
return dev
|
||||
|
||||
if dev.wpid:
|
||||
_log.info("%s: found Unifying device %d (%s)", self, number, dev.wpid)
|
||||
_log.info("%s: found device %d (%s)", self, number, dev.wpid)
|
||||
self._devices[number] = dev
|
||||
return dev
|
||||
|
||||
self._devices[number] = None
|
||||
|
||||
def set_lock(self, lock_closed=True, device=0, timeout=0):
|
||||
|
@ -403,18 +385,18 @@ class Receiver(object):
|
|||
__bool__ = __nonzero__ = lambda self: self.handle is not None
|
||||
|
||||
@classmethod
|
||||
def open(self, path):
|
||||
def open(self, device_info):
|
||||
"""Opens a Logitech Receiver found attached to the machine, by Linux device path.
|
||||
|
||||
:returns: An open file handle for the found receiver, or ``None``.
|
||||
"""
|
||||
try:
|
||||
handle = _base.open_path(path)
|
||||
handle = _base.open_path(device_info.path)
|
||||
if handle:
|
||||
return Receiver(handle, path)
|
||||
return Receiver(handle, device_info)
|
||||
except OSError as e:
|
||||
_log.exception("open %s", path)
|
||||
_log.exception("open %s", device_info)
|
||||
if e.errno == _errno.EACCES:
|
||||
raise
|
||||
except:
|
||||
_log.exception("open %s", path)
|
||||
_log.exception("open %s", device_info)
|
||||
|
|
|
@ -273,6 +273,7 @@ class DeviceStatus(dict):
|
|||
_log.warn("%s: unrecognized %s", self._device, n)
|
||||
|
||||
def _process_hidpp10_notification(self, n):
|
||||
# unpair notification
|
||||
if n.sub_id == 0x40:
|
||||
if n.address == 0x02:
|
||||
# device un-paired
|
||||
|
@ -283,44 +284,33 @@ class DeviceStatus(dict):
|
|||
_log.warn("%s: disconnection with unknown type %02X: %s", self._device, n.address, n)
|
||||
return True
|
||||
|
||||
# wireless link notification
|
||||
if n.sub_id == 0x41:
|
||||
if n.address == 0x04: # unifying protocol
|
||||
# wpid = _strhex(n.data[4:5] + n.data[3:4])
|
||||
# assert wpid == device.wpid
|
||||
|
||||
protocol_name = ('unifying (eQuad DJ)' if n.address == 0x04
|
||||
else 'eQuad' if n.address == 0x03
|
||||
else None)
|
||||
if protocol_name:
|
||||
flags = ord(n.data[:1]) & 0xF0
|
||||
link_encrypyed = bool(flags & 0x20)
|
||||
link_established = not (flags & 0x40)
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
sw_present = bool(flags & 0x10)
|
||||
has_payload = bool(flags & 0x80)
|
||||
_log.debug("%s: unifying connection notification: software=%s, encrypted=%s, link=%s, payload=%s",
|
||||
self._device, sw_present, link_encrypyed, link_established, has_payload)
|
||||
self[ENCRYPTED] = link_encrypyed
|
||||
self._changed(link_established)
|
||||
|
||||
elif n.address == 0x03: # eQuad protocol
|
||||
# Nano devices might not have been initialized fully
|
||||
if self._device._kind is None:
|
||||
kind = ord(n.data[:1]) & 0x0F
|
||||
self._device._kind = _hidpp10.DEVICE_KIND[kind]
|
||||
if self._device._wpid is None:
|
||||
self._device._wpid = _strhex(n.data[2:3] + n.data[1:2])
|
||||
|
||||
flags = ord(n.data[:1]) & 0xF0
|
||||
link_encrypyed = bool(flags & 0x20)
|
||||
link_established = not (flags & 0x40)
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
sw_present = bool(flags & 0x10)
|
||||
has_payload = bool(flags & 0x80)
|
||||
_log.debug("%s: eQuad connection notification: software=%s, encrypted=%s, link=%s, payload=%s",
|
||||
self._device, sw_present, link_encrypyed, link_established, has_payload)
|
||||
_log.debug("%s: %s connection notification: software=%s, encrypted=%s, link=%s, payload=%s",
|
||||
self._device, protocol_name, sw_present, link_encrypyed, link_established, has_payload)
|
||||
self[ENCRYPTED] = link_encrypyed
|
||||
self._changed(link_established)
|
||||
|
||||
if protocol_name == 'eQuad':
|
||||
# some Nano devices might not have been initialized fully
|
||||
if self._device._kind is None:
|
||||
kind = ord(n.data[:1]) & 0x0F
|
||||
self._device._kind = _hidpp10.DEVICE_KIND[kind]
|
||||
assert self._device.wpid == _strhex(n.data[2:3] + n.data[1:2])
|
||||
else:
|
||||
_log.warn("%s: connection notification with unknown protocol %02X: %s", self._device.number, n.address, n)
|
||||
|
||||
# if the device just came online, read the battery charge
|
||||
if self._active: # and BATTERY_LEVEL not in self:
|
||||
self.read_battery()
|
||||
|
||||
|
@ -332,6 +322,7 @@ class DeviceStatus(dict):
|
|||
# if n.address == 0x03, it's an actual input event
|
||||
return True
|
||||
|
||||
# power notification
|
||||
if n.sub_id == 0x4B:
|
||||
if n.address == 0x01:
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
|
|
|
@ -36,7 +36,7 @@ def _receiver():
|
|||
from logitech.unifying_receiver.base import receivers
|
||||
for dev_info in receivers():
|
||||
try:
|
||||
r = Receiver.open(dev_info.path)
|
||||
r = Receiver.open(dev_info)
|
||||
if r:
|
||||
return r
|
||||
except Exception as e:
|
||||
|
@ -99,7 +99,7 @@ def _print_receiver(receiver, verbose=False):
|
|||
else:
|
||||
print (" All notifications disabled")
|
||||
|
||||
if paired_count > 0:
|
||||
if receiver.unifying_supported:
|
||||
activity = receiver.request(0x83B3)
|
||||
if activity:
|
||||
activity = [(d, ord(activity[d - 1:d])) for d in range(1, receiver.max_devices)]
|
||||
|
|
|
@ -50,12 +50,12 @@ def _run(args):
|
|||
listeners = {}
|
||||
from solaar.listener import ReceiverListener
|
||||
|
||||
def handle_receivers_events(action, device):
|
||||
def handle_receivers_events(action, device_info):
|
||||
assert action is not None
|
||||
assert device is not None
|
||||
assert device_info is not None
|
||||
|
||||
# whatever the action, stop any previous receivers at this path
|
||||
l = listeners.pop(device.path, None)
|
||||
l = listeners.pop(device_info.path, None)
|
||||
if l is not None:
|
||||
assert isinstance(l, ReceiverListener)
|
||||
l.stop()
|
||||
|
@ -63,18 +63,17 @@ def _run(args):
|
|||
if action == 'add':
|
||||
# a new receiver device was detected
|
||||
try:
|
||||
l = ReceiverListener.open(device.path, status_changed)
|
||||
l = ReceiverListener.open(device_info, status_changed)
|
||||
if l is not None:
|
||||
listeners[device.path] = l
|
||||
listeners[device_info.path] = l
|
||||
except OSError:
|
||||
# permission error, blacklist this path for now
|
||||
listeners.pop(device.path, None)
|
||||
listeners.pop(device_info.path, None)
|
||||
GLib.idle_add(ui.error_dialog, 'Permissions error',
|
||||
'Found a Logitech Unifying Receiver device,\n'
|
||||
'but did not have permission to open it.\n'
|
||||
'Found a Logitech Receiver, but did not have permission to open it.\n'
|
||||
'\n'
|
||||
'If you\'ve just installed Solaar, try removing\n'
|
||||
'the receiver and plugging it back in.')
|
||||
'If you\'ve just installed Solaar, try removing the receiver\n'
|
||||
'and plugging it back in.')
|
||||
|
||||
# elif action == 'remove':
|
||||
# # we'll be receiving remove events for any hidraw devices,
|
||||
|
|
|
@ -161,12 +161,12 @@ class ReceiverListener(_listener.EventsListener):
|
|||
__unicode__ = __str__
|
||||
|
||||
@classmethod
|
||||
def open(self, path, status_changed_callback):
|
||||
def open(self, device_info, status_changed_callback):
|
||||
assert status_changed_callback
|
||||
receiver = Receiver.open(path)
|
||||
receiver = Receiver.open(device_info)
|
||||
if receiver:
|
||||
rl = ReceiverListener(receiver, status_changed_callback)
|
||||
rl.start()
|
||||
return rl
|
||||
else:
|
||||
_log.warn("failed to open %s", path)
|
||||
_log.warn("failed to open %s", device_info)
|
||||
|
|
|
@ -70,16 +70,17 @@ def _make_receiver_box(receiver):
|
|||
device = f._device
|
||||
if True: # f._info_label.get_visible() and '\n' not in f._info_label.get_text():
|
||||
items = [('Path', device.path), ('Serial', device.serial)] + \
|
||||
[(fw.kind, fw.version) for fw in device.firmware]
|
||||
list((fw.kind, fw.version) for fw in device.firmware) + \
|
||||
[None]
|
||||
|
||||
notification_flags = _hidpp10.get_notification_flags(device)
|
||||
if notification_flags:
|
||||
notification_flags = _hidpp10.NOTIFICATION_FLAG.flag_names(notification_flags)
|
||||
else:
|
||||
notification_flags = ('(none)',)
|
||||
items.append(('Notifications', ('\n%16s' % ' ').join(notification_flags)))
|
||||
items[-1] = ('Notifications', ('\n%16s' % ' ').join(notification_flags))
|
||||
|
||||
f._info_label.set_markup('<small><tt>%s</tt></small>' % '\n'.join('%-14s: %s' % item for item in items))
|
||||
f._info_label.set_markup('<small><tt>%s</tt></small>' % '\n'.join('%-14s: %s' % i for i in items if i))
|
||||
f._info_label.set_sensitive(True)
|
||||
|
||||
def _toggle_info_label(action, f):
|
||||
|
@ -94,7 +95,7 @@ def _make_receiver_box(receiver):
|
|||
toggle_info_action = _action.make_toggle('dialog-information', 'Details', _toggle_info_label, frame)
|
||||
toolbar.insert(toggle_info_action.create_tool_item(), 0)
|
||||
pair_action = _action.pair(frame)
|
||||
if receiver.max_devices == 1:
|
||||
if not receiver.unifying_supported:
|
||||
pair_action.set_sensitive(False)
|
||||
pair_action.set_tooltip('Pairing not supported by this receiver')
|
||||
toolbar.insert(pair_action.create_tool_item(), -1)
|
||||
|
@ -186,16 +187,14 @@ def _make_device_box(index):
|
|||
device = f._device
|
||||
assert device
|
||||
|
||||
items = [None] * 8
|
||||
hid = device.protocol
|
||||
items[0] = ('Protocol', 'HID++ %1.1f' % hid if hid else 'unknown')
|
||||
items[1] = ('Polling rate', '%d ms' % device.polling_rate) if device.polling_rate else None
|
||||
items[2] = ('Wireless PID', device.wpid)
|
||||
items[3] = ('Serial', device.serial)
|
||||
firmware = device.firmware
|
||||
if firmware:
|
||||
firmware = [(fw.kind, (fw.name + ' ' + fw.version).strip()) for fw in firmware]
|
||||
items[4:4+len(firmware)] = firmware
|
||||
items = [
|
||||
('Protocol', 'HID++ %1.1f' % hid if hid else 'unknown'),
|
||||
('Polling rate', '%d ms' % device.polling_rate) if device.polling_rate else None,
|
||||
('Wireless PID', device.wpid),
|
||||
('Serial', device.serial) ] + \
|
||||
list((fw.kind, (fw.name + ' ' + fw.version).strip()) for fw in device.firmware) + \
|
||||
[None]
|
||||
|
||||
if device.status:
|
||||
notification_flags = _hidpp10.get_notification_flags(device)
|
||||
|
@ -204,8 +203,6 @@ def _make_device_box(index):
|
|||
else:
|
||||
notification_flags = ('(none)',)
|
||||
items[-1] = ('Notifications', ('\n%16s' % ' ').join(notification_flags))
|
||||
else:
|
||||
items[-1] = None
|
||||
|
||||
frame._info_label.set_markup('<small><tt>%s</tt></small>' % '\n'.join('%-14s: %s' % i for i in items if i))
|
||||
frame._info_label.set_sensitive(True)
|
||||
|
@ -422,7 +419,7 @@ def _update_device_box(frame, dev):
|
|||
for i in frame._toolbar.get_children():
|
||||
i.set_active(False)
|
||||
|
||||
if dev.receiver.max_devices == 1:
|
||||
if not dev.receiver.unifying_supported:
|
||||
unpair_button = frame.get_child().get_children()[-1]
|
||||
unpair_button.set_sensitive(False)
|
||||
unpair_button.set_tooltip_text('Unpairing not supported by this device')
|
||||
|
|
|
@ -8,8 +8,13 @@
|
|||
|
||||
# HIDAPI/hidraw for Logitech Unifying Receiver
|
||||
ACTION=="add", KERNEL=="hidraw*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52b", GROUP="plugdev", MODE="0660"
|
||||
ACTION=="add", KERNEL=="hidraw*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c532", GROUP="plugdev", MODE="0660"
|
||||
|
||||
# HIDAPI/hidraw for Logitech Nano Receiver
|
||||
# HIDAPI/hidraw for Logitech Nano Receiver, "Unifying ready"
|
||||
ACTION=="add", KERNEL=="hidraw*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52f", GROUP="plugdev", MODE="0660"
|
||||
|
||||
# HIDAPI/hidraw for VX Nano receiver
|
||||
#ACTION=="add", KERNEL=="hidraw*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c51a", GROUP="plugdev", MODE="0660"
|
||||
#ACTION=="add", KERNEL=="hidraw*", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c526", GROUP="plugdev", MODE="0660"
|
||||
|
||||
# vim: ft=udevrules
|
||||
|
|
Loading…
Reference in New Issue