MatMoul / g810-led

Linux led controller for Logitech G213, G410, G413, G512, G513, G610, G810, g815, G910 and GPRO Keyboards
GNU General Public License v3.0
1.38k stars 183 forks source link

Supporting local characters #16

Open larsnaesbye opened 7 years ago

larsnaesbye commented 7 years ago

I'd like to be able to set the color of the keys of my Nordic keyboard (I'm Danish, so I use 'æ', 'ø', and 'å' a lot. However, I have to specify other keynames to set those keys.

My wish is to be able to specify, e.g. g810-led -k æ ff0000

I'd like to help by writing and testing the actual code, but thought it might be good to discuss how to generalise this best. Can we get the key mapping for a character from the driver, for example?

meisanerd commented 7 years ago

There was just a discussion regarding this a few days ago, and it appears that Logitech doesn't actually make it easy/possible to distinguish between the different keyboard layouts. What likely needs to be done is that we need some way of telling the software what keyboard layout is being used, and set up the key mapping based on that.

larsnaesbye commented 7 years ago

Yes, I thought perhaps this could be derived from the OS?

MatMoul commented 7 years ago

At this time, I don't have idea how handle this... Make an argument but it's not very usefull and need a full mapping table. If I can found the keymap from USB infos and not OS, it's a possible way...

larsnaesbye commented 7 years ago

So the quick fix is to just add them to the list as aliases?

Or if we can detect the variant by any means, we could map according to that.....

meisanerd commented 7 years ago

The problem I see with aliases is that there are keys that are shared across the layouts, but have (as far as I know) different internal IDs (such as the - key, in US it is up in the number row, in the FR layout it is near the right shift key). Without knowing which layout is specifically being used, how would we handle the key name.

I am thinking that we could just default to US as we do now, but provide a flag that triggers the aliases based on the layout. It wouldn't be as clean as what is currently in place, but it would allow for localization. Basically, we would just add some code at the top of Keyboard::parseKey that does something like if(layout != "US" && (key == "minus" || key == "-")) key = "slash"; and then add a -layout=X command line option

meisanerd commented 7 years ago

Also, if this helps for automated parsing, the full output from lsusb for my keyboard is as follows (maybe we can find some difference between US and QWERTZ...)

lsusb -v -d 046d:c331

Bus 001 Device 005: ID 046d:c331 Logitech, Inc. 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00                                                                                        
  bDeviceClass            0                                                                                        
  bDeviceSubClass         0                                                                                        
  bDeviceProtocol         0                                                                                        
  bMaxPacketSize0        64                                                                                        
  idVendor           0x046d Logitech, Inc.
  idProduct          0xc331 
  bcdDevice            2.00
  iManufacturer           1 Logitech
  iProduct                2 Gaming Keyboard G810
  iSerial                 3 036635553130
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           59
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          4 U102.00_B0014
    bmAttributes         0xa0
      (Bus 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      65
         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     0x0008  1x 8 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      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     119
         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
MatMoul commented 7 years ago

Diff from my CH keyboard :

bcdDevice 2.00 bcdDevice 2.03 iSerial 3 036635553130 iSerial 3 0287355D3938 iConfiguration 4 U102.00_B0014 iConfiguration 4 U102.03_B0027

larsnaesbye commented 7 years ago

Diff from my Nordic keyboard:

bcdDevice 2.00 bcdDevice 2.03 iSerial 3 036635553130 iSerial 3 118735743830 iConfiguration 4 U102.00_B0014 iConfiguration 4 U102.03_B0027

So we have three different iSerial #:

Nordic: 3 118735743830 Swiss: 3 0287355D3938 US (?): 3 036635553130

MatMoul commented 7 years ago

iSerial must be unique for each keyboard ... bcdDevice seem to be the firmware version iConfiguration seem related to firmware version to.

larsnaesbye commented 7 years ago

Yeah, so I guess @meisanerd has the best idea for now: a layoutparameter....

obstbude commented 7 years ago

Mappingtable for German QWERTZ 105 key layout (Diffrences only).

Name Symbol German Layout Symbol
tilde ~ Zirkumflex ^
minus - Fragezeichen ?
equal = Gravis `
open_bracket [ Ue Ü
close_bracket ] Plus +
semicolon ; Oe Ö
quote ' Ae Ä
dollar $ Raute #
intl_backslash \ Pipe |
slash / Minus -
num_period . Numpad Komma ,

May you could add it to your project wiki.

MatMoul commented 7 years ago

@addictedtoberlin Thank for the mapping table. Wiki is a possible way but it's best to have access from the command line. I will try to find a good solution, just need time.

MatMoul commented 7 years ago

It seems that there are only three options ... A parameter, use of system keymap or make a help page for keymap The three options require mapping table What is the best way ??? Need to find a keymap strategy

noisycat commented 7 years ago

Based on the logitech LED SDK that was released and the python wrappers that were released with them, we should keep the base characters consistent with the english model - and provide aliases for hem them. If we have to, we can add separate 'layout' command line arguments.

There are several ways to detect keyboards, but I think that's possibly a much longer term fix, as it requires more research.

I would suggest a g810-led/layouts subdirectory, with layouts/.csv for aliasing. That way providing new layouts or customizing your own aliases doesn't require any actual code changes.

meisanerd commented 7 years ago

We could use setxkbmap to detect the current layout, and use that. We would then just have to map out all of the possible layouts and add them one at a time. Having a layout parameter to manually override that wouldn't be a bad idea either, and the support code would all be the same.

Here is a code sample that I found that should give us the detection code: http://cboard.cprogramming.com/linux-programming/169388-detect-keyboard-layout-linux.html#post1248447

Once we have that in place and working it should be a simple matter to just set up aliases in the parseKey function. Something like: if(KBD_LAYOUT=="quertz" && key == "zirkumflex") key = "tilde";

noisycat commented 7 years ago

I absolutely don't think we should drag x11 utilities into this.

noisycat commented 7 years ago

Upon further research, there's two possibilities I'd like to look further into:

1) Some of the 'unavailable' information in the text output provided by lsusb might have actual data in it if we try and parse it ourselves. I would hope for a product number akin to what's in the following point. I'll try and look into the unavailable data fields later this week to see if they spit something out. 2) the logitech product numbers - which should be per version that they sell. They may not be readily available from the lsusb, but the consumers should know them fairly easily. I tried to just get a dump of the available layouts for the g810, but logitech will only show me the English version >.> (Black, English: 920-007739)

(2) still winds up requiring us to provide layouts. Which is fine - but it does mean that people who want their layout included are going to need to commit that file.

meisanerd commented 7 years ago

As per the lsusb dump and comparison above, the only differences we found between the keyboards were the serial number and the firmware version. The physical layout does not appear to be defined by Logitech at all, which is why we are looking for alternate solutions.

My suggestion to try to parse the output from setxkbmap was so that we don't have to ask the user to specify the layout or model number, it would just attempt to detect it on its own. If done properly, there would be no hard requirement for x11 utilities, but it would simplify user setup if they did happen to already have it installed. I figure x11 is a better option than Gnome/KDE/XFCE/whatever as it will likely be in place for the majority of the users.

For reference, the product number on my G810 is 820-007620

noisycat commented 7 years ago

I understand that point meisanerd - but my point is that the data like this:

     wDescriptorLength      65
   Report Descriptors: 
    ** UNAVAILABLE **

is unrendered possibly because there's no specific format for it (and just dumping hex to screen would be... bad). We might find model in there. Or we just have people look at the back of their boards. This configuration pattern:

iConfiguration 4 U102.03_B0027

is in the format U(FIRMWARE)_B(M/N #), where you can find the M/N# on the back faceplate of your keyboard.

e.g. http://cdn.gamer-network.net/2016/usgamer/Logitech-G810-Shot-07.jpg

We do not need to bring in x11, or any of the other options, when the majority of users would be better served by just manually reporting their need to the interface we're writing. You do not want the resulting dependency chain and build hell and problem reports that are generated from linking to these software packages. But that's just my opinion.

meisanerd commented 7 years ago

I am not sure that the iConfiguration is in that format, as my M/N is Y-U0027, but the iConfiguration value is U102.00_B0014

Also, if we use the code I linked above, there is no dependency upon x11. What it does is attempts to execute the x11 app and parse the return value. If the app is not installed, there would be nothing to parse, and it would fall back to other methods or the default layout. I am just trying to make it simpler for the general public to be able to use this, so they don't have to go digging through code and do special defines. The best option (in my opinion) is to make it easy enough that they can go into their package manager, install the G810 driver package, and have their keyboard work using their local layout.

I have re-run lsusb with the keyboard unbound to get the values for those Report Descriptors. Here is the output:

lsusb -v -d 046d:c331

Bus 001 Device 004: ID 046d:c331 Logitech, Inc. 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x046d Logitech, Inc.
  idProduct          0xc331 
  bcdDevice            2.00
  iManufacturer           1 Logitech
  iProduct                2 Gaming Keyboard G810
  iSerial                 3 036635553130
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           59
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          4 U102.00_B0014
    bmAttributes         0xa0
      (Bus 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      65
          Report Descriptor: (length is 65)
            Item(Global): Usage Page, data= [ 0x01 ] 1
                            Generic Desktop Controls
            Item(Local ): Usage, data= [ 0x06 ] 6
                            Keyboard
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Global): Usage Page, data= [ 0x07 ] 7
                            Keyboard
            Item(Local ): Usage Minimum, data= [ 0xe0 ] 224
                            Control Left
            Item(Local ): Usage Maximum, data= [ 0xe7 ] 231
                            GUI Right
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x08 ] 8
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Main  ): Input, data= [ 0x01 ] 1
                            Constant Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x03 ] 3
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Global): Usage Page, data= [ 0x08 ] 8
                            LEDs
            Item(Local ): Usage Minimum, data= [ 0x01 ] 1
                            NumLock
            Item(Local ): Usage Maximum, data= [ 0x03 ] 3
                            Scroll Lock
            Item(Main  ): Output, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x05 ] 5
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Main  ): Output, data= [ 0x01 ] 1
                            Constant Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x06 ] 6
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Usage Page, data= [ 0x07 ] 7
                            Keyboard
            Item(Local ): Usage Minimum, data= [ 0x00 ] 0
                            No Event
            Item(Local ): Usage Maximum, data= [ 0xff 0x00 ] 255
                            (null)
            Item(Main  ): Input, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0008  1x 8 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      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     119
          Report Descriptor: (length is 119)
            Item(Global): Usage Page, data= [ 0x01 ] 1
                            Generic Desktop Controls
            Item(Local ): Usage, data= [ 0x06 ] 6
                            Keyboard
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Global): Usage Page, data= [ 0x07 ] 7
                            Keyboard
            Item(Local ): Usage Minimum, data= [ 0x00 ] 0
                            No Event
            Item(Local ): Usage Maximum, data= [ 0xe7 ] 231
                            GUI Right
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xe7 0x00 ] 231
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x14 ] 20
            Item(Global): Report ID, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Global): Usage Page, data= [ 0x0c ] 12
                            Consumer
            Item(Local ): Usage, data= [ 0x01 ] 1
                            Consumer Control
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Global): Report ID, data= [ 0x02 ] 2
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0x01 ] 1
            Item(Global): Report Size, data= [ 0x01 ] 1
            Item(Global): Report Count, data= [ 0x07 ] 7
            Item(Local ): Usage, data= [ 0xb5 ] 181
                            Scan Next Track
            Item(Local ): Usage, data= [ 0xb6 ] 182
                            Scan Previous Track
            Item(Local ): Usage, data= [ 0xb7 ] 183
                            Stop
            Item(Local ): Usage, data= [ 0xcd ] 205
                            Play/Pause
            Item(Local ): Usage, data= [ 0xe9 ] 233
                            Volume Increment
            Item(Local ): Usage, data= [ 0xea ] 234
                            Volume Decrement
            Item(Local ): Usage, data= [ 0xe2 ] 226
                            Mute
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Global): Report Count, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x01 ] 1
                            Constant Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Global): Usage Page, data= [ 0x43 0xff ] 65347
                            (null)
            Item(Local ): Usage, data= [ 0x02 0x06 ] 1538
                            (null)
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Global): Report ID, data= [ 0x11 ] 17
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x13 ] 19
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Local ): Usage, data= [ 0x02 ] 2
                            (null)
            Item(Main  ): Input, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x02 ] 2
                            (null)
            Item(Main  ): Output, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
            Item(Global): Usage Page, data= [ 0x43 0xff ] 65347
                            (null)
            Item(Local ): Usage, data= [ 0x04 0x06 ] 1540
                            (null)
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Global): Report ID, data= [ 0x12 ] 18
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x3f ] 63
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Local ): Usage, data= [ 0x04 ] 4
                            (null)
            Item(Main  ): Input, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x04 ] 4
                            (null)
            Item(Main  ): Output, data= [ 0x00 ] 0
                            Data Array Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
      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
noisycat commented 7 years ago

The proper example you posted has quite a bit of dependency on X11. The first listed (using popen) is a huge security risk given that I run this command with sudo, as do many others - especially those that aren't allowed to use systemd / udev commands thanks to security protocols at their installations. If the group decides to go with that, then let it be known.

Thanks for the extended report.

MatMoul commented 7 years ago

Another problem that should not be forgotten is the profile files A possibility is to add a line that define charset of the file

MatMoul commented 7 years ago

Very hard to find a solution, we need a full keymap for all key of the keyboard... You can have QWERTY, QWERTZ, AZERTY, .... all keys can be impacted :(

larsnaesbye commented 7 years ago

I think the profile file is a good place to put this. How often does one change keyboard?

noisycat commented 7 years ago

@MatMoul it's probably best to keep this to physical key identifiers and not worry about what people are calling their own keys - people can submit images of their keyboard physical layouts and appropriate key translations, and we can build profile style files out of that?

MohamadSaada commented 7 years ago

Hi all, sorry for bothering you today, I was looking through the Logitech files and I found this:

{
    "Logitech.Gaming.Keyboard.G710" : 
    {
        "default" : "INTL",
        "US" : "0x0409",
        "DEU" : "0x0407",
        "UK" : "0x0809",
        "RU" : "0x0419",
        "FRA" : "0x040c",
        "SW" : 
        [       
            "0x040c100c",
            "0x100c100c",
            "0x04070807",
            "0x08070807"
        ],
        "TUR" : "0x041f",
        "NORDIC" :
        [
            "0x0406",
            "0x0414",
            "0x0814",
            "0x041d",
            "0x040b"
        ],
        "KOR" : "0x0412",
        "JPN" : "0x0411",
        "CHT" : "0x0404"
    },
    "Logitech.Gaming.Keyboard.G510s" : 
    {
        "default" : "INTL",
        "US" : "0x0409",
        "DEU" : "0x0407",
        "UK" : "0x0809",
        "RU" : "0x0419",
        "FRA" : "0x040c",
        "SW" : 
        [       
            "0x040c100c",
            "0x100c100c",
            "0x04070807",
            "0x08070807"
        ],
        "TUR" : "0x041f",
        "NORDIC" :
        [
            "0x0406",
            "0x0414",
            "0x0814",
            "0x041d",
            "0x040b"
        ],
        "KOR" : "0x0412",
        "JPN" : "0x0411",
        "CHT" : "0x0404"
    },
    "Logitech.Gaming.Keyboard.G19s" : 
    {
        "default" : "INTL",
        "US" : "0x0409",
        "DEU" : "0x0407",
        "UK" : "0x0809",
        "RU" : "0x0419",
        "FRA" : "0x040c",
        "SW" : 
        [       
            "0x040c100c",
            "0x100c100c",
            "0x04070807",
            "0x08070807"
        ],
        "TUR" : "0x041f",
        "NORDIC" :
        [
            "0x0406",
            "0x0414",
            "0x0814",
            "0x041d",
            "0x040b"
        ],
        "KOR" : "0x0412",
        "JPN" : "0x0411",
        "CHT" : "0x0404"
    },
    "Logitech.Gaming.Keyboard.G105" : 
    {
        "default" : "INTL",
        "US" : "0x0409",
        "DEU" : "0x0407",
        "UK" : "0x0809",
        "RU" : "0x0419",
        "FRA" : "0x040c",
        "SW" : 
        [       
            "0x040c100c",
            "0x100c100c",
            "0x04070807",
            "0x08070807"
        ],
        "TUR" : "0x041f",
        "NORDIC" :
        [
            "0x0406",
            "0x0414",
            "0x0814",
            "0x041d",
            "0x040b"
        ],
        "KOR" : "0x0412",
        "JPN" : "0x0411",
        "CHT" : "0x0404"
    },
    "Logitech.Gaming.Devio.Keyboard" : 
    {
        "default" : "INTL",
        "US" : "0x01",
        "INTL" : "0x02",
        "UK" : "0x03",
        "DEU" : "0x04",
        "FRA" : "0x05",
        "RU" : "0x07",
        "NORDIC" : "0x08",
        "KOR" : "0x09",
        "JPN" : "0x0a",
        "CHT" : "0x0b",
        "SW" : "0x0d",
        "TUR" : "0x0e",
        "ESP": "0x0f",
        "THAI" : "0x33",
        "INTL2" : "0x37"
    }
}

I think the last one Logitech.Gaming.Devio.Keyboard is the one we should focus on, another thing is that when tracing the whireshark dumps, there is no trace of the serial number, I'm still scratching my head and trying to figure out how the Logitech Software detects the layout within these few first calls with the keyboard. without getting the serial number. I still think that the serial number is our best choice to discover the layout, or maybe I'm wrong.

Anyways I've added my serial to the other three serials I found up here, in the hope that someone will have a eureka moment and figure it all out.

107D35743231 0x03 UK 118735743830 0x08 Nordic 0287355D3938 0x0d Swiss 036635553130 0x01 US (Not sure)

if anyone else can provide his/her serial, that would be great.

CReimer commented 7 years ago

I don't think that the serial is the key to all this. But here's the serial number of my German G910 107035573737

In my wireshark dumps is a "GET DESCRIPTOR Response CONFIGURATION" with an iConfiguration of 4. That would fit the list @MohamadSaada provided.

spiritg9 commented 6 years ago

Hello everyone,

I am not very good with c++ so I created my python frontend. As I saw this issue I come up with one idea and coded it for my python fronted.

Basically, idea is:

My code is here https://github.com/spiritg9/g810-led-python-frontend when you git clone repository, you can try this and test with running first run: ./keyboard.py diff after that try for example: ./keyboard.py key č ff0000 where č is your layout key (without shift, small caps)

If you like the idea, ti would be great if somebody would acctually code it for g810-led original project, I would be glad to help with that.

MatMoul commented 6 years ago

@spiritg9 Thanks for your return but xmodmap is dependent of xorg and g810-led must not have this dependency... Currently, g810-led run in ~60ms and I try to maintain this speed.

Silver-Shroud commented 6 years ago

I'm really new to this kind of thing and I have the Japanese "Logicool" G810 QWERTY keyboard which not only has a different key layout, but also has 5 additional keys. If someone could give me a simple tutorial to assist me in giving the information required, I would very much appreciate it.

MatMoul commented 6 years ago

@Kakashi-sensei Thanks for your return but open a new issue for this. Supporting new keys is not a local char problem.

Silver-Shroud commented 6 years ago

How can I help support my keyboard, then?

MatMoul commented 6 years ago

@Kakashi-sensei Firstly open a new issue for your keyboard and provide a photo of it.

mazunki commented 5 years ago

I suggest messing around with std input/std output, during installation, and/or through a proper script to remap a dictionary. Knowing what keys are pressed, by Logitech's keyboard format/layout, the script can pipe (by faking a keypress, in a predefined order) each of these into a dictionary. Use this dictionary to know what key is asked for.

mazunki commented 5 years ago

showkey is also an interesting command, it shows keycodes for (all) keys pressed.

MatMoul commented 5 years ago

@mazunki Thanks for your feedback... Creating dictionaries seems way too tedious ... Using the Keymap seems a good solution but I don't know yet how deal with it ... showkey seems to be doing the job but I can not use an external binary. I'll study how showkey works and see if there isn't a lib ...

dioni21 commented 4 years ago

I've just found this, searching for solutions to my ABNT G512 Carbon. I already a PR proposal, will submit it soon.

But adding to this discussion on "How to name" keys, maybe we could simply have a scan code and/or logitech code hexa mapping. It would have done my job easier.

In my case, I needed to control the extra / key on ABNT keyboards. I found from wireshark that it's scancode is 0x87, and from internet that this code is also used in Japanese keyboards, for key -

What about simply an option like -s <usb_scan_code> or -c <logitech key code>? We may need an option to select group also...

dioni21 commented 3 years ago

FYI: https://github.com/MatMoul/g810-led/pull/241