Repository: pwr-Solaar/Solaar

Issue:
The 'Show Technical Details' View does show the default polling rate instead of current one
**Information**
<!-- Make sure that your issue is not one of the known issues in the Solaar documentation at https://pwr-solaar.github.io/Solaar/ -->
<!-- Do not bother opening an issue for a version older than 1.1.0.  Upgrade to the latest version and see if your issue persists. -->
<!-- If you not running the current version of Solaar, strongly consider upgrading to the newest version. -->
- Solaar version (`solaar --version` or `git describe --tags` if cloned from this repository): solaar 1.1.3
- Distribution: Fedora Linux 36
- Kernel version (ex. `uname -srmo`): `5.17.8-300.fc36.x86_64`
- Output of `solaar show`:

<details>

```
Solaar version 1.1.3

Lightspeed Receiver
  Device path  : /dev/hidraw6
  USB id       : 046d:C547
  Serial       : 9B341CD1
    Firmware   : 04.02.B0009
    Bootloader : 00.05
    Other      : F3.24
  Has 1 paired device(s) out of a maximum of 2.
  Notifications: wireless, software present (0x000900)
  Device activity counters: 1=171

  1: PRO X Wireless
     Device path  : None
     WPID         : 4093
     Codename     : PRO X
     Kind         : mouse
     Protocol     : HID++ 4.2
     Polling rate : 8 ms (125Hz)
     Serial number: 42F42E12
     Model ID:      4093C0940000
     Unit ID:       42F42E12
        Bootloader: BL1 25.00.B0013
             Other: 
          Firmware: MPM 25.01.B0018
     Supports 28 HID++ 2.0 features:
         0: ROOT                   {0000}   
         1: FEATURE SET            {0001}   
         2: DEVICE FW VERSION      {0003}   
            Firmware: Bootloader BL1 25.00.B0013 AB00BE657A82
            Firmware: Other   
            Firmware: Firmware MPM 25.01.B0018 4093FE92436C
            Unit ID: 42F42E12  Model ID: 4093C0940000  Transport IDs: {'wpid': '4093', 'usbid': 'C094'}
         3: DEVICE NAME            {0005}   
            Name: PRO X Wireless
            Kind: mouse
         4: WIRELESS DEVICE STATUS {1D4B}   
         5: RESET                  {0020}   
         6: UNIFIED BATTERY        {1004}   
         7: COLOR LED EFFECTS      {8070}   internal, hidden
         8: ONBOARD PROFILES       {8100}   
            Device Mode: Host
            Onboard Profiles (saved): Disable
            Onboard Profiles        : Disable
         9: MOUSE BUTTON SPY       {8110}   
        10: REPORT RATE            {8060}   
            Polling Rate (ms): 1
            Polling Rate (ms) (saved): 1
            Polling Rate (ms)        : 1
        11: ADJUSTABLE DPI         {2201}   
            Sensitivity (DPI) (saved): 1000
            Sensitivity (DPI)        : 1000
        12: unknown:1500           {1500}   
        13: DEVICE RESET           {1802}   internal, hidden
        14: unknown:1803           {1803}   internal, hidden
        15: CONFIG DEVICE PROPS    {1806}   internal, hidden
        16: unknown:1811           {1811}   internal, hidden
        17: OOBSTATE               {1805}   internal, hidden
        18: unknown:1830           {1830}   internal, hidden
        19: unknown:1890           {1890}   internal, hidden
        20: unknown:1891           {1891}   internal, hidden
        21: unknown:18A1           {18A1}   internal, hidden
        22: unknown:1801           {1801}   internal, hidden
        23: unknown:18B1           {18B1}   internal, hidden
        24: unknown:1E00           {1E00}   hidden
        25: unknown:1EB0           {1EB0}   internal, hidden
        26: unknown:1863           {1863}   internal, hidden
        27: unknown:1E22           {1E22}   internal, hidden
     Battery: 76%, discharging.

```
</details>

- Contents of `~/.config/solaar/config.yaml` (or `~/.config/solaar/config.json` if `~/.config/solaar/config.yaml` not present):

<details>

```
- 1.1.3
- _NAME: PRO X Wireless
  _absent: [hi-res-scroll, lowres-scroll-mode, hires-smooth-invert, hires-smooth-resolution, hires-scroll-mode, smart-shift, thumb-scroll-mode, thumb-scroll-invert,
    pointer_speed, dpi-sliding, speed-change, mouse-gestures, backlight, backlight-timed, fn-swap, reprogrammable-keys, persistent-remappable-keys, divert-keys,
    disable-keyboard-keys, divert-crown, crown-smooth, divert-gkeys, m-key-leds, mr-key-led, multiplatform, change-host, gesture2-gestures, gesture2-divert,
    gesture2-params]
  _modelId: 4093C0940000
  _sensitive: {dpi: true, onboard_profiles: false, report_rate: false}
  _serial: 42F42E12
  _unitId: 42F42E12
  _wpid: '4093'
  dpi: 1000
  onboard_profiles: 2
  report_rate: 1
```
</details>


- Errors or warrnings from Solaar:
<!-- Run Solaar as `solaar -dd`, after killing any running Solaar processes.  If any warnings or errors show up, include the output here. -->



