Repository: pwr-Solaar/Solaar

Issue:
Support for Logitech G613 with receiver id c53d
Apparently solaar v1.0.1 on ubuntu ppa does not support Lightspeed receiver with id c53d . solaar reported that no receiver has been found.

Here is the output of my lsusb

tonny@fenrir:[~]: lsusb
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 005: ID 1b1c:1b65 Corsair 
Bus 003 Device 006: ID 046d:c53d Logitech, Inc. 
Bus 003 Device 003: ID 046d:082b Logitech, Inc. Webcam C170
Bus 003 Device 002: ID 1a40:0101 Terminus Technology Inc. Hub
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 8087:0aa7 Intel Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub



Discussion:
Yes, that receiver is currently unknown to Solaar.   Adding a new receiver is easy but requires super user access.   I created a new branch in my repository for this receiver.   The following should let you see how well your device works:
1/ Clone the c53d branch of my repository via
```
git clone -b c53d https://github.com/pfps/Solaar.git
```
2/ Kill any running Solaar.
3/ Run this Solaar as root (otherwise you would have to install a udev rule and that requires root anyway)
```
sudo Solaar/bin/solaar
```

Please let us know how this goes and please provide the output of `Solaar/bin/solaar show` as that says what features your device has.

I'm having the same problem... Solar only recognizes my G603 mouse, and not my G613 keyboard...

@pfps Do you know if doing this the macro keys will work? Right now, the system sees them as F1~F6 keys :/ 
@raulcraveiro Each device (mouse or keyboard) is different.  You won't know what is supported or what is easy to support until the receiver is added to Solaar and you see what shows up in the Solaar main window.   The output of `solaar show` says which HID++ features are provided by the device, so if things aren't working right providing that information is helpful to see what can be done.
To get this receiver added I need someone to test out my changes.
It's working!

