Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for G915 #25

Open
BrandonR541 opened this issue Mar 20, 2022 · 24 comments
Open

add support for G915 #25

BrandonR541 opened this issue Mar 20, 2022 · 24 comments
Labels
new device support for new device

Comments

@BrandonR541
Copy link

I am trying to setup a Logitech G915 Lightspeed keyboard. When I run newDeviceDebugger, it ends of failing and hanging, and the keyboard becomes non-operational until the wireless usb adapter is removed and reinserted. I believe it is a problem with the disableGKeys line, the byte code provided in the script for the G910 does not work, and I do not know where to find the proper code to add to the script. Below the terminal output from running newDeviceDebugger:

sudo python3 src/newDeviceDebugger.py

DEBUG: Searching for keyboard...
DEBUG: Keyboard found! :)
DEBUG: requesting USB endpoint...
DEBUG: check and detach kernel driver if active
INFO: starting service...
/home/brandon/Desktop/keyboard-center/src/newDeviceDebugger.py:122: DeprecationWarning: There is no current event loop
evLoop = asyncio.get_event_loop()
DEBUG: Using selector: EpollSelector
DEBUG: Connection using HIDAPI...
DEBUG: Sending sequence to disable G keys
ERROR: Task exception was never retrieved
future: <Task finished name='Task-1' coro=<usbListener() done, defined at /home/brandon/Desktop/keyboard-center/src/newDeviceDebugger.py:48> exception=HIDException('Broken pipe')>
Traceback (most recent call last):
File "/home/brandon/Desktop/keyboard-center/src/newDeviceDebugger.py", line 58, in usbListener
await disableGkeyMapping(disableGKeys)
File "/home/brandon/Desktop/keyboard-center/src/newDeviceDebugger.py", line 45, in disableGkeyMapping
hdev.write(data)
File "/home/brandon/Desktop/keyboard-center/src/lib/hid.py", line 163, in write
return self.__hidcall(hidapi.hid_write, self.__dev, data, len(data))
File "/home/brandon/Desktop/keyboard-center/src/lib/hid.py", line 154, in __hidcall
raise HIDException(err)
lib.hid.HIDException: Broken pipe

@zocker-160
Copy link
Owner

zocker-160 commented Mar 20, 2022

thank you for this report, please disable the disableGKeys by commenting out line 53 and 54 with # in the script

I am pretty sure that the G915 needs a different disable sequence and the one from the G910 will not work.

@BrandonR541
Copy link
Author

Commenting out lines 53 and 54 did not fix it.

In the gif you have showing how to contribute a keyboard, when you are pressing the g keys and getting byte codes displayed, you are typing G1 and then pressing G1, typing G2 then pressing it etc, but I am unable to actually type any letters, every button I press just reads out the two byte codes. I am also unable to press control-c for that reason, and if I use my mouse to close the console window, the keyboard does not work at all and the wireless adapter must be unplugged and plugged back in (keyboard power off does not work) for the keyboard to start working again.

How were you finding the byte codes for disableGKeys? I can send you the output of pressing any button.

@BrandonR541
Copy link
Author

BrandonR541 commented Mar 27, 2022

Here is the output from the furthest I was able to get. the keys were pressed in the order: G1 through G5, M1through M3, MR, Mediakeys Back, Pause, Forward, Mute, Volume up and down but I forget which was first. Pressing any other key on the keyboard will just result in more byte codes.
If it matters, the disableGKeys value used was the one provided for G910. Also, usbVendor = 0x046d and usbProduct = 0xc541. Lines 53 and 54 were commented out. The rest of the file was unchanged.

python3 src/newDeviceDebugger.py

DEBUG: Searching for keyboard...
DEBUG: Keyboard found! :)
DEBUG: requesting USB endpoint...
DEBUG: check and detach kernel driver if active
INFO: starting service...
/home/brandon/Desktop/keyboard-center/src/newDeviceDebugger.py:125: DeprecationWarning: There is no current event loop
evLoop = asyncio.get_event_loop()
DEBUG: Using selector: EpollSelector
DEBUG: listening to USB Interface (1, 0)
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
got data from keyboard: b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x03\xb6\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
got data from keyboard: b'\x03\xcd\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
got data from keyboard: b'\x03\xb5\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
got data from keyboard: b'\x03\xe2\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
got data from keyboard: b'\x03\xea\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
got data from keyboard: b'\x03\xea\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
got data from keyboard: b'\x03\xe9\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
got data from keyboard: b'\x03\xe9\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'

@zocker-160
Copy link
Owner

zocker-160 commented Mar 27, 2022

thanks a lot for this information, that is very useful. Would you mind posting your output of the --info command as explained in the readme?