**Describe the bug**
The 'Show Technical Details' View does show the default polling rate instead of current one if you change the polling rate.

**To Reproduce**
Steps to reproduce the behavior:
1. Change the polling rate 
2. Click on 'Show Technical Details'
3. The Polling Rate here shown here is the default instead of the recently set one. 

**Screenshots**
![image](https://user-images.githubusercontent.com/58076574/170733957-e8533d2f-a529-4f69-9aea-f879ce15f7a9.png)
**Additional context**
\-



Discussion:

Resolving patch:
diff --git a/lib/logitech_receiver/device.py b/lib/logitech_receiver/device.py
--- a/lib/logitech_receiver/device.py
+++ b/lib/logitech_receiver/device.py
@@ -33,13 +33,13 @@ class Device:
     read_register = _hidpp10.read_register
     write_register = _hidpp10.write_register
 
-    def __init__(self, receiver, number, link_notification=None, info=None):
+    def __init__(self, receiver, number, link_notification=None, info=None, path=None, handle=None):
         assert receiver or info
         self.receiver = receiver
         self.may_unpair = False
         self.isDevice = True  # some devices act as receiver so we need a property to distinguish them
-        self.handle = None
-        self.path = None
+        self.path = path
+        self.handle = handle
         self.product_id = None
 
         if receiver:
@@ -93,6 +93,19 @@ def __init__(self, receiver, number, link_notification=None, info=None):
         # if _log.isEnabledFor(_DEBUG):
         #     _log.debug("new Device(%s, %s, %s)", receiver, number, link_notification)
 
+        if not self.path:
+            self.path = _hid.find_paired_node(receiver.path, number, 1) if receiver else info.path
+        if not self.handle:
+            try:
+                self.handle = _base.open_path(self.path) if self.path else None
+            except Exception:  # maybe the device wasn't set up
+                try:
+                    import time
+                    time.sleep(1)
+                    self.handle = _base.open_path(self.path) if self.path else None
+                except Exception:  # give up
+                    self.handle = None
+
         if receiver:
             if link_notification is not None:
                 self.online = not bool(ord(link_notification.data[0:1]) & 0x40)
@@ -114,17 +127,6 @@ def __init__(self, receiver, number, link_notification=None, info=None):
             # device is unpaired
             assert self.wpid is not None, 'failed to read wpid: device %d of %s' % (number, receiver)
 
-            self.path = _hid.find_paired_node(receiver.path, number, 1)
-            try:
-                self.handle = _hid.open_path(self.path) if self.path else None
-            except Exception:  # maybe the device wasn't set up
-                try:
-                    import time
-                    time.sleep(1)
-                    self.handle = _hid.open_path(self.path)
-                except Exception:  # give up
-                    self.handle = None
-
             self.descriptor = _descriptors.get_wpid(self.wpid)
             if self.descriptor is None:
                 # Last chance to correctly identify the device; many Nano receivers do not support this call.
@@ -133,8 +135,6 @@ def __init__(self, receiver, number, link_notification=None, info=None):
                     self._codename = codename
                     self.descriptor = _descriptors.get_codename(self._codename)
         else:
-            self.path = info.path
-            self.handle = _hid.open_path(self.path)
             self.online = None  # a direct connected device might not be online (as reported by user)
             self.product_id = info.product_id
             self.bluetooth = info.bus_id == 0x0005
@@ -275,7 +275,7 @@ def power_switch_location(self):
     def polling_rate(self):
         if not self._polling_rate:
             self.update_pairing_information()
-        if not self._polling_rate and self.protocol >= 2.0:
+        if self.protocol >= 2.0:
             rate = _hidpp20.get_polling_rate(self)
             self._polling_rate = rate if rate else self._polling_rate
         return self._polling_rate
@@ -457,7 +457,7 @@ def open(self, device_info):
         try:
             handle = _base.open_path(device_info.path)
             if handle:
-                return Device(None, None, info=device_info)
+                return Device(None, None, info=device_info, handle=handle, path=device_info.path)
         except OSError as e:
             _log.exception('open %s', device_info)
             if e.errno == _errno.EACCES:
diff --git a/lib/logitech_receiver/hidpp20.py b/lib/logitech_receiver/hidpp20.py
--- a/lib/logitech_receiver/hidpp20.py
+++ b/lib/logitech_receiver/hidpp20.py
@@ -88,6 +88,7 @@
     BACKLIGHT=0x1981,
     BACKLIGHT2=0x1982,
     BACKLIGHT3=0x1983,
+    ILLUMINATION=0x1990,
     PRESENTER_CONTROL=0x1A00,
     SENSOR_3D=0x1A01,
     REPROG_CONTROLS=0x1B00,
diff --git a/lib/logitech_receiver/receiver.py b/lib/logitech_receiver/receiver.py
--- a/lib/logitech_receiver/receiver.py
+++ b/lib/logitech_receiver/receiver.py
@@ -98,6 +98,8 @@ def __init__(self, handle, device_info):
 
     def close(self):
         handle, self.handle = self.handle, None
+        for _n, d in self._devices.items():
+            d.close()
         self._devices.clear()
         return (handle and _base.close(handle))
 


Test patch: