Closed jocelynthode closed 3 years ago
This appears to be a connection notification (0x41). That should not be processed by the custom notification code but instead by _process_hidpp10_notification. These messages are mostly the same for all protocols. The warning message that should have been created is "connection notification with unknown protocol".
Try running with -dd
and see if the debug messages help say what is going on. If that doesn't help, try putting in print statements in notifications.py to diagnose the control flow.
_process_hidpp10_notification should be updated to allow this protocol.
Hey @pfps . Thanks for the tips I actually lost myself in the code. You were right and it was using the _process_hidpp10_notification
method. I added a new protocol for 0x0F
and now I'm stuck at the next issue.
I'll try and dig by myself in the following days and see if I get stuck again!
Thanks!
I fixed up _process_hidpp10_notification to better handle some corner cases and also all protocols (which are supposed to be mostly the same). Try PR #1306. You could base your changes on this PR.
To download and work with Solar
git clone https://github.com/pwr-Solaar/Solaar.git
cd Solaar
Run Solaar as bin/solaar from this directory.
To run PR #1306, first clone Solaar if you have not already done so and cd to the clone directory. The first time you download the pull request, fetch it into a new branch and checkout that branch, as in:
git fetch origin pull/1306/head:pull_1306
git checkout pull_1306
To download a new version of the pull request, fetch it and then set your pull branch to the new fetch, as in:
git checkout pull_1306
git fetch origin pull/1306/head
git reset --hard FETCH_HEAD
@jocelynthode What is the next issue you ran into?
Hey @pfps,
sorry I was at work and unable to work further on this. I just started debugging again.
my next issue is now in the _notifications_handler
listener method
The first few notifications being handled are working fine and I get the following logs:
DEVICE CONNNECTION NOTIFICATION Notification(10,1,41,0F,329340) <Device(1,4093,PRO X Wireless,E7C3DFD4)> {}
DEVICE CONNNECTION NOTIFICATION Notification(10,1,41,0F,318E40) <Device(1,408E,G915 TKL LIGHTSPEED Wireless RGB Mechanical Gaming Keyboard,EC762B99)> {}
However afterwards I start getting weird notification with a 0x00
address: Notification(11,1,11,00,00000000000000000000000000000000)
This obviously make the code crash on the line further if not (0 < n.devnumber <= self.receiver.max_devices):
since there are no max_device.
The receiver in these weird notifications are the mouse and keyboard (e.g.: <Device(255,C545,G915 TKL LIGHTSPEED Wireless RGB Mechanical Gaming Keyboard,?)>
) My guess is that the code should handle only notifications for the Lightspeed receiver but here the receiver is the Peripheral directly instead of its parent lightspeed receiver.
This might be due to the new code that catches a few too many Notifications?
What might be happening is that the notifications are being picked up by the device listener. These notifications are not going to cause any processing in this part of Solaar to the correct thing to do is to pass them through. But the code needs a bit of fixup to do the right thing.
OK, try PR #1306 now.
Seems to have fixed the issue! on to the next one ;)
I had to fix a few conditions. Now it seems as if the lightspeed receiver disconnect which logs the following:
21:47:01,074 INFO [ReceiverListener:hidraw2] solaar.listener: <LightspeedReceiver(/dev/hidraw2,12)>: notifications listener has stopped
From my understanding this seems to then trigger an update of the window making every lightspeed receiver entry disappear and thus deleting the mouse and keyboard.
I think I'm close to having it working as the status update for both the mouse and keyboards look good:
22:13:14,773 INFO [ReceiverListener:hidraw2] solaar.listener: status_changed <Device(1,4093,PRO X Wireless,E7C3DFD4)>: paired online, {'LINK ENCRYPTED': True, 'BATTERY LEVEL': 75, 'BATTERY STATUS': NamedInt(0, 'discharging'), 'BATTERY NEXT LEVEL': None, 'BATTERY VOLTAGE': None, 'BATTERY CHARGING': False, 'ERROR': None} (0)
22:13:14,773 INFO [ReceiverListener:hidraw2] solaar.listener: status_changed <Device(1,4093,PRO X Wireless,E7C3DFD4)>: paired online, {'LINK ENCRYPTED': True, 'BATTERY LEVEL': 75, 'BATTERY STATUS': NamedInt(0, 'discharging'), 'BATTERY NEXT LEVEL': None, 'BATTERY VOLTAGE': None, 'BATTERY CHARGING': False, 'ERROR': None} (0)
22:13:14,931 INFO [ReceiverListener:hidraw7] solaar.listener: status_changed <Device(1,408E,G915 TKL LIGHTSPEED Wireless RGB Mechanical Gaming Keyboard,EC762B99)>: paired online, {'LINK ENCRYPTED': True, 'BATTERY LEVEL': NamedInt(50, 'average'), 'BATTERY STATUS': NamedInt(0, 'discharging'), 'BATTERY NEXT LEVEL': None, 'BATTERY VOLTAGE': 4015, 'BATTERY CHARGING': False, 'ERROR': None} (0)
22:13:14,931 INFO [ReceiverListener:hidraw7] solaar.listener: status_changed <Device(1,408E,G915 TKL LIGHTSPEED Wireless RGB Mechanical Gaming Keyboard,EC762B99)>: paired online, {'LINK ENCRYPTED': True, 'BATTERY LEVEL': NamedInt(50, 'average'), 'BATTERY STATUS': NamedInt(0, 'discharging'), 'BATTERY NEXT LEVEL': None, 'BATTERY VOLTAGE': 4015, 'BATTERY CHARGING': False, 'ERROR': None} (0)
I feel like I'm missing a key understanding on why the lightspeed devices would switch to inactive.
Devices go into power-saving mode which disconnects them from the receiver but receivers shouldn't (unless the USB port goes into power saving mode). Perhaps you could post the output of solaar show
when the devices are active to show how everything is connected.
There are a lot of moving parts here, which causes complexity in the code and in debugging. You could also post the output of solaar -dd
to show the messages that are being sent and what Solaar is doing.
Also, having two devices active at the same time makes debugging much more difficult as Solaar is multi-threaded and the interactions with the devices can be interleaved.
Unfortunately I don't have any other keyboard at the moment so I can't really remove it :/
Here is the output of my solaar show
Lightspeed Receiver
Device path : /dev/hidraw2
USB id : 046d:C547
Serial : XXX
Firmware : 04.00.B0005
Bootloader : 00.05
Other : 84.70
Has 1 paired device(s) out of a maximum of 2.
Notifications: wireless, software present (0x000900)
Device activity counters: 1=13
1: PRO X Wireless
Device path : None
WPID : 4093
Codename : PRO X
Kind : mouse
Protocol : HID++ 4.2
Polling rate : 1 ms (1000Hz)
Serial number: XXX
Model ID: XX
Unit ID: E7C3DFD4
Bootloader: BL1 25.00.B0013
Other:
Firmware: MPM 25.00.B0013
The power switch is located on the base.
Supports 27 HID++ 2.0 features:
0: ROOT {0000}
1: FEATURE SET {0001}
2: DEVICE FW VERSION {0003}
Firmware: Bootloader BL1 25.00.B0013 AB00BE657A82
Firmware: Other
Firmware: Firmware MPM 25.00.B0013 4093BE657A82
Unit ID: E7C3DFD4 Model ID: 4093C0940000 Transport IDs: {'wpid': '4093', 'usbid': 'C094'}
3: DEVICE NAME {0005}
Name: PRO X Wireless
Kind: mouse
4: WIRELESS DEVICE STATUS {1D4B}
5: RESET {0020}
6: UNIFIED BATTERY {1004}
7: COLOR LED EFFECTS {8070} internal, hidden
8: ONBOARD PROFILES {8100}
Device Mode: Host
9: MOUSE BUTTON SPY {8110}
10: REPORT RATE {8060}
Polling Rate (ms): 1
Polling Rate (ms) (saved): 1
Polling Rate (ms) : 1
11: ADJUSTABLE DPI {2201}
Sensitivity (DPI) (saved): 1600
Sensitivity (DPI) : 1600
12: DEVICE RESET {1802} internal, hidden
13: unknown:1803 {1803} internal, hidden
14: CONFIG DEVICE PROPS {1806} internal, hidden
15: unknown:1811 {1811} internal, hidden
16: OOBSTATE {1805} internal, hidden
17: unknown:1830 {1830} internal, hidden
18: unknown:1890 {1890} internal, hidden
19: unknown:1891 {1891} internal, hidden
20: unknown:18A1 {18A1} internal, hidden
21: unknown:1801 {1801} internal, hidden
22: unknown:18B1 {18B1} internal, hidden
23: unknown:1E00 {1E00} hidden
24: unknown:1EB0 {1EB0} internal, hidden
25: unknown:1863 {1863} internal, hidden
26: unknown:1E22 {1E22} internal, hidden
Battery: 74%, discharging.
Lightspeed Receiver
Device path : /dev/hidraw7
USB id : 046d:C545
Serial : XXXX
Firmware : 02.00.B0001
Bootloader : 00.01
Other : CF.20
Has 1 paired device(s) out of a maximum of 2.
Notifications: wireless, software present (0x000900)
Device activity counters: 1=105
1: G915 TKL LIGHTSPEED Wireless RGB Mechanical Gaming Keyboard
Device path : None
WPID : 408E
Codename : G915 TKL
Kind : keyboard
Protocol : HID++ 4.2
Polling rate : 1 ms (1000Hz)
Serial number: EC762B99
Model ID: XXXX
Unit ID: XXX
Bootloader: BL1 12.00.B0017
Other:
Firmware: MPK 14.00.B0017
Other:
Other:
The power switch is located on the top left corner.
Supports 38 HID++ 2.0 features:
0: ROOT {0000}
1: FEATURE SET {0001}
2: DEVICE FW VERSION {0003}
Firmware: Bootloader BL1 12.00.B0017 00008B79E978
Firmware: Other
Firmware: Firmware MPK 14.00.B0017 408E8B79E978
Firmware: Other
Firmware: Other
Unit ID: EC762B99 Model ID: B35F408EC343 Transport IDs: {'btleid': 'B35F', 'wpid': '408E', 'usbid': 'C343'}
3: DEVICE NAME {0005}
Name: G915 TKL LIGHTSPEED Wireless RGB Mechanical Gaming Keyboard
Kind: keyboard
4: WIRELESS DEVICE STATUS {1D4B}
5: RESET {0020}
6: DEVICE FRIENDLY NAME {0007}
Friendly Name: G915 TKL
7: BATTERY VOLTAGE {1001}
Battery: 4005mV, discharging, average.
8: CHANGE HOST {1814}
Change Host : 1:archfixe
9: HOSTS INFO {1815}
Host 0 (paired): archfixe
Host 1 (unpaired):
10: RGB EFFECTS {8071}
11: PER KEY LIGHTING V2 {8081}
12: REPROG CONTROLS V4 {1B04}
13: REPORT HID USAGE {1BC0}
14: ENCRYPTION {4100}
15: KEYBOARD DISABLE BY USAGE {4522}
16: KEYBOARD LAYOUT 2 {4540}
17: GKEY {8010}
Divert G Keys (saved): False
Divert G Keys : False
18: MKEYS {8020}
19: MR {8030}
20: BRIGHTNESS CONTROL {8040}
21: ONBOARD PROFILES {8100}
Device Mode: On-Board
22: REPORT RATE {8060}
Polling Rate (ms): 1
23: DFUCONTROL SIGNED {00C2}
24: DFU {00D0}
25: DEVICE RESET {1802} internal, hidden
26: unknown:1803 {1803} internal, hidden
27: CONFIG DEVICE PROPS {1806} internal, hidden
28: unknown:1813 {1813} internal, hidden
29: OOBSTATE {1805} internal, hidden
30: unknown:1830 {1830} internal, hidden
31: unknown:1890 {1890} internal, hidden
32: unknown:1891 {1891} internal, hidden
33: unknown:18A1 {18A1} internal, hidden
34: unknown:1E00 {1E00} hidden
35: unknown:1EB0 {1EB0} internal, hidden
36: unknown:1861 {1861} internal, hidden
37: unknown:18B0 {18B0} internal, hidden
Has 2 reprogrammable keys:
0: Host Switch Channel 1 , default: HostSwitch Channel 1 => HostSwitch Channel 1
divertable, persistently divertable, pos:1, group:0, group mask:empty
reporting: default
1: Host Switch Channel 2 , default: HostSwitch Channel 2 => HostSwitch Channel 2
divertable, persistently divertable, pos:2, group:0, group mask:empty
reporting: default
Battery: 4005mV, discharging, average.
Wired Devices
1: PRO X Wireless
Device path : /dev/hidraw2
USB id : 046d:C547
Codename : PRO X
Kind : mouse
Protocol : HID++ 1.0
Serial number: ?
Firmware: 04.00.B0005
Bootloader: 00.05
Other: 84.70
Notifications: wireless, software present (0x000900).
Features: (none)
Battery status unavailable.
2: G915 TKL LIGHTSPEED Wireless RGB Mechanical Gaming Keyboard
Device path : /dev/hidraw7
USB id : 046d:C545
Codename : G915 TKL
Kind : keyboard
Protocol : HID++ 1.0
Serial number: ?
Firmware: 02.00.B0001
Bootloader: 00.01
Other: CF.20
Notifications: wireless, software present (0x000900).
Features: (none)
Battery status unavailable.
here is a gist of the debug logs: https://gist.github.com/jocelynthode/8fed3ad8a34ff93c854b6e992e4f49dd
Something is going wrong. There should not be two entries for your devices. Your devices are connected via a receiver and should not also be connected via a wired connection.
What kernel and distribution are you running?
I think the problem is that you have added incorrect descriptors for your devices. Devices that connect via a receiver don't have USB IDs so you should remove this information, which is only for devices that connect directly via a USB cable. As well, the USB ID you have is the ID for the receiver.
For example, the G502 gaming mouse can connect via a USB cable. Its descriptor is
_D('G502 Hero Gaming Mouse', codename='G502 Hero', usbid=0xc08d)
But this descriptor is only needed to give a slightly better name to the mouse. Solaar doesn't need it.
This mouse can also connect via a Lightspeed receiver, which Solaar does need to know about in base_usb.py as
LIGHTSPEED_RECEIVER_C539 = _lightspeed_receiver(0xc539)
Ah that's exactly what my last issue was! I thought I had to add the usbid as the mouse can be connected via a USB cable and I saw this information in the solaar show.
Here's the result! Thanks for all the help you provided! I was a bit lost around the codebase and logitech's protocols :)
I'll test my changes a bit more and will make a PR this evening.
Also I noticed that unfortunately, when the mouse is plugged I cannot see it anymore. If I wanted to also see my mouse/keyboard when they are connected to for example to monitor the battery charge? Or is this out of scope of the project?
The problem is likely that the mouse uses USB interface 1 when connected via a USB cable. Look for lines similar to
23:50:03,021 DEBUG [MainThread] hidapi.udev: Found device BID 0003 VID 0000046D PID 0000XXXX INTERFACE y FILTER 2
when the mouse is connected via a USB cable. If only interface 0 and 1 show up then you probably need a descriptor like
_D('PRO X Wireless Mouse', codename='PRO X', usbid=0xXXXX, wpid='4093', interface=1)
Strange, the keyboard seems to appear by itself in the gui when cabled although I did not find any descriptor for it besides mine.
When the mouse and keyboard are cabled I see the following lines:
07:43:23,782 DEBUG [MainThread] hidapi.udev: Found device BID 0003 VID 0000046D PID 0000C094 INTERFACE 0 FILTER 1
07:43:23,783 DEBUG [MainThread] hidapi.udev: Found device BID 0003 VID 0000046D PID 0000C094 INTERFACE 1 FILTER 1
07:43:24,088 DEBUG [MainThread] hidapi.udev: Found device BID 0003 VID 0000046D PID 0000C094 INTERFACE 2 FILTER 1
07:43:24,088 DEBUG [MainThread] hidapi.udev: Found device BID 0003 VID 0000046D PID 0000C343 INTERFACE 0 FILTER 2
07:43:24,089 DEBUG [MainThread] hidapi.udev: Found device BID 0003 VID 0000046D PID 0000C343 INTERFACE 1 FILTER 2
07:43:24,089 DEBUG [MainThread] hidapi.udev: Found device BID 0003 VID 0000046D PID 0000C343 INTERFACE 2 FILTER 2
so the usbid will be 0xC094
and 0xC343
.
However I'm not sure I understand how the descriptor would work if I added these usbid and how to choose between all 3 interfaces.
and would the interface specified only be used when connecting via usb? Otherwise how is Solaar differentiating when to use which interface?
When a device is directly connected (via a USB cable or via Bluetooth) it shows up by itself, i.e., not associated with a receiver. If the receiver is also connected the receiver will still show up. The devices paired with the receiver will also show up, even if they are not currently connected to the receiver, but then they are inactive. So a device can show up twice, but only one will be active.
The reason that the 0xC094 is not showing up is that it is a new product and its USB ID is out of the range that Solaar is looking for. To fix this change the 0xC093 to 0x094 in other_device_check in base_usb.py.
The different interfaces are only for USB connections. They are a peculiarity of USB - different interfaces process different messages. It is possible to figure out which interface does HID++ but it is complicated and Solaar just uses interface 2, which is correct for most devices, unless there is descriptor providing a different interface.
You probably don't need a descriptor for either of these devices.
Everything is now working perfectly. Thanks for all the help and the various explanations :)
Hey guys,
I recently bought a Logitech Wireless Pro X Superlight and a G915 TKL keyboard. I can configure them just fine through Piper/ratbagd when they are plugged over usb.
However I'd like to get more information in my system tray icon such as the battery level. I found about this project and I saw that when using solaar I only see in the windows "Lightspeed Receiver" but I don't see any recognized keyboard or mouse under it.
After digging a bit in the code I tried adding in
descriptors.py
the following declaration:However, now when I launched my built copy of Solaar I get the following error warning and then the notification listener crashes:
by analyzing error I found out that there is a missing case for this kind of notification. Specifically the code trie sto use the
_process_hidpp10_custom_notification
and not a specially 2.0+ method. the adress0x0F
has also no case.Could someone provide me some pointers on where to go from there so that I could try and implement support for these devices?
Cheers