Repository: pwr-Solaar/Solaar

Issue:
"show" tracebacks on G935 headset
Using current git version on a Logitech G935 headset:
```
$ ./bin/solaar -D /dev/hidraw5 --debug show
2022-12-05 17:31:27,905,905  WARNING [MainThread] hidapi.udev: Report Descriptor not processed for BID 0003 VID 0000046D PID 00000A87: No module named 'hid_parser'
2022-12-05 17:31:27,906,906  WARNING [MainThread] hidapi.udev: Report Descriptor not processed for BID 0003 VID 0000046D PID 0000C52B: No module named 'hid_parser'
2022-12-05 17:31:27,907,907  WARNING [MainThread] hidapi.udev: Report Descriptor not processed for BID 0005 VID 0000046D PID 0000B02A: No module named 'hid_parser'
solaar version 1.1.7-37-g7874886

USB and Bluetooth Devices

  1: G935 Gaming Headset
     Device path  : /dev/hidraw5
     USB id       : 046d:0A87
     Codename     : G935 Headset
     Kind         : headset
     Protocol     : HID++ 4.2
     Serial number: 
     Model ID:      000000000A87
     Unit ID:       FFFFFFFF
          Firmware: U1  29.00.B0012
     Supports 9 HID++ 2.0 features:
2022-12-05 17:31:27,978,978    ERROR [MainThread] logitech_receiver.base: (4) device 255 error on feature request {0609}: 5 = logitech internal
Traceback (most recent call last):
  File "/home/hadess/Projects/jhbuild/Solaar/lib/logitech_receiver/settings_templates.py", line 1250, in check_feature
    detected = sclass.build(device)
               ^^^^^^^^^^^^^^^^^^^^
  File "/home/hadess/Projects/jhbuild/Solaar/lib/logitech_receiver/settings.py", line 233, in build
    validator = validator_class.build(cls, device, **cls.validator_options)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/hadess/Projects/jhbuild/Solaar/lib/logitech_receiver/settings_templates.py", line 1177, in build
    data = device.feature_request(_F.EQUALIZER, 0x00)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/hadess/Projects/jhbuild/Solaar/lib/logitech_receiver/device.py", line 443, in feature_request
    return _hidpp20.feature_request(self, feature, function, *params, no_reply=no_reply)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/hadess/Projects/jhbuild/Solaar/lib/logitech_receiver/hidpp20.py", line 1126, in feature_request
    return device.request((feature_index << 8) + (function & 0xFF), *params, no_reply=no_reply)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/hadess/Projects/jhbuild/Solaar/lib/logitech_receiver/device.py", line 431, in request
    return _base.request(
           ^^^^^^^^^^^^^^
  File "/home/hadess/Projects/jhbuild/Solaar/lib/logitech_receiver/base.py", line 460, in request
    raise _hidpp20.FeatureCallError(number=devnumber, request=request_id, error=error, params=params)
logitech_receiver.hidpp20.FeatureCallError: {'number': 255, 'request': 1545, 'error': 5, 'params': b''}

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/hadess/Projects/jhbuild/Solaar/lib/logitech_receiver/common.py", line 254, in __getattr__
    return super().__getattr__(k)
           ^^^^^^^^^^^^^^^^^^^
AttributeError: 'super' object has no attribute '__getattr__'. Did you mean: '__setattr__'?
```
There's more errors after that, with expections during exception handling.

This is the output I got from the tools at https://github.com/cvuchener/hidpp:
```
$ src/tools/hidpp-list-features /dev/hidraw5 
Logitech G935 Gaming Headset (046d:0a87) is a HID++ 4.2 device
Feature 0x01: [0x0001] Feature set
Feature 0x02: [0x0003] Device FW version
Feature 0x03: [0x0005] Device name
Feature 0x04: [0x8070] Color LED effects
Feature 0x05: [0x8010] G-key
Feature 0x06: [0x8310] Equalizer
Feature 0x07: [0x8300] Sidetone
Feature 0x08: [0x1f20] ADC Measurement
```

Bisected to ec0e304fdc2db379106b0252656252efbf2287f5


