g810-led icon indicating copy to clipboard operation
g810-led copied to clipboard

Supporting local characters

Open larsnaesbye opened this issue 8 years ago • 38 comments

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?

larsnaesbye avatar Nov 03 '16 07:11 larsnaesbye

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.

meisanerd avatar Nov 03 '16 15:11 meisanerd

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

larsnaesbye avatar Nov 03 '16 17:11 larsnaesbye

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...

MatMoul avatar Nov 03 '16 19:11 MatMoul

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.....

larsnaesbye avatar Nov 03 '16 22:11 larsnaesbye

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 avatar Nov 10 '16 16:11 meisanerd

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

meisanerd avatar Nov 10 '16 16:11 meisanerd

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

MatMoul avatar Nov 10 '16 19:11 MatMoul

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

larsnaesbye avatar Nov 11 '16 22:11 larsnaesbye

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

MatMoul avatar Nov 11 '16 22:11 MatMoul

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

larsnaesbye avatar Nov 11 '16 22:11 larsnaesbye

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.

obstbude avatar Nov 26 '16 12:11 obstbude

@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 avatar Nov 27 '16 16:11 MatMoul

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

MatMoul avatar Dec 13 '16 00:12 MatMoul

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.

noisycat avatar Dec 13 '16 07:12 noisycat

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";

meisanerd avatar Dec 13 '16 16:12 meisanerd

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

noisycat avatar Dec 13 '16 16:12 noisycat

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.

noisycat avatar Dec 13 '16 17:12 noisycat

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

meisanerd avatar Dec 13 '16 18:12 meisanerd

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.

noisycat avatar Dec 13 '16 18:12 noisycat

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

meisanerd avatar Dec 13 '16 18:12 meisanerd

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.

noisycat avatar Dec 13 '16 22:12 noisycat

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 avatar Dec 14 '16 23:12 MatMoul

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 :(

MatMoul avatar Dec 28 '16 21:12 MatMoul

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

larsnaesbye avatar Dec 30 '16 23:12 larsnaesbye

@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?

noisycat avatar Jan 05 '17 06:01 noisycat

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.

MohamadSaada avatar Feb 09 '17 18:02 MohamadSaada

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.

CReimer avatar Mar 11 '17 21:03 CReimer

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:

  • have one constant xmodmap -pke output for us keyboard
  • on first run, run xmodmap -pke for current layout (in my case, I tested it with croatian)
  • recognize the differences in layouts
  • query user to press keys that differe
  • save that differences for remaping
  • on key color change, see if the key is in remap keys

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.

spiritg9 avatar Oct 22 '17 11:10 spiritg9

@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.

MatMoul avatar Oct 22 '17 14:10 MatMoul

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.

Silver-Shroud avatar Feb 12 '18 16:02 Silver-Shroud