From the looks of it, the keyboard seems to use the same USB endpoint for the G-keys and the "regular" keys, which would really suck (and explain why your keyboard becomes unusable when you run the script since it unhooks the kernel driver).

All the other keyboards use two separate endpoints which allows me to use the Linux kernel driver for the normal keys and hook keyboard-center into the G-keys endpoint.

How were you finding the byte codes for disableGKeys?

By reverse engineering the Windows driver.

@BrandonR541
Copy link
Author

BrandonR541 commented Mar 27, 2022

No problem, and thank you for the software! I'm glad I can help.

python3 src/newDeviceDebugger.py --info

DEBUG: Searching for keyboard...
DEBUG: Keyboard found! :)
DEBUG: requesting USB endpoint...
DEBUG: check and detach kernel driver if active
###
DEVICE ID 046d:c541 on Bus 001 Address 034 =================
bLength                :   0x12 (18 bytes)
bDescriptorType        :    0x1 Device
bcdUSB                 :  0x200 USB 2.0
bDeviceClass           :    0x0 Specified at interface
bDeviceSubClass        :    0x0
bDeviceProtocol        :    0x0
bMaxPacketSize0        :   0x40 (64 bytes)
idVendor               : 0x046d
idProduct              : 0xc541
bcdDevice              :  0x102 Device 1.02
iManufacturer          :    0x1 Logitech
iProduct               :    0x2 USB Receiver
iSerialNumber          :    0x0 
bNumConfigurations     :    0x1
CONFIGURATION 1: 98 mA ===================================
bLength              :    0x9 (9 bytes)
bDescriptorType      :    0x2 Configuration
wTotalLength         :   0x54 (84 bytes)
bNumInterfaces       :    0x3
bConfigurationValue  :    0x1
iConfiguration       :    0x4 MPR01.02_B0028
bmAttributes         :   0xa0 Bus Powered, Remote Wakeup
bMaxPower            :   0x31 (98 mA)
INTERFACE 0: Human Interface Device ====================
bLength            :    0x9 (9 bytes)
bDescriptorType    :    0x4 Interface
bInterfaceNumber   :    0x0
bAlternateSetting  :    0x0
bNumEndpoints      :    0x1
bInterfaceClass    :    0x3 Human Interface Device
bInterfaceSubClass :    0x1
bInterfaceProtocol :    0x2
iInterface         :    0x0
ENDPOINT 0x81: Interrupt IN ==========================
bLength          :    0x7 (7 bytes)
bDescriptorType  :    0x5 Endpoint
bEndpointAddress :   0x81 IN
bmAttributes     :    0x3 Interrupt
wMaxPacketSize   :   0x40 (64 bytes)
bInterval        :    0x1
INTERFACE 1: Human Interface Device ====================
bLength            :    0x9 (9 bytes)
bDescriptorType    :    0x4 Interface
bInterfaceNumber   :    0x1
bAlternateSetting  :    0x0
bNumEndpoints      :    0x1
bInterfaceClass    :    0x3 Human Interface Device
bInterfaceSubClass :    0x1
bInterfaceProtocol :    0x1
iInterface         :    0x0
ENDPOINT 0x82: Interrupt IN ==========================
bLength          :    0x7 (7 bytes)
bDescriptorType  :    0x5 Endpoint
bEndpointAddress :   0x82 IN
bmAttributes     :    0x3 Interrupt
wMaxPacketSize   :   0x40 (64 bytes)
bInterval        :    0x1
INTERFACE 2: Human Interface Device ====================
bLength            :    0x9 (9 bytes)
bDescriptorType    :    0x4 Interface
bInterfaceNumber   :    0x2
bAlternateSetting  :    0x0
bNumEndpoints      :    0x1
bInterfaceClass    :    0x3 Human Interface Device
bInterfaceSubClass :    0x0
bInterfaceProtocol :    0x0
iInterface         :    0x0
ENDPOINT 0x83: Interrupt IN ==========================
bLength          :    0x7 (7 bytes)
bDescriptorType  :    0x5 Endpoint
bEndpointAddress :   0x83 IN
bmAttributes     :    0x3 Interrupt
wMaxPacketSize   :   0x40 (64 bytes)
bInterval        :    0x1
###

The default G-key mappings in the Logitech software on a windows machine are just standard F1-F5 keys. There are options for commands like alt-tab and stuff, and things like mouse button clicks, but there is nothing that is outside of the standard keyboard and mouse buttons as far as I can tell. Maybe you could make use of the extended F keys, like F13+, as those are able to be mapped to the G keys, and most people would never use those anyways?

@BrandonR541
Copy link
Author

This page has a lot of useful information about the G915. There are multiple endpoints, and can work in wired vs wireless and stuff, something in this guys debugging efforts for another program may help with this?

keyleds/keyleds#47

@zocker-160
Copy link
Owner

sadly the discussion in keyleds is not very useful for me, since they are trying to control the LEDs, which all keyboards use a different USB endpoint for afaik.

IIRC when you plug you keyboard in directly via USB, then it should behave the same as a G815, but something is really weird in your output.

Can you please double check that your USB ID for the G915 is 046d:c541 (with lsusb)?
I cannot find it in any USB ID database and AFAIK when connecting directly it should have 046d:c33e...

Maybe you could make use of the extended F keys, like F13+, as those are able to be mapped to the G keys, and most people would never use those anyways?

All Logitech keyboards with GKeys have a default mapping, which for most of them is towards the FKeys (aka G1 maps to F1 etc).
This default mapping needs to be disabled first in order to make the Gkeys usable in the first place.

In order to do that, I need to send a specific command to the keyboard using the disableGKeys function. Once that is done, the keyboard will disable the mapping and start sending the raw values, which then I can use to map to other keys.

There is sadly no other way, I cannot map G1-G5 to F13-F20, because the keyboard will ignore any command as long as the default mapping is active.

One additional problem with the wireless keyboards like the G915 is, that (as it seems like) the detach kernel driver command does actually detach the driver for the USB receiver and not the keyboard itself rendering the keyboard unusable.

I would really love to implement support for as much keyboards as possible, but I can only do that when either someone tells me the byte commands I need to send to the keyboard or by getting my hands on one. Sadly G915 is a very expensive keyboard.

@Corionis
Copy link

Thanks for the long explanation. Now some of it makes more sense.

We worked on the G910 recently. I'm having serious issues, just haven't wanted to heap-on more problems. Once it starts working it works consistently and well. But getting it to work after having booted to Windows, then back to Linux Mint, has occasionally taken a lot of time and fooling around. Sometimes I just give up.

Those steps include powering-off everything - even the mobo at the power supply, unplugging the keyboard, and reinstalling Keyboard Center. Many times that doesn't work. Restarting Keyboard Center multiple times works, sometimes. Last night that didn't. So I watched a movie and 2-3 hours later another single restart of the KC service worked. Weird.

It's a little embarrassing given I've been working hardware and software since 1976. Cannot find a consistent technique or combination that makes any sense.

I would like to contribute a new wired Logitech G910 Orion Spark to your project.
This one: https://www.amazon.com/gp/product/B01GAONOAC
Will have it shipped directly to you.
Just need a name, address and possibly phone number for delivery in Germany.

@zocker-160
Copy link
Owner

@Corionis thanks a ton for you offer I highly appreciate it. I have not forgotten you and your issue with the G910.

That being said, I cannot accept your offer since I actually can get my hands on a G910 by borrowing it. I sadly didn't find the time to work on it yet :(.

As for the G915, that is a way harder problem to solve, because I currently don't know how I can access the raw data coming from the USB receiver without detaching the entire device.

@Corionis
Copy link

Alright. Glad there's a way. We'll figure it out over time. (I deleted the post with my email address).

@BrandonR541
Copy link
Author

BrandonR541 commented Mar 28, 2022

lsusb -v

Bus 001 Device 042: ID 046d:c541 Logitech, Inc. USB Receiver
Device Descriptor:
bLength                18
bDescriptorType         1
bcdUSB               2.00
bDeviceClass            0 
bDeviceSubClass         0 
bDeviceProtocol         0 
bMaxPacketSize0        64
idVendor           0x046d Logitech, Inc.
idProduct          0xc541 
bcdDevice            1.02
iManufacturer           1 Logitech
iProduct                2 USB Receiver
iSerial                 0 
bNumConfigurations      1
Configuration Descriptor:
bLength                 9
bDescriptorType         2
wTotalLength       0x0054
bNumInterfaces          3
bConfigurationValue     1
iConfiguration          4 MPR01.02_B0028
bmAttributes         0xa0
(Bus Powered)
Remote Wakeup
MaxPower               98mA
Interface Descriptor:
bLength                 9
bDescriptorType         4
bInterfaceNumber        0
bAlternateSetting       0
bNumEndpoints           1
bInterfaceClass         3 Human Interface Device
bInterfaceSubClass      1 Boot Interface Subclass
bInterfaceProtocol      2 Mouse
iInterface              0 
HID Device Descriptor:
bLength                 9
bDescriptorType        33
bcdHID               1.11
bCountryCode            0 Not supported
bNumDescriptors         1
bDescriptorType        34 Report
wDescriptorLength      83
Report Descriptors: 
** UNAVAILABLE **
Endpoint Descriptor:
bLength                 7
bDescriptorType         5
bEndpointAddress     0x81  EP 1 IN
bmAttributes            3
Transfer Type            Interrupt
Synch Type               None
Usage Type               Data
wMaxPacketSize     0x0040  1x 64 bytes
bInterval               1
Interface Descriptor:
bLength                 9
bDescriptorType         4
bInterfaceNumber        1
bAlternateSetting       0
bNumEndpoints           1
bInterfaceClass         3 Human Interface Device
bInterfaceSubClass      1 Boot Interface Subclass
bInterfaceProtocol      1 Keyboard
iInterface              0 
HID Device Descriptor:
bLength                 9
bDescriptorType        33
bcdHID               1.11
bCountryCode            0 Not supported
bNumDescriptors         1
bDescriptorType        34 Report
wDescriptorLength     133
Report Descriptors: 
** UNAVAILABLE **
Endpoint Descriptor:
bLength                 7
bDescriptorType         5
bEndpointAddress     0x82  EP 2 IN
bmAttributes            3
Transfer Type            Interrupt
Synch Type               None
Usage Type               Data
wMaxPacketSize     0x0040  1x 64 bytes
bInterval               1
Interface Descriptor:
bLength                 9
bDescriptorType         4
bInterfaceNumber        2
bAlternateSetting       0
bNumEndpoints           1
bInterfaceClass         3 Human Interface Device
bInterfaceSubClass      0 
bInterfaceProtocol      0 
iInterface              0 
HID Device Descriptor:
bLength                 9
bDescriptorType        33
bcdHID               1.11
bCountryCode            0 Not supported
bNumDescriptors         1
bDescriptorType        34 Report
wDescriptorLength      54
Report Descriptors: 
** UNAVAILABLE **
Endpoint Descriptor:
bLength                 7
bDescriptorType         5
bEndpointAddress     0x83  EP 3 IN
bmAttributes            3
Transfer Type            Interrupt
Synch Type               None
Usage Type               Data
wMaxPacketSize     0x0040  1x 64 bytes
bInterval               1
Device Status:     0x0000
(Bus Powered)

It seems like the program Solaar might have figured something out here. They have the ability to divert G keys, and to receive G key presses as G1 etc and not what they are mapped to, and this works for the 915. Solaar also displays information for both the lightspeed adapter and the keyboard itself.

Lightspeed Receiver

Path         : /dev/hidraw6
USB ID       : 046d:C541
Serial       : DAE2E430
  Firmware   : 01.02.B0028
  Bootloader : 01.27
  Other      : 89.37
Notifications: wireless
               software present

G915 Keyboard

Path         : None
Index        : 1
Wireless PID : 407C
Protocol     : HID++ 4.2
Polling rate : 8 ms (125Hz)
Serial       : 5C36E9BB
  Bootloader : BOT 77.02.B0039
  Other      : 
  Firmware   : MPK 09.03.B0041
  Other      : 
  Other      : 

solaar show

Lightspeed Receiver
Device path  : /dev/hidraw6
USB id       : 046d:C541
Serial       : DAE2E430
Firmware   : 01.02.B0028
Bootloader : 01.27
Other      : 89.37
Has 1 paired device(s) out of a maximum of 2.
Notifications: wireless, software present (0x000900)
Device activity counters: 1=230

1: G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD
Device path  : None
WPID         : 407C
Codename     : G915 KEYBOARD
Kind         : keyboard
Protocol     : HID++ 4.2
Polling rate : 8 ms (125Hz)
Serial number: 5C36E9BB
Model ID:      B354407CC33E
Unit ID:       5C36E9BB
Bootloader: BOT 77.02.B0039
Other:
Firmware: MPK 09.03.B0041
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 BOT 77.02.B0039 0000EC44D534
Firmware: Other
Firmware: Firmware MPK 09.03.B0041 407C3791543D
Firmware: Other
Firmware: Other
Unit ID: 5C36E9BB  Model ID: B354407CC33E  Transport IDs: {'btleid': 'B354', 'wpid': '407C', 'usbid': 'C33E'}
3: DEVICE NAME            {0005}
Name: G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD
Kind: keyboard
4: WIRELESS DEVICE STATUS {1D4B}
5: RESET                  {0020}
6: DEVICE FRIENDLY NAME   {0007}
Friendly Name: G915 KEYBOARD
7: BATTERY VOLTAGE        {1001}
Battery: 3959mV, discharging, 70.
8: CHANGE HOST            {1814}
Change Host        : 1:brandonpc
9: HOSTS INFO             {1815}
Host 0 (paired): brandonpc
Host 1 (unpaired):
10: RGB EFFECTS            {8071}
11: PER KEY LIGHTING V2    {8081}
12: REPROG CONTROLS V4     {1B04}
Key/Button Diversion (saved): {Host Switch Channel 1:Regular, Host Switch Channel 2:Regular}
Key/Button Diversion        : {Host Switch Channel 1:Regular, Host Switch Channel 2:Regular}
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): True
Divert G Keys        : False
18: MKEYS                  {8020}
M-Key LEDs (saved): {M1:True, M2:True, M3:True}
M-Key LEDs        : {M1:False, M2:False, M3:False}
19: MR                     {8030}
MR-Key LED (saved): True
MR-Key LED        : False
20: BRIGHTNESS CONTROL     {8040}
21: ONBOARD PROFILES       {8100}
Device Mode: Host
Onboard Profiles (saved): Disable
Onboard Profiles        : Disable
22: REPORT RATE            {8060}
Polling Rate (ms): 1
Polling Rate (ms) (saved): 1
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: 3959mV, discharging, 70.

I'll try things plugged in soon as well to see if that makes a difference.

@zocker-160
Copy link
Owner

oh thanks for the output, so the USB ID is for the receiver, which makes a lot of sense and sadly also means that my current approach will not work.

It seems like the program Solaar might have figured something out here.

Solaar is a very good idea, I did not think about that. I will have to check out how those guys are doing it.

@zocker-160 zocker-160 added the new device support for new device label Mar 28, 2022
@zocker-160 zocker-160 changed the title Keyboard Contribution Problem add support for G915 Mar 30, 2022
@zocker-160
Copy link
Owner

zocker-160 commented Mar 30, 2022

@BrandonR541 does the G915 map G1 to F1 etc by default? (Or any other key for that matter or do the G-keys just do "nothing"?)

@BrandonR541
Copy link
Author

Yes, the default mapping for the G915 is G1 to F1 etc. They can be set to "disabled" though.

@BrandonR541
Copy link
Author

This is the same output as my last post, but with the keyboard plugged in and not using the wireless adapter.

lsusb -v

Bus 003 Device 011: ID 046d:c33e Logitech, Inc. G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD
Device Descriptor:
bLength                18
bDescriptorType         1
bcdUSB               2.00
bDeviceClass            0 
bDeviceSubClass         0 
bDeviceProtocol         0 
bMaxPacketSize0        64
idVendor           0x046d Logitech, Inc.
idProduct          0xc33e 
bcdDevice            9.03
iManufacturer           1 Logitech
iProduct                2 G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD
iSerial                 3 5C36E9BB
bNumConfigurations      1
Configuration Descriptor:
bLength                 9
bDescriptorType         2
wTotalLength       0x0054
bNumInterfaces          3
bConfigurationValue     1
iConfiguration          4 MPK09.03_B0041
bmAttributes         0xe0
Self Powered
Remote Wakeup
MaxPower              500mA
Interface Descriptor:
bLength                 9
bDescriptorType         4
bInterfaceNumber        0
bAlternateSetting       0
bNumEndpoints           1
bInterfaceClass         3 Human Interface Device
bInterfaceSubClass      1 Boot Interface Subclass
bInterfaceProtocol      1 Keyboard
iInterface              0 
HID Device Descriptor:
bLength                 9
bDescriptorType        33
bcdHID               1.11
bCountryCode            0 Not supported
bNumDescriptors         1
bDescriptorType        34 Report
wDescriptorLength      67
Report Descriptors: 
** UNAVAILABLE **
Endpoint Descriptor:
bLength                 7
bDescriptorType         5
bEndpointAddress     0x81  EP 1 IN
bmAttributes            3
Transfer Type            Interrupt
Synch Type               None
Usage Type               Data
wMaxPacketSize     0x0040  1x 64 bytes
bInterval               1
Interface Descriptor:
bLength                 9
bDescriptorType         4
bInterfaceNumber        1
bAlternateSetting       0
bNumEndpoints           1
bInterfaceClass         3 Human Interface Device
bInterfaceSubClass      1 Boot Interface Subclass
bInterfaceProtocol      2 Mouse
iInterface              0 
HID Device Descriptor:
bLength                 9
bDescriptorType        33
bcdHID               1.11
bCountryCode            0 Not supported
bNumDescriptors         1
bDescriptorType        34 Report
wDescriptorLength     123
Report Descriptors: 
** UNAVAILABLE **
Endpoint Descriptor:
bLength                 7
bDescriptorType         5
bEndpointAddress     0x82  EP 2 IN
bmAttributes            3
Transfer Type            Interrupt
Synch Type               None
Usage Type               Data
wMaxPacketSize     0x0040  1x 64 bytes
bInterval               1
Interface Descriptor:
bLength                 9
bDescriptorType         4
bInterfaceNumber        2
bAlternateSetting       0
bNumEndpoints           1
bInterfaceClass         3 Human Interface Device
bInterfaceSubClass      0 
bInterfaceProtocol      0 
iInterface              0 
HID Device Descriptor:
bLength                 9
bDescriptorType        33
bcdHID               1.11
bCountryCode            0 Not supported
bNumDescriptors         1
bDescriptorType        34 Report
wDescriptorLength      54
Report Descriptors: 
** UNAVAILABLE **
Endpoint Descriptor:
bLength                 7
bDescriptorType         5
bEndpointAddress     0x83  EP 3 IN
bmAttributes            3
Transfer Type            Interrupt
Synch Type               None
Usage Type               Data
wMaxPacketSize     0x0040  1x 64 bytes
bInterval               1
Device Status:     0x0001
Self Powered

G915 Keyboard

Path         : /dev/hidraw6
Index        : 255
Product ID   : 046d:C33E
Protocol     : HID++ 4.2
Polling rate : 1 ms (1000Hz)
Serial       : 
Unit ID      : 5C36E9BB
  Bootloader : BOT 77.02.B0039
  Other      : 
  Firmware   : MPK 09.03.B0041
  Other      : 
  Other      : 
Notifications: (none)

solaar show

1: G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD
Device path  : /dev/hidraw6
USB id       : 046d:C33E
Codename     : G915
Kind         : ?
Protocol     : HID++ 4.2
Polling rate : 1 ms (1000Hz)
Serial number:
Model ID:      B354407CC33E
Unit ID:       5C36E9BB
Bootloader: BOT 77.02.B0039
Other:
Firmware: MPK 09.03.B0041
Other:
Other:
Supports 37 HID++ 2.0 features:
0: ROOT                   {0000}
1: FEATURE SET            {0001}
2: DEVICE FW VERSION      {0003}
Firmware: Bootloader BOT 77.02.B0039 0000EC44D534
Firmware: Other
Firmware: Firmware MPK 09.03.B0041 C33E3791543D
Firmware: Other
Firmware: Other
Unit ID: 5C36E9BB  Model ID: B354407CC33E  Transport IDs: {'btleid': 'B354', 'wpid': '407C', 'usbid': 'C33E'}
3: DEVICE NAME            {0005}
Name: G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD
Kind: keyboard
4: WIRELESS DEVICE STATUS {1D4B}
5: RESET                  {0020}
6: BATTERY VOLTAGE        {1001}
Battery: 3995mV, recharging, 80.
7: CHANGE HOST            {1814}
Change Host        : 1:brandonpc
8: HOSTS INFO             {1815}
Host 0 (paired): brandonpc
Host 1 (unpaired):
9: RGB EFFECTS            {8071}
10: PER KEY LIGHTING V2    {8081}
11: REPROG CONTROLS V4     {1B04}
Key/Button Diversion (saved): {Host Switch Channel 1:Regular, Host Switch Channel 2:Regular}
Key/Button Diversion        : {Host Switch Channel 1:Regular, Host Switch Channel 2:Regular}
12: REPORT HID USAGE       {1BC0}
13: ENCRYPTION             {4100}
14: KEYBOARD DISABLE BY USAGE {4522}
15: KEYBOARD LAYOUT 2      {4540}
16: GKEY                   {8010}
Divert G Keys (saved): True
Divert G Keys        : False
17: MKEYS                  {8020}
M-Key LEDs (saved): {M1:True, M2:True, M3:True}
M-Key LEDs        : {M1:False, M2:False, M3:False}
18: MR                     {8030}
MR-Key LED (saved): True
MR-Key LED        : False
19: BRIGHTNESS CONTROL     {8040}
20: ONBOARD PROFILES       {8100}
Device Mode: Host
Onboard Profiles (saved): Disable
Onboard Profiles        : Disable
21: REPORT RATE            {8060}
Polling Rate (ms): 1
Polling Rate (ms) (saved): 1
Polling Rate (ms)        : 1
22: DFUCONTROL SIGNED      {00C2}
23: DFU                    {00D0}
24: DEVICE RESET           {1802}   internal, hidden
25: unknown:1803           {1803}   internal, hidden
26: CONFIG DEVICE PROPS    {1806}   internal, hidden
27: unknown:1813           {1813}   internal, hidden
28: OOBSTATE               {1805}   internal, hidden
29: unknown:1830           {1830}   internal, hidden
30: unknown:1890           {1890}   internal, hidden
31: unknown:1891           {1891}   internal, hidden
32: unknown:18A1           {18A1}   internal, hidden
33: unknown:1E00           {1E00}   hidden
34: unknown:1EB0           {1EB0}   internal, hidden
35: unknown:1861           {1861}   internal, hidden
36: 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: 3995mV, recharging, 80.

@zocker-160
Copy link
Owner

Yes, the default mapping for the G915 is G1 to F1 etc. They can be set to "disabled" though.

how do you disable that? Does Solaar offer a function for that?

@zocker-160
Copy link
Owner

thank you for the lsusb output, this is what I originally expected to see with 046d:c33e

keyboard center should be able to work with the keyboard in the plugged in state

@BrandonR541
Copy link
Author

G key Disable Info

The G keys can be set to "Disabled" through the Logitech software on a windows machine.
Additionally, Solar can either let the G keys act as they normally would, or it can "Divert" them, which it describes as:

Makes G keys send GKEY HID++ notifications {which trigger Solaar rules, but are otherwise ignored). May also make M Keys and MR keys send HID++ notifications.

The Solaar rules are where you can set macros and shortcuts and stuff through a condition evaluations and actions. The conditions include key-presses, where it treats each G key as its own special thing, and not what it is set to such as F1 etc. The only other information I see is when you set a condition to keypress a G key, it also shows a code - G1 is 1001 G2 is 1002 etc. Other special things like Brightness Down is 00C7 Crown is 4600, stuff like that.

Wired Mode Information

With the keyboard plugged in and the device id set properly, this is the output:

python3 src/newDeviceDebugger.py

DEBUG: Searching for keyboard...
DEBUG: Keyboard found! :)
DEBUG: requesting USB endpoint...
DEBUG: check and detach kernel driver if active
INFO: starting service...
/home/brandon/Downloads/keyboard-center-master/src/newDeviceDebugger.py:118: DeprecationWarning: There is no current event loop
evLoop = asyncio.get_event_loop()
DEBUG: Using selector: EpollSelector
DEBUG: Connection using HIDAPI...
DEBUG: Sending sequence to disable G keys
ERROR: Task exception was never retrieved
future: <Task finished name='Task-1' coro=<usbListener() done, defined at /home/brandon/Downloads/keyboard-center-master/src/newDeviceDebugger.py:44> exception=HIDException('Broken pipe')>
Traceback (most recent call last):
File "/home/brandon/Downloads/keyboard-center-master/src/newDeviceDebugger.py", line 54, in usbListener
await disableGkeyMapping(disableGKeys)
File "/home/brandon/Downloads/keyboard-center-master/src/newDeviceDebugger.py", line 41, in disableGkeyMapping
hdev.write(data)
File "/home/brandon/Downloads/keyboard-center-master/src/lib/hid.py", line 163, in write
return self.__hidcall(hidapi.hid_write, self.__dev, data, len(data))
File "/home/brandon/Downloads/keyboard-center-master/src/lib/hid.py", line 154, in __hidcall
raise HIDException(err)
lib.hid.HIDException: Broken pipe

With lines 53 and 54 commented out again, this is what I get:

python3 src/newDeviceDebugger.py

DEBUG: Searching for keyboard...
DEBUG: Keyboard found! :)
DEBUG: requesting USB endpoint...
DEBUG: check and detach kernel driver if active
INFO: starting service...
/home/brandon/Downloads/keyboard-center-master/src/newDeviceDebugger.py:118: DeprecationWarning: There is no current event loop
evLoop = asyncio.get_event_loop()
DEBUG: Using selector: EpollSelector
DEBUG: listening to USB Interface (1, 0)
G1
^[OP
G2
^[OQ
G3
^[OR
G4
^[OS
G5
^[[15~
M1
got data from keyboard: b'\x02\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
M2
got data from keyboard: b'\x02\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
M3
got data from keyboard: b'\x02\x00\x00\x00\x00\x00\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
MR


Media Back
got data from keyboard: b'\x03\xb6\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
Media Play/Pause
got data from keyboard: b'\x03\xcd\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
Media Forward
got data from keyboard: b'\x03\xb5\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
Media Mute
got data from keyboard: b'\x03\xe2\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
Volume Up
got data from keyboard: b'\x03\xe9\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
Volume Down
got data from keyboard: b'\x03\xea\x00\x00\x00'
got data from keyboard: b'\x03\x00\x00\x00\x00'
^CINFO: stopping...

Note:
Changing between onboard mode or standard mode changes the output. With onboard mode enabled, the output above is given. When onboard mode is turned off, the G and M keys no longer register anything, no bytecodes and not even any of those weird character outputs.

@zocker-160
Copy link
Owner

@BrandonR541 thanks for the output, I updated the debugger scipt, could you please pull the repo and run the the debugger script again with elevated permissions (aka sudo)?

I think the error you are seeing in the first output is because of lacking permissions, because you don't have the udev rules set.

@BrandonR541
Copy link
Author

BrandonR541 commented Mar 30, 2022

After running the new version, I am still getting errors, with and without sudo.

sudo python3 src/newDeviceDebugger.py

DEBUG: Searching for keyboard...
DEBUG: Keyboard found! :)
DEBUG: requesting USB endpoint...
DEBUG: HIDraw read endpoint found: /dev/hidraw4
DEBUG: HIDraw disable endpoint found: /dev/hidraw4
DEBUG: HIDraw read endpoint found: /dev/hidraw4
DEBUG: HIDraw disable endpoint found: /dev/hidraw4
DEBUG: HIDraw read endpoint found: /dev/hidraw4
DEBUG: HIDraw disable endpoint found: /dev/hidraw4
DEBUG: HIDraw read endpoint found: /dev/hidraw4
DEBUG: HIDraw disable endpoint found: /dev/hidraw4
DEBUG: Checking for HID availability...
DEBUG: Connected to /dev/hidraw4
INFO: starting listener...
/home/brandon/.local/share/Trash/files/keyboard-center-master (2)/src/newDeviceDebugger.py:181: DeprecationWarning: There is no current event loop
evLoop = asyncio.get_event_loop()
DEBUG: Using selector: EpollSelector
DEBUG: Connection using HIDAPI...
DEBUG: Sending sequence to disable G keys
0: b'\x11\x01\x11\x1a\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
ERROR: Task exception was never retrieved
future: <Task finished name='Task-1' coro=<usbListener() done, defined at /home/brandon/.local/share/Trash/files/keyboard-center-master (2)/src/newDeviceDebugger.py:109> exception=HIDException('Broken pipe')>
Traceback (most recent call last):
File "/home/brandon/.local/share/Trash/files/keyboard-center-master (2)/src/newDeviceDebugger.py", line 118, in usbListener
await disableGkeyMapping(HIDpathDisable)
File "/home/brandon/.local/share/Trash/files/keyboard-center-master (2)/src/newDeviceDebugger.py", line 102, in disableGkeyMapping
hdev.write(data)
File "/home/brandon/.local/share/Trash/files/keyboard-center-master (2)/src/lib/hid.py", line 163, in write
return self.__hidcall(hidapi.hid_write, self.__dev, data, len(data))
File "/home/brandon/.local/share/Trash/files/keyboard-center-master (2)/src/lib/hid.py", line 154, in __hidcall
raise HIDException(err)
lib.hid.HIDException: Broken pipe
^CINFO: stopping...

I also tried commenting out the same lines as before again (now 117 and 118) but that did not change anything.

Is there something I should add to udev rules?

running evtest shows the G915 as several devices, and each one has a different set of keys and stuff. Could those outputs be useful?

evtest

No device specified, trying to scan all of /dev/input/event*
Not running as root, no devices may be available.
Available devices:
/dev/input/event19:     input-remapper gamepad
/dev/input/event20:     Logitech G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD
/dev/input/event22:     Logitech G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD Mouse
/dev/input/event23:     Logitech G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD Consumer Control
/dev/input/event24:     Logitech G915 WIRELESS RGB MECHANICAL GAMING KEYBOARD System Control
/dev/input/event26:     py-evdev-uinput
Select the device event number [0-26]:

@zocker-160
Copy link
Owner

The broken pipe error and DeprecationWarning: There is no current event loop worry me, they should not happen.

Is there something I should add to udev rules?

If you run as sudo you don't need any udev rules.

running evtest shows the G915 as several devices, and each one has a different set of keys and stuff. Could those outputs be useful?

Sadly not really, because all keyboards have multiple event groups for a specific group of keys, so this is expected.

Could you tell me your python and kernel version pls?

@BrandonR541
Copy link
Author

python --version
Python 3.10.2
uname -r
5.14.2.21.realtime1-1-rt

Would it help to try running on a clean install, like a live usb? I could also give you remote access in that case if it would help

@zocker-160
Copy link
Owner

so weird, both your Python and Kernel version are supported, so I really wonder why those errors are happening.

I will check how Solaar is talking to the keyboard, maybe I can learn something from that. If I cannot get my hands on a G915, then remote access to a linux VM / live system would be a great alternative.

Sadly I don't think I will have time for that any time soon though. :(

@BrandonR541
Copy link
Author

I have installed a lot of stuff trying different keyboard mapping and led things, so maybe there is a conflict somewhere, I'll try things out on a fresh install at some point just in case.

No worries about the timeline, I'm not in a rush, but yeah at some point in the future if you think remote access could help just let me know. I also have a windows machine if there is anything else that would be helpful on there.

Thanks for all the effort to make this work, I really appreciate it, and thanks for creating the software regardless of getting the G915 to work!

@zocker-160 zocker-160 mentioned this issue Jul 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new device support for new device
Projects
None yet
Development

No branches or pull requests

3 participants