Discussion:
When it works:
```
Solaar version 1.1.3

USB and Bluetooth Devices

  1: G935 Gaming Headset
     Device path  : /dev/hidraw5
     USB id       : 046d:0A87
     Codename     : G935 Headset
     Kind         : headset
     Protocol     : HID++ 4.2
     Serial number: 
     Model ID:      000000000A87
     Unit ID:       FFFFFFFF
          Firmware: U1  29.00.B0012
     Supports 8 HID++ 2.0 features:
         0: ROOT                   {0000}   
         1: FEATURE SET            {0001}   
         2: DEVICE FW VERSION      {0003}   
            Firmware: Firmware U1  29.00.B0012 0A87
            Unit ID: FFFFFFFF  Model ID: 000000000A87  Transport IDs: {'btid': '0000', 'btleid': '0000'}
         3: DEVICE NAME            {0005}   
            Name: G935 Gaming Headset
            Kind: None
         4: COLOR LED EFFECTS      {8070}   
         5: GKEY                   {8010}   
            Divert G Keys (saved): False
            Divert G Keys        : False
         6: EQUALIZER              {8310}   
         7: SIDETONE               {8300}   
     Battery status unavailable.
```
When showing debugging output, Solaar prints exception traces even when the exceptions occur in try statements.  It appears that this is the case here.  Please provide full output from `solaar show`.

The commit you found is the commit that adds support for setting the equalizer levels.


error output:
[solaar-debug.txt](https://github.com/pwr-Solaar/Solaar/files/10156442/solaar-debug.txt)

What does `solaar show` produce on stdout?
> What does `solaar show` produce on stdout?

I already copy/pasted it at the top of the issue. Did you want stdin and stderr combined?

Resolving patch:
diff --git a/lib/logitech_receiver/common.py b/lib/logitech_receiver/common.py
--- a/lib/logitech_receiver/common.py
+++ b/lib/logitech_receiver/common.py
@@ -253,7 +253,7 @@ def __getattr__(self, k):
         try:
             return super().__getattr__(k)
         except AttributeError:
-            return self.args[0][k]
+            return self.args[0].get(k)  # was self.args[0][k]
 
 
 """Firmware information."""
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
@@ -1251,9 +1251,10 @@ def check_feature(device, sclass):
         if _log.isEnabledFor(_DEBUG):
             _log.debug('check_feature %s [%s] detected %s', sclass.name, sclass.feature, detected)
         return detected
-    except Exception:
+    except Exception as e:
         from traceback import format_exc
-        _log.error('check_feature %s [%s] error %s', sclass.name, sclass.feature, format_exc())
+        _log.error('check_feature %s [%s] error %s\n%s', sclass.name, sclass.feature, e, format_exc())
+        return False  # differentiate from an error-free determination that the setting is not supported
 
 
 # Returns True if device was queried to find features, False otherwise
@@ -1274,8 +1275,9 @@ def check_feature_settings(device, already_known):
                     already_known.append(setting)
                     if sclass.name in newAbsent:
                         newAbsent.remove(sclass.name)
-                elif sclass.name not in newAbsent and sclass.name not in absent and sclass.name not in device.persister:
-                    newAbsent.append(sclass.name)
+                elif setting is None:
+                    if sclass.name not in newAbsent and sclass.name not in absent and sclass.name not in device.persister:
+                        newAbsent.append(sclass.name)
     if device.persister and newAbsent:
         absent.extend(newAbsent)
         device.persister['_absent'] = absent
diff --git a/lib/solaar/cli/show.py b/lib/solaar/cli/show.py
--- a/lib/solaar/cli/show.py
+++ b/lib/solaar/cli/show.py
@@ -234,7 +234,7 @@ def _print_device(dev, num=None):
                     try:
                         v = setting.val_to_string(setting.read(False))
                     except _hidpp20.FeatureCallError as e:
-                        v = e
+                        v = 'HID++ error ' + str(e)
                     print('            %s        : %s' % (setting.label, v))
 
     if dev.online and dev.keys:


Test patch: