Open braoult opened 5 years ago
Hey,
you really went to great lengths to investigate the issue. I really appreciate it.
Currently the GKeys can't be used in combinations (G1+G2...) because the keyboard returns different hex values. As you can see here command_bytearray.py, every GKey is maped to a unique hex byte array. But when you press multiple GKeys or press and hold G1 and then press G2 the keyboard returns a completely different hex byte array. This is probably because it merges the two hex codes from G1 and G2 together (my guess is it does some kind of boolean operation on them).
Because of this behavior the driver currently simply drops the hex code it receives because it does not know what to do with it. Implementing the decoding will be quite tedious but I hope I will find some time to code it in when I figure out how the Gkeys are actually merged. (Nothing is easy with Logitech on Linux :P)
So I just found this project (which is awesome) and I saw this issue.
Doing a very simple check of command_bytearray.py
(literally converting everything to pure hex and adding spaces), this operation would appear (emphasis here) to be extremely straightforward:
# import binascii
# spaces added below
b'11 ff 08 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['g1'])
b'11 ff 08 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['g2'])
b'11 ff 08 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['g3'])
b'11 ff 08 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['g4'])
b'11 ff 08 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['g5'])
b'11 ff 08 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['g6'])
b'11 ff 08 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['g7'])
b'11 ff 08 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['g8'])
b'11 ff 08 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['g9'])
b'11 ff 09 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['m1'])
b'11 ff 09 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['m2'])
b'11 ff 09 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['m3'])
b'11 ff 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['m1-3_key_release'])
b'11 ff 0a 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['mr'])
b'11 ff 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' # >>> binascii.hexlify(commands['mr-key_release'])
Basically, at least for the Gx
keys, they always have the first three bytes as 0x11ff08
. Beyond that, each of the G keys has exactly one bit set, and that bit is unique among all of the Gx
keys. The obvious conclusion from this is that the Gx
keys are signaled this way so that they can be 'OR'ed together when pressed in unison, and can be used as a mask to distinguish the combination of keys pressed.
Note I'm not sure how this would work for a Gx
key and a normal key at the same time, but my guess would be that the byte sent by the normal key is 'OR'ed with a one of the 0x00
bytes in the bytearray
.
For the Mx
keys and the MR
key, since there is a release value, my guess is that these aren't combined at all (though the Mx
keys could be combined with each other). For Mx
when a bytearray
begins with 0x11ff09
, this is a signal to set a register indicating which (if any) Mx
keys are active. The value of the register becomes the bits that follow. This fits into the idea that the release key for M1
through M3
turns off all of those bits. Similarly, MR
would seem to be the same, but with just one key that is set to either 1
or 0
.
I'm going to try this out when I get a chance, unless someone else wants to. I'll report back.
Oh. It looks like someone in #32 already determined the values of the actual arrays produced from the key combos. I just combined it what I did, and it seems to be 'OR'ing it. I'll see if I can make a simple PR.
If it's of any use, code I used is attached. gkeycombos.rb.txt
Hi,
I want to use G5 a an "Hyper" Key, and all other keys G-keys defined as F-key (F13...F21). My main point is that I prefer to manage G-keys at application-level. Note: Below was tested on XUbuntu 18.04.
I added in char_uinput_mapper.py :
My /etc/g910-gkeys/config.json contains the mapping of G1-G9 to F13-F21 (please see the comment for G8) :
I have added in my ~.Xmodmap :
So far so good, the
hyper
modifier works (tested under Emacs):G5-c
is seen asHyper-c
, etc...G5+CTRL+Windows+ALT+SHIFT-f
is seen asctrl-meta-super-hyper-shift-f
.For other g-keys (except G8/F20), I can also use ctrl-g1, shift-g1, meta-g1, ctrl+super+g1 etc, who return the correct codes (ctrl-F13, etc...).
The issue is for the "hyper" modifier (G5), when used with another G-KEY. G5-G1 should return "Hyper-F13". It returns nothing. More interesting: When used with another modifier (let say control), nothing is returned too: ctrl-G5-G1, shift-G5-G1 etc... do not work.
Hope this will help,
br.