![image](https://user-images.githubusercontent.com/5623492/82839211-04783280-9ea5-11ea-90b9-28534d0871b5.png)

Do you need me to test something specifically?

Good.   I'll put in a PR for the changes.

Could you post the output from `solaar show` so that I can see what features the keyboard has?
Thank you @pfps 
@pfps Here's the output from the show:

Lightspeed Receiver
  Device path  : /dev/hidraw5
  USB id       : 046d:c539
  Serial       : 61E612F6
    Firmware   : 39.06.B0040
    Bootloader : 02.09
    Other      : AA.BE
  Has 1 paired device(s) out of a maximum of 1.
  Notifications: wireless, software present (0x000900)
  Device activity counters: (empty)

  1: G603 Wireless Gaming Mouse
     Codename     : G603
     Kind         : mouse
     Wireless PID : 406C
     Protocol     : HID++ 4.2
     Polling rate : 8 ms (125Hz)
     Serial number: BE87C8CC
        Bootloader: BOT 58.06.B0028
          Firmware: MPM 08.06.B0028
             Other: 
     The power switch is located on the base.
     Supports 33 HID++ 2.0 features:
         0: ROOT                   {0000}   
         1: FEATURE SET            {0001}   
         2: DEVICE FW VERSION      {0003}   
         3: DEVICE NAME            {0005}   
         4: WIRELESS DEVICE STATUS {1D4B}   
         5: DEVICE FRIENDLY NAME   {0007}   
         6: BATTERY STATUS         {1000}   
         7: REPROG CONTROLS V4     {1B04}   
         8: CHANGE HOST            {1814}   
         9: HOSTS INFO             {1815}   
        10: COLOR LED EFFECTS      {8070}   
        11: ONBOARD PROFILES       {8100}   
        12: MOUSE BUTTON SPY       {8110}   
        13: REPORT RATE            {8060}   
        14: MODE STATUS            {8090}   
        15: DFUCONTROL UNSIGNED    {00C1}   
        16: DFUCONTROL SIGNED      {00C2}   
        17: DEVICE RESET           {1802}   internal, hidden
        18: unknown:1803           {1803}   internal, hidden
        19: CONFIG DEVICE PROPS    {1806}   internal, hidden
        20: unknown:1813           {1813}   internal, hidden
        21: OOBSTATE               {1805}   internal, hidden
        22: unknown:1830           {1830}   internal, hidden
        23: unknown:1890           {1890}   internal, hidden
        24: unknown:1891           {1891}   internal, hidden
        25: unknown:1DF3           {1DF3}   internal, hidden
        26: unknown:1E00           {1E00}   hidden
        27: unknown:1EB0           {1EB0}   internal, hidden
        28: unknown:1861           {1861}   internal, hidden
        29: unknown:18B1           {18B1}   internal, hidden
        30: unknown:1E22           {1E22}   
        31: unknown:1801           {1801}   internal, hidden
        32: ADJUSTABLE DPI         {2201}   
     Has 2 reprogrammable keys:
         0: unknown:00D1              , default: unknown:00AE                => unknown:00D1              
             divertable, persistently divertable, pos:1, group:0, gmask:0
         1: unknown:00D2              , default: unknown:00AF                => unknown:00D2              
             divertable, persistently divertable, pos:2, group:0, gmask:0
     Battery: 90%, discharging.

Lightspeed Receiver
  Device path  : /dev/hidraw2
  USB id       : 046d:c53d
  Serial       : 17887C62
    Firmware   : 43.00.B0006
    Bootloader : 02.10
    Other      : AA.D2
  Has 1 paired device(s) out of a maximum of 1.
  Notifications: (none)
  Device activity counters: (empty)

  1: G613 Wireless Mechanical Gaming Keyboard
     Codename     : G613
     Kind         : keyboard
     Wireless PID : 4065
     Protocol     : HID++ 4.2
     Polling rate : 1 ms (1000Hz)
     Serial number: 63A22FBD
        Bootloader: BOT 46.00.B0006
          Firmware: MPK 05.02.B0021
             Other: 
     Supports 32 HID++ 2.0 features:
         0: ROOT                   {0000}   
         1: FEATURE SET            {0001}   
         2: DEVICE FW VERSION      {0003}   
         3: DEVICE NAME            {0005}   
         4: WIRELESS DEVICE STATUS {1D4B}   
         5: RESET                  {0020}   
         6: DEVICE FRIENDLY NAME   {0007}   
         7: BATTERY STATUS         {1000}   
         8: CHANGE HOST            {1814}   
         9: HOSTS INFO             {1815}   
        10: REPROG CONTROLS V4     {1B04}   
        11: REPORT HID USAGE       {1BC0}   
        12: ENCRYPTION             {4100}   
        13: KEYBOARD DISABLE BY USAGE {4522}   
        14: KEYBOARD LAYOUT 2      {4540}   
        15: GKEY                   {8010}   
        16: REPORT RATE            {8060}   
        17: DFUCONTROL SIGNED      {00C2}   
        18: DEVICE RESET           {1802}   internal, hidden
        19: unknown:1803           {1803}   internal, hidden
        20: CONFIG DEVICE PROPS    {1806}   internal, hidden
        21: unknown:1813           {1813}   internal, hidden
        22: OOBSTATE               {1805}   internal, hidden
        23: unknown:1830           {1830}   internal, hidden
        24: unknown:1890           {1890}   internal, hidden
        25: unknown:1891           {1891}   internal, hidden
        26: unknown:18A1           {18A1}   internal, hidden
        27: unknown:1DF3           {1DF3}   internal, hidden
        28: unknown:1E00           {1E00}   hidden
        29: unknown:1EB0           {1EB0}   internal, hidden
        30: unknown:1861           {1861}   internal, hidden
        31: unknown:18B1           {18B1}   internal, hidden
     Has 2 reprogrammable keys:
         0: unknown:00D1              , default: unknown:00AE                => unknown:00D1              
             divertable, persistently divertable, pos:1, group:0, gmask:0
         1: unknown:00D2              , default: unknown:00AF                => unknown:00D2              
             divertable, persistently divertable, pos:2, group:0, gmask:0
     Battery: 80%, discharging.
OK, that will help when more features are implemented.
Just gonna throw my output here as well since it's a tiny bit different and maybe that helps with compatibility somehow.
```
Lightspeed Receiver
  Device path  : /dev/hidraw10
  USB id       : 046d:c53d
  Serial       : C7A6EBE9
    Firmware   : 43.01.B0009
    Bootloader : 02.10
    Other      : AA.D2
  Has 1 paired device(s) out of a maximum of 1.
  Notifications: wireless, software present (0x000900)
  Device activity counters: (empty)

  1: G613 Wireless Mechanical Gaming Keyboard
     Codename     : G613
     Kind         : keyboard
     Wireless PID : 4065
     Protocol     : HID++ 4.2
     Polling rate : 1 ms (1000Hz)
     Serial number: 1B3FC305
        Bootloader: BOT 46.00.B0006
          Firmware: MPK 05.02.B0021
             Other: 
     Supports 32 HID++ 2.0 features:
         0: ROOT                   {0000}   
         1: FEATURE SET            {0001}   
         2: DEVICE FW VERSION      {0003}   
         3: DEVICE NAME            {0005}   
         4: WIRELESS DEVICE STATUS {1D4B}   
         5: RESET                  {0020}   
         6: DEVICE FRIENDLY NAME   {0007}   
         7: BATTERY STATUS         {1000}   
         8: CHANGE HOST            {1814}   
         9: HOSTS INFO             {1815}   
        10: REPROG CONTROLS V4     {1B04}   
        11: REPORT HID USAGE       {1BC0}   
        12: ENCRYPTION             {4100}   
        13: KEYBOARD DISABLE BY USAGE {4522}   
        14: KEYBOARD LAYOUT 2      {4540}   
        15: GKEY                   {8010}   
        16: REPORT RATE            {8060}   
        17: DFUCONTROL SIGNED      {00C2}   
        18: DEVICE RESET           {1802}   internal, hidden
        19: unknown:1803           {1803}   internal, hidden
        20: CONFIG DEVICE PROPS    {1806}   internal, hidden
        21: unknown:1813           {1813}   internal, hidden
        22: OOBSTATE               {1805}   internal, hidden
        23: unknown:1830           {1830}   internal, hidden
        24: unknown:1890           {1890}   internal, hidden
        25: unknown:1891           {1891}   internal, hidden
        26: unknown:18A1           {18A1}   internal, hidden
        27: unknown:1DF3           {1DF3}   internal, hidden
        28: unknown:1E00           {1E00}   hidden
        29: unknown:1EB0           {1EB0}   internal, hidden
        30: unknown:1861           {1861}   internal, hidden
        31: unknown:18B1           {18B1}   internal, hidden
     Has 2 reprogrammable keys:
         0: unknown:00D1              , default: unknown:00AE                => unknown:00D1              
             divertable, persistently divertable, pos:1, group:0, gmask:0
         1: unknown:00D2              , default: unknown:00AF                => unknown:00D2              
             divertable, persistently divertable, pos:2, group:0, gmask:0
     Battery: 50%, discharging.
```
Awesome to see this support is potentially coming soon. Thanks so much for all your efforts here, its much appreciated.
Support is already in the version of Solaar on this repository, and maybe in some distributions as well.  You can clone and run Solaar from hear fairly easily - see the instructions in https://pwr-solaar.github.io/Solaar/installation

Hi Guys,

Hi Can I set the G-keys for this keyboard?
Sollar doesn't currently support the GKEY feature, which is probably what is needed to set these keys.  Depending on how this feature works it may be easy to implement in Solaar.
I have a G613 and came upon this searching for setting the G Keys as well. If some king of dump is needed I could try to provide it.

FWIW on both Windows and Linux the G Keys are identified as F keys without the Logitech software installed.
I expect that the GKEY feature allows "diverting" the G keys to report using a special mechanism.  A very recent addition to Solaar allows such diverted reports to be processed and turned into other key presses (at least under X11).  If this diversion is not on, then the G keys act like Fn keys.
The easiest way to find out more is to get some documentation from Logitech.  If this fails, then it might be necessary to sniff out what the Logitech software is doing.
This is really odd to me, the hardware is delivering the same keycode to G1 and F1?
Or is the OS replacing the keycode gap?
There are lots of things that are odd about Logitech (and other) devices.  If you have this keyboard then you could use a tool like showkey or xev to find out more about what G keys do without the Logitech software running.
Using showkey command, both Fs and Gs have the same code

Resolving patch:
diff --git a/lib/logitech_receiver/diversion.py b/lib/logitech_receiver/diversion.py
--- a/lib/logitech_receiver/diversion.py
+++ b/lib/logitech_receiver/diversion.py
@@ -135,7 +135,6 @@ def key_press_handler(reply):
 
 # See docs/rules.md for documentation
 
-keys_down = []
 key_down = None
 
 
@@ -595,21 +594,17 @@ def data(self):
 if x11:
     built_in_rules = Rule([
         {'Rule': [  # Implement problematic keys for Craft and MX Master
-            {'Feature': 'REPROG_CONTROLS_V4'},
-            {'Report': 0x0},
             {'Rule': [{'Key': 'Brightness Down'}, {'KeyPress': 'XF86_MonBrightnessDown'}]},
             {'Rule': [{'Key': 'Brightness Up'}, {'KeyPress': 'XF86_MonBrightnessUp'}]},
         ]},
         {'Rule': [  # In firefox, crown emits keys that move up and down if not pressed, rotate through tabs otherwise
             {'Process': 'firefox'},
-            {'Feature': 'CROWN'},
-            {'Report': 0x0},
             {'Rule': [{'Test': 'crown_pressed'}, {'Test': 'crown_right_ratchet'}, {'KeyPress': ['Control_R', 'Tab']}]},
             {'Rule': [{'Test': 'crown_pressed'},
                       {'Test': 'crown_left_ratchet'},
                       {'KeyPress': ['Control_R', 'Shift_R', 'Tab']}]},
             {'Rule': [{'Test': 'crown_right_ratchet'}, {'KeyPress': 'Down'}]},
-            Rule([Test('crown_left_ratchet'), KeyPress(['Up'])]),
+            {'Rule': [{'Test': 'crown_left_ratchet'}, {'KeyPress': 'Up'}]},
         ]},
         {'Rule': [  # Otherwise, crown movements emit keys that modify volume if not pressed, move between tracks otherwise
             {'Feature': 'CROWN'}, {'Report': 0x0},
@@ -626,12 +621,15 @@ def data(self):
         ]}
     ])
 
+keys_down = []
+g_keys_down = 0x00
+
 
 # process a notification
 def process_notification(device, status, notification, feature):
     if not x11:
         return
-    global keys_down, key_down
+    global keys_down, g_keys_down, key_down
     key_down = None
     # need to keep track of keys that are down to find a new key down
     if feature == _F.REPROG_CONTROLS_V4 and notification.address == 0x00:
@@ -640,6 +638,13 @@ def process_notification(device, status, notification, feature):
             if key and key not in keys_down:
                 key_down = key
         keys_down = new_keys_down
+    # and also G keys down
+    elif feature == _F.GKEY and notification.address == 0x00:
+        new_g_keys_down, = _unpack('!B', notification.data[:1])
+        for i in range(1, 9):
+            if new_g_keys_down & (0x01 << (i - 1)) and not g_keys_down & (0x01 << (i - 1)):
+                key_down = _CONTROL['G' + str(i)]
+        g_keys_down = new_g_keys_down
     rules.evaluate(feature, notification, device, status, True)
 
 
diff --git a/lib/logitech_receiver/settings_templates.py b/lib/logitech_receiver/settings_templates.py
--- a/lib/logitech_receiver/settings_templates.py
+++ b/lib/logitech_receiver/settings_templates.py
@@ -97,7 +97,7 @@
                         _('Change the action for the key or button.') + '\n' +
                         _('Changing important actions (such as for the left mouse button) can result in an unusable system.'))
 _DIVERT_KEYS = ('divert-keys', _('Key/Button Diversion'),
-                _('Divert the key or button to report using HID++ notifications.'))
+                _('Make the key or button send HID++ notifications (which trigger Solaar rules but are otherwise ignored).'))
 _DISABLE_KEYS = ('disable-keyboard-keys', _('Disable keys'), _('Disable specific keyboard keys.'))
 _PLATFORM = ('multiplatform', _('Set OS'), _('Change keys to match OS.'))
 _CHANGE_HOST = ('change-host', _('Change Host'), _('Switch connection to a different host'))
@@ -110,7 +110,9 @@
 _DPI_SLIDING = ('dpi-sliding', _('DPI Sliding Adjustment'),
                 _('Adjust the DPI by sliding the mouse horizontally while holding the DPI button.'))
 _DIVERT_CROWN = ('divert-crown', _('Divert crown events'),
-                 _('Make the crown send HID++ events (which are normally ignored in Linux).'))
+                 _('Make crown send CROWN HID++ notifications (which trigger Solaar rules but are otherwise ignored).'))
+_DIVERT_GKEYS = ('divert-gkeys', _('Divert G Keys'),
+                 _('Make G keys send GKEY HID++ notifications (which trigger Solaar rules but are otherwise ignored).'))
 
 _GESTURE2_GESTURES_LABELS = {
     _GG['Tap1Finger']: (_('Single tap'), _('Performs a left click.')),
@@ -711,6 +713,18 @@ def _feature_divert_crown():
     return _Setting(_DIVERT_CROWN, rw, _BooleanV(true_value=0x02, false_value=0x01, mask=0xff), device_kind=(_DK.keyboard, ))
 
 
+def _feature_divert_gkeys():
+    class _DivertGkeysRW(_FeatureRW):
+        def __init__(self, feature):
+            super(_DivertGkeysRW, self).__init__(feature, write_fnid=0x20)
+
+        def read(self, device):  # no way to read, so just assume not diverted
+            return 0x00
+
+    rw = _DivertGkeysRW(_F.GKEY)
+    return _Setting(_DIVERT_GKEYS, rw, _BooleanV(true_value=0x01, false_value=0x00, mask=0xff), device_kind=(_DK.keyboard, ))
+
+
 #
 #
 #
@@ -743,6 +757,7 @@ def _S(name, featureID=None, featureFn=None, registerFn=None, identifier=None):
     _S(_DIVERT_KEYS, _F.REPROG_CONTROLS_V4, _feature_divert_keys),
     _S(_DISABLE_KEYS, _F.KEYBOARD_DISABLE_KEYS, _feature_disable_keyboard_keys),
     _S(_DIVERT_CROWN, _F.CROWN, _feature_divert_crown),
+    _S(_DIVERT_GKEYS, _F.GKEY, _feature_divert_gkeys),
     _S(_PLATFORM, _F.MULTIPLATFORM, _feature_multiplatform),
     _S(_PLATFORM, _F.DUALPLATFORM, _feature_dualplatform, identifier='dualplatform'),
     _S(_CHANGE_HOST, _F.CHANGE_HOST, _feature_change_host),
diff --git a/lib/logitech_receiver/special_keys.py b/lib/logitech_receiver/special_keys.py
--- a/lib/logitech_receiver/special_keys.py
+++ b/lib/logitech_receiver/special_keys.py
@@ -271,6 +271,10 @@
     LeftAndRightClick=0x0102,
     LED_Toggle=0x013B,  #
 )
+
+for i in range(1, 7):  # add in G keys - these are not really Logitech Controls
+    CONTROL[0x1000 + i] = 'G' + str(i)
+
 CONTROL._fallback = lambda x: 'unknown:%04X' % x
 
 # <tasks.xml awk -F\" '/<Task /{gsub(/ /, "_", $6); printf("\t%s=0x%04X,\n", $6, $4)}'


Test patch: