receiver: add support for EX100 keyboard/mouse and receiver (046d:c517)
docs: add EX100 keyboard/mouse combo device: add EX100 keyboard and mouse hidpp10: fix notification parsing, add device features flags, fix documentation links notifications: fix wpid processing for 27 MHz protocol cli: add display of device features flags for HID++ 1.0 devices
This commit is contained in:
parent
4dfa55c96c
commit
e436b1bd1d
|
@ -49,7 +49,7 @@ a tuple of known feature settings (from lib/logitech/settings_templates.py).
|
||||||
|
|
||||||
| USB ID | Kind | Max Paired Devices |
|
| USB ID | Kind | Max Paired Devices |
|
||||||
------------|------------|--------------------|
|
------------|------------|--------------------|
|
||||||
| 046d:c517 | Nano | 1 |
|
| 046d:c517 | 27Mhz old | 2-4? |
|
||||||
| 046d:c518 | Nano | 1 |
|
| 046d:c518 | Nano | 1 |
|
||||||
| 046d:c51a | Nano | 1 |
|
| 046d:c51a | Nano | 1 |
|
||||||
| 046d:c51b | Nano | 1 |
|
| 046d:c51b | Nano | 1 |
|
||||||
|
@ -68,7 +68,8 @@ a tuple of known feature settings (from lib/logitech/settings_templates.py).
|
||||||
| 064d:c53f | Lightspeed | 1 |
|
| 064d:c53f | Lightspeed | 1 |
|
||||||
| 17ef:6042 | Nano | 1 |
|
| 17ef:6042 | Nano | 1 |
|
||||||
|
|
||||||
|
* The receiver with usb Id 046d:c517 is old, 27 MHz receiver, supporting only
|
||||||
|
subset of HID++ 1.0 protocol. Only hardware pairing supported.
|
||||||
|
|
||||||
### Keyboards (Unifying):
|
### Keyboards (Unifying):
|
||||||
|
|
||||||
|
@ -215,7 +216,10 @@ setting is useful only to disable smooth scrolling.
|
||||||
| MK550 | | | | |
|
| MK550 | | | | |
|
||||||
| MK700 | 2008 | 1.0 | yes | FN swap, reprog keys |
|
| MK700 | 2008 | 1.0 | yes | FN swap, reprog keys |
|
||||||
| MK710 | | 1.0 | yes | FN swap, reprog keys |
|
| MK710 | | 1.0 | yes | FN swap, reprog keys |
|
||||||
|
| EX100 keyboard | 6500 | 1.0 | yes | |
|
||||||
|
| EX100 mouse | 3f00 | 1.0 | yes | |
|
||||||
|
|
||||||
|
* The EX100 is old, pre-unifying set, supporting only part of HID++ 1.0 features
|
||||||
|
|
||||||
[solaar]: https://github.com/pwr-Solaar/Solaar
|
[solaar]: https://github.com/pwr-Solaar/Solaar
|
||||||
[logitech]: https://www.logitech.com
|
[logitech]: https://www.logitech.com
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
./scan-registers.sh ff /dev/hidraw4
|
||||||
|
# Old notification flags: 000100
|
||||||
|
>> ( 0.035) [10 FF 8100 000100] '\x10\xff\x81\x00\x00\x01\x00'
|
||||||
|
<< ( 0.015) [10 FF 8101 000000] '\x10\xff\x81\x01\x00\x00\x00'
|
||||||
|
>> ( 0.020) [10 FF 8101 000200] '\x10\xff\x81\x01\x00\x02\x00'
|
||||||
|
<< ( 0.030) [10 FF 8102 000000] '\x10\xff\x81\x02\x00\x00\x00'
|
||||||
|
>> ( 0.036) [10 FF 8102 000200] '\x10\xff\x81\x02\x00\x02\x00'
|
||||||
|
--
|
||||||
|
<< ( 0.142) [10 FF 8109 000000] '\x10\xff\x81\t\x00\x00\x00'
|
||||||
|
>> ( 0.148) [10 FF 8109 010000] '\x10\xff\x81\t\x01\x00\x00'
|
||||||
|
--
|
||||||
|
<< ( 1.790) [10 FF 8170 000000] '\x10\xff\x81p\x00\x00\x00'
|
||||||
|
>> ( 1.796) [10 FF 8170 012100] '\x10\xff\x81p\x01!\x00'
|
||||||
|
<< ( 1.806) [10 FF 8171 000000] '\x10\xff\x81q\x00\x00\x00'
|
||||||
|
>> ( 1.812) [10 FF 8171 011200] '\x10\xff\x81q\x01\x12\x00'
|
||||||
|
--
|
||||||
|
<< ( 1.838) [10 FF 8173 000000] '\x10\xff\x81s\x00\x00\x00'
|
||||||
|
>> ( 1.844) [10 FF 8173 643F00] '\x10\xff\x81sd?\x00'
|
||||||
|
--
|
||||||
|
<< ( 2.046) [10 FF 8180 000000] '\x10\xff\x81\x80\x00\x00\x00'
|
||||||
|
>> ( 2.052) [10 FF 8180 030000] '\x10\xff\x81\x80\x03\x00\x00'
|
||||||
|
--
|
||||||
|
<< ( 3.326) [10 FF 81D0 000000] '\x10\xff\x81\xd0\x00\x00\x00'
|
||||||
|
>> ( 3.332) [10 FF 81D0 000000] '\x10\xff\x81\xd0\x00\x00\x00'
|
||||||
|
|
||||||
|
devices
|
||||||
|
01 mouse
|
||||||
|
Red button pressed
|
||||||
|
>> ( 1676.106) [10 01 0810 000000] '\x10\x01\x08\x10\x00\x00\x00'
|
||||||
|
>> ( 1676.114) [10 01 4600 000021] '\x10\x01F\x00\x00\x00!'
|
||||||
|
>> ( 1676.122) [10 FF 4600 211100] '\x10\xffF\x00!\x11\x00'
|
||||||
|
|
||||||
|
Power lewel?
|
||||||
|
?? Input: 10 01 81 07 00 00 00
|
||||||
|
<< ( 1739.032) [10 01 8107 000000] '\x10\x01\x81\x07\x00\x00\x00'
|
||||||
|
>> ( 1739.040) [10 01 8107 030000] '\x10\x01\x81\x07\x03\x00\x00'
|
||||||
|
[10 01 8107 070000] '\x10\x01\x81\x07\x07\x00\x00'
|
||||||
|
|
||||||
|
power change
|
||||||
|
>> ( 2441.563) [10 01 0703 000000] '\x10\x01\x07\x03\x00\x00\x00'
|
||||||
|
>> ( 100.159) [10 01 0707 000000] '\x10\x01\x07\x07\x00\x00\x00'
|
||||||
|
|
||||||
|
enable power event
|
||||||
|
<< ( 59.190) [10 01 8000 100000] '\x10\x01\x80\x00\x10\x00\x00'
|
||||||
|
>> ( 59.193) [10 01 8000 000000] '\x10\x01\x80\x00\x00\x00\x00'
|
||||||
|
|
||||||
|
|
||||||
|
03 keyboard
|
||||||
|
|
||||||
|
Power level?
|
||||||
|
?? Input: 10 03 81 07 00 00 00
|
||||||
|
<< ( 1777.961) [10 03 8107 000000] '\x10\x03\x81\x07\x00\x00\x00'
|
||||||
|
>> ( 1777.967) [10 03 8107 070000] '\x10\x03\x81\x07\x07\x00\x00'
|
||||||
|
|
||||||
|
power on
|
||||||
|
>> ( 1571.805) [10 03 0810 000000] '\x10\x03\x08\x10\x00\x00\x00'
|
||||||
|
>> ( 1574.709) [10 03 0800 000000] '\x10\x03\x08\x00\x00\x00\x00'
|
||||||
|
|
||||||
|
red button pressed
|
||||||
|
>> ( 1619.043) [10 03 0810 000000] '\x10\x03\x08\x10\x00\x00\x00'
|
||||||
|
>> ( 1619.051) [10 03 4600 000011] '\x10\x03F\x00\x00\x00\x11'
|
||||||
|
>> ( 1619.059) [10 FF 4600 221100] '\x10\xffF\x00"\x11\x00'
|
||||||
|
>> ( 1621.747) [10 03 0800 000000] '\x10\x03\x08\x00\x00\x00\x00'
|
||||||
|
|
||||||
|
Fn pressed
|
||||||
|
>> ( 1651.715) [10 03 032C 100000] '\x10\x03\x03,\x10\x00\x00'
|
||||||
|
>> ( 1652.170) [10 03 0300 000000] '\x10\x03\x03\x00\x00\x00\x00'
|
||||||
|
|
||||||
|
|
||||||
|
$ bin/solaar probe
|
||||||
|
Nano Receiver
|
||||||
|
Device path : /dev/hidraw3
|
||||||
|
USB id : 046d:c517
|
||||||
|
Serial : None
|
||||||
|
Has 2 paired device(s) out of a maximum of 6.
|
||||||
|
Notifications: wireless (0x000100)
|
||||||
|
Register Dump
|
||||||
|
Notification Register 0x00: 0x000100
|
||||||
|
Connection State 0x02: 0x000200
|
||||||
|
Device Activity 0xb3: None
|
||||||
|
Pairing Register 0xb5 0x00: None
|
||||||
|
Pairing Register 0xb5 0x10: None
|
||||||
|
Pairing Register 0xb5 0x20: None
|
||||||
|
Pairing Register 0xb5 0x30: None
|
||||||
|
Pairing Name 0xb5 0x40: None
|
||||||
|
Pairing Register 0xb5 0x01: None
|
||||||
|
Pairing Register 0xb5 0x11: None
|
||||||
|
Pairing Register 0xb5 0x21: None
|
||||||
|
Pairing Register 0xb5 0x31: None
|
||||||
|
Pairing Name 0xb5 0x41: None
|
||||||
|
Pairing Register 0xb5 0x02: None
|
||||||
|
Pairing Register 0xb5 0x12: None
|
||||||
|
Pairing Register 0xb5 0x22: None
|
||||||
|
Pairing Register 0xb5 0x32: None
|
||||||
|
Pairing Name 0xb5 0x42: None
|
||||||
|
Pairing Register 0xb5 0x03: None
|
||||||
|
Pairing Register 0xb5 0x13: None
|
||||||
|
Pairing Register 0xb5 0x23: None
|
||||||
|
Pairing Register 0xb5 0x33: None
|
||||||
|
Pairing Name 0xb5 0x43: None
|
||||||
|
Pairing Register 0xb5 0x04: None
|
||||||
|
Pairing Register 0xb5 0x14: None
|
||||||
|
Pairing Register 0xb5 0x24: None
|
||||||
|
Pairing Register 0xb5 0x34: None
|
||||||
|
Pairing Name 0xb5 0x44: None
|
||||||
|
Pairing Register 0xb5 0x05: None
|
||||||
|
Pairing Register 0xb5 0x15: None
|
||||||
|
Pairing Register 0xb5 0x25: None
|
||||||
|
Pairing Register 0xb5 0x35: None
|
||||||
|
Pairing Name 0xb5 0x45: None
|
||||||
|
Firmware 0xf1 0x00: None
|
||||||
|
Firmware 0xf1 0x01: None
|
||||||
|
Firmware 0xf1 0x02: None
|
||||||
|
Firmware 0xf1 0x03: None
|
||||||
|
Firmware 0xf1 0x04: None
|
||||||
|
|
||||||
|
Battery status:
|
||||||
|
1.9V critical
|
||||||
|
2.3V low
|
||||||
|
2.5V full
|
|
@ -27,6 +27,7 @@ from __future__ import absolute_import, division, print_function, unicode_litera
|
||||||
## should this last be changed so that may_unpair is used for all receivers? writing to _R.receiver_pairing doesn't seem right
|
## 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
|
# 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?
|
## currently only one receiver is so marked - should there be more?
|
||||||
|
# ex100_wpid_fix enable workarounds for EX100 and possible other old 27Mhz receivers
|
||||||
|
|
||||||
_DRIVER = ('hid-generic', 'generic-usb', 'logitech-djreceiver')
|
_DRIVER = ('hid-generic', 'generic-usb', 'logitech-djreceiver')
|
||||||
|
|
||||||
|
@ -86,6 +87,18 @@ _lightspeed_receiver = lambda product_id: {
|
||||||
'name': 'Lightspeed Receiver'
|
'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_wpid_fix': True
|
||||||
|
}
|
||||||
|
|
||||||
# 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)
|
||||||
|
@ -93,8 +106,10 @@ UNIFYING_RECEIVER_C532 = _unifying_receiver(0xc532)
|
||||||
# Nano receviers that support the Unifying protocol
|
# Nano receviers that support the Unifying protocol
|
||||||
NANO_RECEIVER_ADVANCED = _nano_receiver(0xc52f)
|
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 receivers that don't support the Unifying protocol
|
||||||
NANO_RECEIVER_C517 = _nano_receiver_maxn(0xc517, 6)
|
|
||||||
NANO_RECEIVER_C518 = _nano_receiver(0xc518)
|
NANO_RECEIVER_C518 = _nano_receiver(0xc518)
|
||||||
NANO_RECEIVER_C51A = _nano_receiver(0xc51a)
|
NANO_RECEIVER_C51A = _nano_receiver(0xc51a)
|
||||||
NANO_RECEIVER_C51B = _nano_receiver(0xc51b)
|
NANO_RECEIVER_C51B = _nano_receiver(0xc51b)
|
||||||
|
@ -119,7 +134,7 @@ ALL = (
|
||||||
UNIFYING_RECEIVER_C52B,
|
UNIFYING_RECEIVER_C52B,
|
||||||
UNIFYING_RECEIVER_C532,
|
UNIFYING_RECEIVER_C532,
|
||||||
NANO_RECEIVER_ADVANCED,
|
NANO_RECEIVER_ADVANCED,
|
||||||
NANO_RECEIVER_C517,
|
EX100_27MHZ_RECEIVER_C517,
|
||||||
NANO_RECEIVER_C518,
|
NANO_RECEIVER_C518,
|
||||||
NANO_RECEIVER_C51A,
|
NANO_RECEIVER_C51A,
|
||||||
NANO_RECEIVER_C51B,
|
NANO_RECEIVER_C51B,
|
||||||
|
|
|
@ -293,6 +293,13 @@ _D(
|
||||||
wpid='3622',
|
wpid='3622',
|
||||||
registers=(_R.battery_status, ),
|
registers=(_R.battery_status, ),
|
||||||
)
|
)
|
||||||
|
_D(
|
||||||
|
'Wireless Keyboard EX100',
|
||||||
|
codename='EX100',
|
||||||
|
protocol=1.0,
|
||||||
|
wpid='6500',
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
)
|
||||||
|
|
||||||
# Mice
|
# Mice
|
||||||
|
|
||||||
|
@ -523,6 +530,14 @@ _D(
|
||||||
wpid='6822',
|
wpid='6822',
|
||||||
registers=(_R.battery_status, ),
|
registers=(_R.battery_status, ),
|
||||||
)
|
)
|
||||||
|
_D(
|
||||||
|
'Wireless Mouse EX100',
|
||||||
|
codename='EX100m',
|
||||||
|
protocol=1.0,
|
||||||
|
wpid='3F00',
|
||||||
|
registers=(_R.battery_status, ),
|
||||||
|
# settings=[ _RS.smooth_scroll(), ], # command accepted, but no change in whell action
|
||||||
|
)
|
||||||
|
|
||||||
# Trackballs
|
# Trackballs
|
||||||
|
|
||||||
|
|
|
@ -64,14 +64,26 @@ POWER_SWITCH_LOCATION = _NamedInts(
|
||||||
# - the rest work only on devices as far as we can tell right now
|
# - the rest work only on devices as far as we can tell right now
|
||||||
# In the future would be useful to have separate enums for receiver and device notification flags,
|
# In the future would be useful to have separate enums for receiver and device notification flags,
|
||||||
# but right now we don't know enough.
|
# but right now we don't know enough.
|
||||||
|
# additional flags taken from https://drive.google.com/file/d/0BxbRzx7vEV7eNDBheWY0UHM5dEU/view?usp=sharing
|
||||||
NOTIFICATION_FLAG = _NamedInts(
|
NOTIFICATION_FLAG = _NamedInts(
|
||||||
|
numpad_numerical_keys=0x800000,
|
||||||
|
f_lock_status=0x400000,
|
||||||
|
roller_H=0x200000,
|
||||||
battery_status=0x100000, # send battery charge notifications (0x07 or 0x0D)
|
battery_status=0x100000, # send battery charge notifications (0x07 or 0x0D)
|
||||||
|
mouse_extra_buttons=0x080000,
|
||||||
|
roller_V=0x040000,
|
||||||
keyboard_sleep_raw=0x020000, # system control keys such as Sleep
|
keyboard_sleep_raw=0x020000, # system control keys such as Sleep
|
||||||
keyboard_multimedia_raw=0x010000, # consumer controls such as Mute and Calculator
|
keyboard_multimedia_raw=0x010000, # consumer controls such as Mute and Calculator
|
||||||
# reserved_r1b4= 0x001000, # unknown, seen on a unifying receiver
|
# reserved_r1b4= 0x001000, # unknown, seen on a unifying receiver
|
||||||
|
reserved5=0x008000,
|
||||||
|
reserved4=0x004000,
|
||||||
|
reserved3=0x002000,
|
||||||
|
reserved2=0x001000,
|
||||||
software_present=0x000800, # .. no idea
|
software_present=0x000800, # .. no idea
|
||||||
|
reserved1=0x000400,
|
||||||
keyboard_illumination=0x000200, # illumination brightness level changes (by pressing keys)
|
keyboard_illumination=0x000200, # illumination brightness level changes (by pressing keys)
|
||||||
wireless=0x000100, # notify when the device wireless goes on/off-line
|
wireless=0x000100, # notify when the device wireless goes on/off-line
|
||||||
|
mx_air_3d_gesture=0x000001,
|
||||||
)
|
)
|
||||||
|
|
||||||
ERROR = _NamedInts(
|
ERROR = _NamedInts(
|
||||||
|
@ -116,6 +128,25 @@ REGISTERS = _NamedInts(
|
||||||
notifications=0x00,
|
notifications=0x00,
|
||||||
firmware=0xF1,
|
firmware=0xF1,
|
||||||
)
|
)
|
||||||
|
# Flags taken from https://drive.google.com/file/d/0BxbRzx7vEV7eNDBheWY0UHM5dEU/view?usp=sharing
|
||||||
|
DEVICE_FEATURES = _NamedInts(
|
||||||
|
reserved1=0x010000,
|
||||||
|
special_buttons=0x020000,
|
||||||
|
enhanced_key_usage=0x040000,
|
||||||
|
fast_fw_rev=0x080000,
|
||||||
|
reserved2=0x100000,
|
||||||
|
reserved3=0x200000,
|
||||||
|
scroll_accel=0x400000,
|
||||||
|
buttons_control_resolution=0x800000,
|
||||||
|
inhibit_lock_key_sound=0x000001,
|
||||||
|
reserved4=0x000002,
|
||||||
|
mx_air_3d_engine=0x000004,
|
||||||
|
host_control_leds=0x000008,
|
||||||
|
reserved5=0x000010,
|
||||||
|
reserved6=0x000020,
|
||||||
|
reserved7=0x000040,
|
||||||
|
reserved8=0x000080,
|
||||||
|
)
|
||||||
|
|
||||||
#
|
#
|
||||||
# functions
|
# functions
|
||||||
|
@ -316,3 +347,19 @@ def set_notification_flags(device, *flag_bits):
|
||||||
assert flag_bits & 0x00FFFFFF == flag_bits
|
assert flag_bits & 0x00FFFFFF == flag_bits
|
||||||
result = write_register(device, REGISTERS.notifications, _int2bytes(flag_bits, 3))
|
result = write_register(device, REGISTERS.notifications, _int2bytes(flag_bits, 3))
|
||||||
return result is not None
|
return result is not None
|
||||||
|
|
||||||
|
|
||||||
|
def get_device_features(device):
|
||||||
|
assert device
|
||||||
|
|
||||||
|
# Avoid a call if the device is not online,
|
||||||
|
# or the device does not support registers.
|
||||||
|
if device.kind is not None:
|
||||||
|
# peripherals with protocol >= 2.0 don't support registers
|
||||||
|
if device.protocol and device.protocol >= 2.0:
|
||||||
|
return
|
||||||
|
|
||||||
|
flags = read_register(device, REGISTERS.mouse_button_flags)
|
||||||
|
if flags is not None:
|
||||||
|
assert len(flags) == 3
|
||||||
|
return _bytes2int(flags)
|
||||||
|
|
|
@ -160,8 +160,8 @@ def _process_hidpp10_custom_notification(device, status, n):
|
||||||
# message layout: 10 ix <register> <xx> <yy> <zz> <00>
|
# message layout: 10 ix <register> <xx> <yy> <zz> <00>
|
||||||
assert n.data[-1:] == b'\x00'
|
assert n.data[-1:] == b'\x00'
|
||||||
data = chr(n.address).encode() + n.data
|
data = chr(n.address).encode() + n.data
|
||||||
charge, status_text = _hidpp10.parse_battery_status(n.sub_id, data)
|
charge, status_text, next_charge = _hidpp10.parse_battery_status(n.sub_id, data)
|
||||||
status.set_battery_info(charge, status_text, None)
|
status.set_battery_info(charge, status_text, next_charge)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if n.sub_id == _R.keyboard_illumination:
|
if n.sub_id == _R.keyboard_illumination:
|
||||||
|
@ -201,6 +201,9 @@ def _process_hidpp10_notification(device, status, n):
|
||||||
if protocol_name:
|
if protocol_name:
|
||||||
if _log.isEnabledFor(_DEBUG):
|
if _log.isEnabledFor(_DEBUG):
|
||||||
wpid = _strhex(n.data[2:3] + n.data[1:2])
|
wpid = _strhex(n.data[2:3] + n.data[1:2])
|
||||||
|
# workaround for short EX100 wpids
|
||||||
|
if protocol_name == '27 MHz':
|
||||||
|
wpid = _strhex(n.data[2:3]) + '00'
|
||||||
assert wpid == device.wpid, '%s wpid mismatch, got %s' % (device, wpid)
|
assert wpid == device.wpid, '%s wpid mismatch, got %s' % (device, wpid)
|
||||||
|
|
||||||
flags = ord(n.data[:1]) & 0xF0
|
flags = ord(n.data[:1]) & 0xF0
|
||||||
|
|
|
@ -88,6 +88,14 @@ class PairedDevice(object):
|
||||||
self.wpid = _strhex(link_notification.data[2:3] + link_notification.data[1:2])
|
self.wpid = _strhex(link_notification.data[2:3] + link_notification.data[1:2])
|
||||||
# assert link_notification.address == (0x04 if unifying else 0x03)
|
# assert link_notification.address == (0x04 if unifying else 0x03)
|
||||||
kind = ord(link_notification.data[0:1]) & 0x0F
|
kind = ord(link_notification.data[0:1]) & 0x0F
|
||||||
|
# fix EX100 wpid
|
||||||
|
if receiver.ex100_wpid_fix: # EX100 receiver
|
||||||
|
self.wpid = _strhex(link_notification.data[2:3]) + '00'
|
||||||
|
# workaround for EX100 switched kind
|
||||||
|
if self.wpid == '3F00':
|
||||||
|
kind = 2
|
||||||
|
if self.wpid == '6500':
|
||||||
|
kind = 1
|
||||||
self._kind = _hidpp10.DEVICE_KIND[kind]
|
self._kind = _hidpp10.DEVICE_KIND[kind]
|
||||||
else:
|
else:
|
||||||
# force a reading of the wpid
|
# force a reading of the wpid
|
||||||
|
@ -97,6 +105,20 @@ class PairedDevice(object):
|
||||||
self.wpid = _strhex(pair_info[3:5])
|
self.wpid = _strhex(pair_info[3:5])
|
||||||
kind = ord(pair_info[7:8]) & 0x0F
|
kind = ord(pair_info[7:8]) & 0x0F
|
||||||
self._kind = _hidpp10.DEVICE_KIND[kind]
|
self._kind = _hidpp10.DEVICE_KIND[kind]
|
||||||
|
elif receiver.ex100_wpid_fix:
|
||||||
|
# ex100 receiver, fill fake device_info with known wpid's
|
||||||
|
# accordingly to drivers/hid/hid-logitech-dj.c
|
||||||
|
# index 1 or 2 always mouse, index 3 always the keyboard,
|
||||||
|
# index 4 is used for an optional separate numpad
|
||||||
|
if number == 1: # mouse
|
||||||
|
self.wpid = '3F00'
|
||||||
|
self._kind = _hidpp10.DEVICE_KIND[2]
|
||||||
|
elif number == 3: # keyboard
|
||||||
|
self.wpid = '6500'
|
||||||
|
self._kind = _hidpp10.DEVICE_KIND[1]
|
||||||
|
else: # unknown device number on EX100
|
||||||
|
_log.error('failed to set fake EX100 wpid for device %d of %s', number, receiver)
|
||||||
|
raise _base.NoSuchDevice(number=number, receiver=receiver, error='Unknown EX100 device')
|
||||||
else:
|
else:
|
||||||
# unifying protocol not supported, must be a Nano receiver
|
# unifying protocol not supported, must be a Nano receiver
|
||||||
device_info = self.receiver.read_register(_R.receiver_info, 0x04)
|
device_info = self.receiver.read_register(_R.receiver_info, 0x04)
|
||||||
|
@ -365,6 +387,7 @@ class Receiver(object):
|
||||||
self._str = '<%s(%s,%s%s)>' % (
|
self._str = '<%s(%s,%s%s)>' % (
|
||||||
self.name.replace(' ', ''), self.path, '' if isinstance(self.handle, int) else 'T', self.handle
|
self.name.replace(' ', ''), self.path, '' if isinstance(self.handle, int) else 'T', self.handle
|
||||||
)
|
)
|
||||||
|
self.ex100_wpid_fix = product_info.get('ex100_wpid_fix', False)
|
||||||
|
|
||||||
self._firmware = None
|
self._firmware = None
|
||||||
self._devices = {}
|
self._devices = {}
|
||||||
|
|
|
@ -96,6 +96,13 @@ def _print_device(dev):
|
||||||
print(' Notifications: %s (0x%06X).' % (', '.join(notification_names), notification_flags))
|
print(' Notifications: %s (0x%06X).' % (', '.join(notification_names), notification_flags))
|
||||||
else:
|
else:
|
||||||
print(' Notifications: (none).')
|
print(' Notifications: (none).')
|
||||||
|
device_features = _hidpp10.get_device_features(dev)
|
||||||
|
if device_features is not None:
|
||||||
|
if device_features:
|
||||||
|
device_features_names = _hidpp10.DEVICE_FEATURES.flag_names(device_features)
|
||||||
|
print(' Features: %s (0x%06X)' % (', '.join(device_features_names), device_features))
|
||||||
|
else:
|
||||||
|
print(' Features: (none)')
|
||||||
|
|
||||||
if dev.online and dev.features:
|
if dev.online and dev.features:
|
||||||
print(' Supports %d HID++ 2.0 features:' % len(dev.features))
|
print(' Supports %d HID++ 2.0 features:' % len(dev.features))
|
||||||
|
|
Loading…
Reference in New Issue