8 Sep 2014

Logitech G600 in (Arch-)Linux

I like optimizing my workflow and therefore I like potent input devices!

I use the Logitech G600 mouse and it offers an insane amount of buttons. But how do you make use of those in Linux?

If you want to make use of the G-shift functionality and to improve the further configuration-experience, you should (sadly) plug this mouse into a windows machine with the Logitech software installed. Here you are able to define three profiles, which are stored internally in the mouse.
You should start by choosing cool colours for the RGB-LEDs. After this is done you should define all standard mouse buttons, profile-change and g-shift button to be the same for all three profiles. The twelve thumb buttons should have different symbols for every possible case! (normal and g-shift for three profiles = 6 sets. You don't need to make use of all three profiles if you don't need them)
I chose something like {1, 2, 3, ..., 9, 0, ß, ´} for the first profile and the keypad numbers 0 - 9 and keypad + and - for the G-shift case of the first profile. Another possibility would be the letters A - Z. With this you make sure that for example G9 (first thumb button) and G-shift+G9 are received as different events in Linux.
Maybe it's possible to define your wished shortcuts here, but I want to have a more generic way.

Back to Linux:
It didn't take long until I noticed, that this mouse is actually registering two events in /dev/input/ . One for the normal mouse-stuff (like clicking, you know) - and the other for all the fancy extra buttons and functionality. The second one is actually acting like a keyboard.

With

    sudo evtest 

you will be able to detect the scancodes of each button-event. First choose the event corresponding to the "keyboard-part" of the G600 and then hit each combination possible. (G9, G10, ..., G20, G-shift+G9, ... , G-shift+G20, for each profile you want to use)
You are searching for lines like:

    Event: time 1410191730.438246, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7001e

The bold part is the scancode you will need for this specific button.

Now we want to make a rule that those buttons behave differently for this device only. For our rule we should know the vendor and product ID of our USB-device. This is done through
      
    lsusb -v

this leads to something like:
    
    [text]      
    idVendor           0x046d Logitech, Inc.     
    idProduct          0xc24a G600 Gaming Mouse 
    [moretext]

The creation of such a rule is nowadays done through the udev-hwdb (hardwaredatabase). In Arch you have to create a file in /etc/udev/hwdb.d/
with the name

    70-SOMENAME.hwdb

There we need to write the line

    keyboard:usb:v046DpC24A*

followed by many definitions of the form
    
    KEYBOARD_KEY_<hex scan code>=<key code identifier>

where <hex scan code> is the scancode we obtained with evtest and <key code identifier> is a keycode of a currently (unused!) keyboard symbol. (You can find a list of possible keycodes at here)
I used some Japanese stuff, because I'm quite sure that I never have to use a Japanese keyboard. So this looks something like:

    KEYBOARD_KEY_7001e=zenkakuhankaku
    KEYBOARD_KEY_7001f=katakanahiragana       
    KEYBOARD_KEY_70020=katakana    
    KEYBOARD_KEY_70021=hangeul

After this you need to run

    udevadm hwdb --update

and you need to reconnect the device. (e.g. physically)

Now we can use xbindkeys and xautomation to define the shortcuts.
Use 

    xbindkeys -k

for each button. This will result into something like:

    "(Scheme function)"       
        m:0x10+c:191 

Now create a file named ".xbindkeysrc" in your homefolder and add one entry of the above format per button-event. (again: G-shift+GX is separate from GX) The entries could look like this:

    #G18     
    "xte 'keydown Super_L' 'key j' 'keyup Super_L'" 
        m:0x10+c:191+Release 
    #G18 +G-shift    
    "xte 'keydown Super_L' 'keydown Shift_L' 'key j' 'keyup Shift_L' 'keyup Super_L'"       
        m:0x10+c:202+Release

Now just start xbindkeys, and create some way of autostarting xbindkeys and you are done.

I used this procedure to define some Awesome WM shortcuts (like switching the current tag and changing layouts), and to improve browsing in Firefox. (changing tabs, closing tabs, reopen the last tab, back, forward, etc.)   

UPDATE (26.06.2015):

Today I had an issue that the mapping doesn’t work anymore (after an update). Long story short: with
    evdev:input:b*v046DpC24A*  
instead of 
    keyboard:usb:v046DpC24A

in the beginning of the hwdb file it worked again.  

14 comments:

  1. Did you manage to get G-Shift bindings working? If I use a G-Shift + Gx combination with evtest, it shows the same code that a non-G-Shift key press would show.

    Thanks!

    ReplyDelete
  2. Yes I was able to bind the G-Shifted buttons. I had similar problems like you are describing before.
    The trick is to define the "internal" mouse profiles in a different way. (sadly you need some windows machine with the logitech software for this)
    By default the thumbbuttons are defines as the keystrokes "1", "2", "3" and so on. The default g-shift+thumbbutton is just "Ctrl+1", "Ctrl+2", etc. Since events like "Ctrl" is handled differently than simple buttons like the numbers, evtest can't distinguish between those to.

    So simple solution:
    Connect the device to some windows machine with the Logitech Software installed.
    Choose the mode where you can change the internal Profiles (Slider at the bottom of the Logitech Software.)
    Set the Thumbuttons and the G-Shift+Thumbuttons to some clearly distinguishable keys (like letters and numbers)
    Boot to Linux and enjoy your G-Shifted buttons.


    With those three profiles and all thumbbuttons you have like 24*3=72 different possible key-events.
    This offers an insane amount of possible short-cuts.

    ReplyDelete
  3. Thanks for your help - I've written a similar post (with a link back to you) here, as I needed a slightly different setup.

    ReplyDelete
  4. How did you find that 0x10+c was your mouse code?

    ReplyDelete
  5. Nevermind. I see that that's what the xbindkeys -k is supposed to do.

    ReplyDelete
  6. In Arch, do keycodes like "zenkakuhankaku" not generate keycode numbers greater than 255? Or is that not a problem for the Arch version of xev and xbindkeys? Under debian that generates keycode 429 which xev won't catch.

    ReplyDelete
  7. Hm good question. That might depend on your Hardware etc.
    There seems to be no way to use keycodes >255

    https://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/313514

    But you can map those to smaller keycodes:

    http://unix.stackexchange.com/questions/58559/how-to-change-a-keycode-using-setkeycodes

    ReplyDelete
  8. I just had to use the evtest to get the code and setting the .hwdb file so far has given me the control I need. but figuring out all the possible key commands possible is a little challenging since they are listed in alphabetical order and not by use. Im in Ubuntu gnome and not Arch.

    ReplyDelete
  9. I can't get this to work at all. I have /etc/udev/hwdb.d/70-g600.hwdb containing

    evdev:input:b*v046DpC24A*
    KEYBOARD_KEY_7001e=hangeul
    ...

    and when running `udevadm hwdb --update' no errors are thrown. Any ideas on what the problem is?

    ReplyDelete
    Replies
    1. What exactly does not work? Everything after the udevadm hwdb --update step?
      What is the output of xbindkeys -k, when you hit a button on the G600? (maybe try different buttons)
      Did you reconnect the G600 after the hwdb --update?

      Delete
  10. I recently ran into problems with this method due to the hardware identifier

    evdev:input:b*v046DpC24A*

    A Wiki article on the Arch Linux site pointed me at this command:

    udevadm info /dev/input/event5

    This is an "ok" debugging command to see if the key maps are loading properly as it dumps useful information about the mouse that should include the KEYBOARD_KEY directive if the rule is loading properly.

    Some more research led me to the command:

    udevadm --debug test devid

    "devid" is the DEVPATH variable from the 'udevadm info' command above. Reading the output of this command is a bit daunting but it lead me to the file:

    /lib64/udev/rules.d/60-evdev.rules

    Some time deciphering the udev rules in this file showed that it makes three attempts to load the hwdb information based on how the device is identified.

    The first, in theory, should match against the vendor/product ID you are using but the debug commands I was running was showing the look up was failing but was not producing enough information as to why.

    The second rule is used if the atkbd driver is used. It's not in this case even though the device we're going after is identifying itself as a hid keyboard.

    The third rule attempts to make a hwdb lookup based on the device name attribute along with it's DMI string.

    Since the first rule was failing to match and the second wasn't used I tried to match the third rule.

    udevadm info -q all -a /dev/input/event5

    This command also dumps quite a bit of information. Looking at the first parent device gave me:

    ATTRS{name}=="Logitech Gaming Mouse G600"

    Ok, that's the first piece I need. The second is the DMI identifier. Looking at the test output the DMI string is a nightmarishly long string that, thankfully, we don't have to match exactly.

    So, I, finally, set the hwdb match string to:

    evdev:name:Logitech Gaming Mouse G600:dmi:bvn*

    Ran:

    udevadm hwdb --update

    udevadm trigger /dev/input/event5

    udevadm info /dev/input/event5

    KEYBOARD_KEY entries are now in the output. Done!

    ReplyDelete
    Replies
    1. I also have the G600 mouse, but i'm running Linux Mint 17 and i can't get it to work, following the same steps that you did.

      I've tried with:
      "evdev:input:b*v046DpC24A*"
      "keyboard:usb:v046DpC24A*"
      and "evdev:name:Logitech Gaming Mouse G600:dmi:bvn*"

      The rules are never loaded even after "udevadm hwdb --update"...unplug/plug mouse...system reboot. It just doesn't work.

      Any advice?

      Delete
    2. Just had the same issue in Linux Mint 18.

      You should run:
      sudo systemd-hwdb update
      instead of:
      sudo udevadm hwdb --update

      "evdev:input:b*v046DpC24A*" worked for me.

      Delete
  11. I like the concepts and the workflow that you have shown to us. This gives us a lot of insights in using the proper control of this devices that are to input in any specific values. The commands and the inputs are great to know, as it needs to learn for the users to be more familiar with this thing.

    ReplyDelete