Closed coxaka closed 1 year ago
Is your G935 connected wirelessly?
Getting this to work is going to be tricky. The error you see is because the script tries to find the USB endpoint of the device, which if connected via Bluetooth is not going to exist.
This issue is similar to the G915 (wireless version of G815), because the USB endpoint registered in the system is not actually the one of the keyboard, but it is the one of the USB dongle doing the connection.
Is it possible to connect the headphones via USB cable?
If yes it would be interesting if the USB endpoint can be found correctly or not. If not, then could you give me the dmesg output when connecting your headphones?
You can do it like this:
sudo dmesg -w
It should show some output of the headphones registering in the kernel.
In general it is sadly quite tricky to add support for devices "remotely" since so far I have always needed to also reverse engineer the Windows driver in order to get command sequences needed to switch the device into host mode.
It is connected wireless with a dongle. As far as I know you can only connect USB for charging
dmesg output:
[ 1344.560923] usb 1-5: new full-speed USB device number 9 using xhci_hcd
[ 1344.728220] usb 1-5: New USB device found, idVendor=046d, idProduct=0a87, bcdDevice= 1.12
[ 1344.728233] usb 1-5: New USB device strings: Mfr=3, Product=4, SerialNumber=0
[ 1344.728237] usb 1-5: Product: G935 Gaming Headset
[ 1344.728241] usb 1-5: Manufacturer: Logitech
[ 1345.069799] input: Logitech G935 Gaming Headset Consumer Control as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.3/0003:046D:0A87.0009/input/input32
[ 1345.124631] input: Logitech G935 Gaming Headset as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.3/0003:046D:0A87.0009/input/input33
[ 1345.124746] input: Logitech G935 Gaming Headset as /devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.3/0003:046D:0A87.0009/input/input35
[ 1345.125116] hid-generic 0003:046D:0A87.0009: input,hiddev96,hidraw0: USB HID v1.11 Device [Logitech G935 Gaming Headset] on usb-0000:00:14.0-5/input3
Thank you for the dmesg, it is sadly the exact same problem / situation as with the G915 (#25).
Connecting to the USB dongle probably fails, because one or more of these parameters at the start of the script are not correct:
usbConfiguration = 0
usbInterface = (1, 0)
usbEndpoint = 0
disableGKeysInterface = 1
usbUseWrite = True
Sadly I cannot tell you which ones are needed for your device, every device is different, it is essentially a guessing game.
Once that works, it should be possible to find the correct HID endpoint and connect to it.
If you are lucky, the headphones will directly send raw data to that endpoint. If not (like it is the case with the G915) then I usually have to send one or more commands to the device to make it send the raw commands. Sadly as I already mentioned above, I had to find those out by reversing the Windows driver as Logitech does not document them publicly.
I managed to get the USB info by running
import usb.core
print(usb.core.find(idVendor=0x046d, idProduct=0x0a87))
Using interface 3 seems to work
usbConfiguration = 0
usbInterface = (3, 0)
usbEndpoint = 0
disableGKeysInterface = 3
usbUseWrite = True
DEBUG: Searching for keyboard...
DEBUG: Keyboard found! :)
DEBUG: requesting USB endpoint...
DEBUG: HIDraw read endpoint found: /dev/hidraw0
DEBUG: HIDraw disable endpoint found: /dev/hidraw0
DEBUG: HIDraw read endpoint found: /dev/hidraw0
DEBUG: HIDraw disable endpoint found: /dev/hidraw0
[...]
DEBUG: Checking for HID availability...
DEBUG: Connected to /dev/hidraw0
INFO: starting listener...
DEBUG: Using selector: EpollSelector
DEBUG: Connection using HIDAPI...
DEBUG: Sending sequence to disable G keys
0: b'\x11\xff\x10>\x00\x04\x00\x00\x00\x00\x00\x00\xd0\x01d\x07\x00\x00\x00\x00'
1: b'\x11\xff\x08.\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
DEBUG: listening to USB Interface (3, 0) | b'/dev/hidraw0'
Unfortunately only the mute and volume controls seem to be picked up. I tried all known disableGKey commands but they dont seem to change anything
vol up
got data from keyboard: b'\x01\x01\x00\x00\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00'
vol down
got data from keyboard: b'\x01\x02\x00\x00\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00'
mute/unmute
got data from keyboard: b'\x01\x00\x00\x00\x00'
Oddly when toggling the LEDs or changing sidetone settings with other software like HeadsetControl the headset sends something back:
leds off
got data from keyboard: b'\x11\xff\x04<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
leds on
got data from keyboard: b'\x11\xff\x04<\x00\x02\x00\xb6\xff\x0f\xa0\x00d\x00\x00\x00\x00\x00\x00\x00'
sidetone off
got data from keyboard: b'\x11\xff\x07\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
sidetone max
got data from keyboard: b'\x11\xff\x07\x1ad\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
is there a method to finding the correct commands? or just poking around in a debugger?
Oh this is interesting, so Interfaces 0 - 2 are Audio, which makes sense and 3 is a HID device.
Does anything happen when you press the GKeys? In the case of the G915 the GKeys are mapped to F1-Fn by default is that also the case for you?
is there a method to finding the correct commands? or just poking around in a debugger?
Depends on the device. If your headset is supported by Logitech Ghub (not LGS), then my setup was a Windows VM with Logitech Ghub installed in it and Wireshark with the USB plugin (you have to check the USB thingy in the installer).
Then you have to listen on the USB port of the device and launch Ghub.
It will then send a bunch of data back and forth. Most important is the launch sequence and when you press any of the GKeys.
You can copy the bytes sent directly into the debugger script and check if it is working.
EDIT: how does the headset get listed in sudo evtest
? When listening to it, which buttons does it trigger when you press any of the GKeys?
evtest only triggers when using the volume wheel while newDeviceDebugger additionally shows mic mute events.
/dev/input/event3: Logitech G935 Gaming Headset Consumer Control
/dev/input/event4: Logitech G935 Gaming Headset
/dev/input/event5: Logitech G935 Gaming Headset
3
Event: time 1690760103.022618, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e9
Event: time 1690760103.022618, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 1
Event: time 1690760103.022618, -------------- SYN_REPORT ------------
Event: time 1690760103.072615, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00e9
Event: time 1690760103.072615, type 1 (EV_KEY), code 115 (KEY_VOLUMEUP), value 0
Event: time 1690760103.072615, -------------- SYN_REPORT ------------
Event: time 1690760105.924779, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00ea
Event: time 1690760105.924779, type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 1
Event: time 1690760105.924779, -------------- SYN_REPORT ------------
Event: time 1690760105.974727, type 4 (EV_MSC), code 4 (MSC_SCAN), value c00ea
Event: time 1690760105.974727, type 1 (EV_KEY), code 114 (KEY_VOLUMEDOWN), value 0
I'll check later if I can see something with wireshark
Progress :)
Using wireshark I found commands being sent from the host
putting these into the newDeviceDebugger actually seems to work and I can see the G buttons being pressed
from my testing only this packet seems to be required:
disableGKeys = [
b'\x11\xff\x05\x2a\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
]
which leads to these results:
G3 pressed
got data from keyboard: b'\x11\xff\x05\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
unpressed
got data from keyboard: b'\x11\xff\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
G2 pressed/unpressed
got data from keyboard: b'\x11\xff\x05\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x11\xff\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
G1 pressed/unpressed
got data from keyboard: b'\x11\xff\x05\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x11\xff\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Mute button pressed
got data from keyboard: b'\x08\x01'
flick up microphone (mute)
got data from keyboard: b'\x08\x10'
flick down microphone (unmute)
got data from keyboard: b'\x08 '
lost connection to headset (turned off)
got data from keyboard: b'\x11\xff\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
headset connected
got data from keyboard: b'\x11\xff\x08\x00\x0ec\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00'
oh nice good job, this is exactly what I need!
Does mute / unmute actually work, as in does it trigger the mute / unmute system wide? If not, this could be added quite easily.
EDIT: does the mute button not send two packages? Usually there is a "pressed" and a "release" package
I have pushed the initial implementation to the G935
branch, could you give it a try and see how far you can get?
I tested the G935 branch and it works like a charm.
Mute/unmute doesnt work, flicking up the microphone mutes it but there is no way to unmute it after that. The mute button only sends one packet no matter if the microphone is muted or unmuted or if the button is pressed released or held. I think it would be best to make the mute button also configurable since you mainly mute yourself by moving the microphone up.
Also if its not too hard to implement it would be great if the disableGKeys command can be sent everytime the headset connects (in case you turn the headset off or change batteries)
Another small nitpick: The order of the G buttons does not represent the physical layout, it should be G3, G2, G1, Mute
Mute/unmute doesnt work I think it would be best to make the mute button also configurable since you mainly mute yourself by moving the microphone up.
Sorry this might be a dumb question, but are you talking about the headphone mute or the microphone mute? You make it sound like they are the same thing and both mute the microphone?
flicking up the microphone mutes it but there is no way to unmute it after that.
This seems to be a known issue since forever and it looks like only hacky solutions exist. (see here for reference). My hope is that uinput.KEY_MICMUTE does also unmute it, but it could get really messy as it would just toggle each time and not actually set on or off.
The mute button only sends one packet no matter if the microphone is muted or unmuted or if the button is pressed released or held.
Ok understood not a big issue, but weird given that all their keyboards do it.
Also if its not too hard to implement it would be great if the disableGKeys command can be sent everytime the headset connects (in case you turn the headset off or change batteries)
Sadly tricky to implement in the current codebase as this behavior does not exist with wired keyboard. A quick hack could be doable, but I fear that it might cause issues with existing users, so the proper way would be to implement an alternative mode for headphones (where I then could also treat the mute / unmute separately as currently mute is done by the kernel driver for all supported keyboard.
Another small nitpick: The order of the G buttons does not represent the physical layout, it should be G3, G2, G1, Mute
Do you mean just the order of the buttons in the UI or does G1 in the UI not map to the physical G1 button?
Sorry this might be a dumb question, but are you talking about the headphone mute or the microphone mute? You make it sound like they are the same thing and both mute the microphone?
They both mute the microphone which is why I suggested making the button configurable.
This seems to be a known issue since forever and it looks like only hacky solutions exist. (see here for reference). My hope is that uinput.KEY_MICMUTE does also unmute it, but it could get really messy as it would just toggle each time and not actually set on or off.
Actually it all works as expected until you disable G keys. And when G keys are disabled and the microphone is stuck you can fix it by muting and unmuting e.g. by sending XF86AudioMicMute twice
Do you mean just the order of the buttons in the UI or does G1 in the UI not map to the physical G1 button?
It is mapped correctly, just the order in the UI is wrong
They both mute the microphone which is why I suggested making the button configurable.
Alright ok now I understand.
And when G keys are disabled and the microphone is stuck you can fix it by muting and unmuting e.g. by sending XF86AudioMicMute twice
Does mute / unmute after G keys disabled work at all? If yes, then that is the kernel driver doing it, which means remapping those buttons is not trivial. if no, then it should be fixable.
It is mapped correctly, just the order in the UI is wrong
Understood, well that is currently hard coded. :V
Does mute / unmute after G keys disabled work at all? If yes, then that is the kernel driver doing it, which means remapping those buttons is not trivial. if no, then it should be fixable.
with G keys disabled unmute doesnt work at all, mute only works when moving the microphone up, which is probably a firmware thing
ok one last question, does the mute button (the one you would like to remap) do anything after sending disableGKeys?
no it just sends data but doesnt mute or unmute the microphone
got data from keyboard: b'\x08\x01'
Alright understood, I will add the mute button as G4 then so you can remap it. (the names are hard coded for now, renaming them will require implementing a separate mode for that, which I currently don't have the time to do)
EDIT: ah damn I just realized that I cannot do that with the current logic, because there is no releaseEvent, so the moment you press the button it will get registered as you holding down the button all the time.
I pushed version 1.0.5 with initial support. For full support you will have to be a bit patient as I currently don't have the time to do it.
Awesome. Take your time, the features you added already help a lot, the rest are just nice to haves. Thanks for helping and thanks for writing this software!
I am trying to get output from a G935. G935 is a headset that has buttons on the side which can be remapped in the Logitech software just like any other G-Key.
Unfortunately the newDeviceDebugger just throws an error:
same output for --info I also tested with my G815 which works without issues.
To me it seems like the G935 connects just like a keyboard since volume up and volume down "keypresses" are correctly being recognized in other software