Repository: pwr-Solaar/Solaar

Issue:
window.py:597:_update_details:AssertionError when trying to unpair devices from a Nano Receiver
**Information**
- Solaar version (`solaar --version` or `git describe --tags` if cloned from this repository): `1.0.4` with #996 applied
- Distribution: `Fedora 33`
- Kernel version (ex. `uname -srmo`): `5.9.14-200.fc33.x86_64`
- Output of `solaar show`:
```
Nano Receiver
  Device path  : /dev/hidraw9
  USB id       : 046d:C534
  Serial       : None
    Firmware   : 29.00.B0015
  Has 2 paired device(s) out of a maximum of 2.
  Has 18 successful pairing(s) remaining.
  Notifications: wireless, software present (0x000900)

  1: Wireless Keyboard MK270
     Device path  : /dev/hidraw10
     WPID         : 4023
     Codename     : MK270
     Kind         : keyboard
     Protocol     : HID++ 2.0
     Polling rate : 20 ms (50Hz)
     Serial number: 00000000
     Battery: unknown (device is offline).

  2: Wireless Mouse M150
     Device path  : /dev/hidraw11
     WPID         : 4022
     Codename     : M150
     Kind         : mouse
     Protocol     : HID++ 2.0
     Polling rate : 8 ms (125Hz)
     Serial number: 00000000
     Battery: unknown (device is offline).

Nano Receiver
  Device path  : /dev/hidraw4
  USB id       : 046d:C52E
  Serial       : 9CAE9170
    Firmware   : 15.00.B0048
  Has 2 paired device(s) out of a maximum of 2.
  Notifications: wireless, software present (0x000900)

  1: ? (101E)
     Device path  : None
     WPID         : 101E
     Codename     : ? (101E)
     Kind         : mouse
     Protocol     : unknown (device is offline)
     Polling rate : 8 ms (125Hz)
     Serial number: 489A0850
     The power switch is located on the (unknown).
     Battery: unknown (device is offline).

  2: ? (200E)
     Device path  : None
     WPID         : 200E
     Codename     : ? (200E)
     Kind         : keyboard
     Protocol     : unknown (device is offline)
     Polling rate : 20 ms (50Hz)
     Serial number: 489A0850
     The power switch is located on the (unknown).
     Battery: unknown (device is offline).
```

**Describe the bug**
Quoting from downstream [bug report](https://bugzilla.redhat.com/show_bug.cgi?id=1912132#c8):

> The error occurred every time I try to unpair on each of the following two receivers.
> Both sets of keyboard/mouse didn't work so I tried to unpair and then pair the devices again.

**Additional context**
Downstream bug report: Fedora [bug 1912132](https://bugzilla.redhat.com/show_bug.cgi?id=1912132).
```
Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/solaar/ui/window.py", line 597, in _update_details
    assert selected_device
AssertionError

Local variables in innermost frame:
button: <Gtk.ToggleButton object at 0x7f3d84bb84c0 (GtkToggleButton at 0x55c6d46e55d0)>
visible: True
_read_slow: <function _update_details.<locals>._read_slow at 0x7f3d84ba3820>
_details_items: <function _update_details.<locals>._details_items at 0x7f3d84ba39d0>
_make_text: <function _update_details.<locals>._make_text at 0x7f3d84ba38b0>
_set_details: <function _update_details.<locals>._set_details at 0x7f3d84ba3a60>
selected_device: <Device(1,None,? (101E),489A0850)>
```


Discussion:
Unfortunately I can't view the downstream report. 

Receiver C534 is a Nano receiver.  I have one of these receivers.  Solaar does not allow unpairing of devices from that receiver (since a few versions ago but certainly 1.0.4 does not allow unpairing).  Instead some models of Logitech devices (probably only MK270 keyboards and M150 mice, but maybe also M185 mice) can be paired with the receiver, replacing a currently-paired device.  This receiver allows only a limited number of these repairings.  From the information above it appears that there have been no such repairings for this receiver.

Receiver C52E is also a Nano receiver.  Unpairing should also not be possible on this receiver.  I don't know which devices can be paired with this receiver nor whether it has a limited number of such pairings.  This receiver may also be an old model.  Old Logitech receiver models may exhibit quirks that Solaar does not know about and thus may cause problems for Solaar.

So I'm not sure what the reporter actually did.  It appears that Solaar is making an assumption that is not always correct, but without knowing more about the situation I cannot determine how to fix it.

To allow diagnosis of this issue the user should try with debugging turned on (`-dd` flag) and try the operation that caused the fault.   Also provide screenshots of the Solaar main window showing detailed information about the MK270 keyboard.


If the keyboard and mouse that were obtained with the C534 receiver are the ones that are in use, it is very likely that the receiver still is paired with them.   Ensuring that the mouse and keyboard are powered on and that their batteries have sufficient power should allow them to be used.  If this is not the case, it is very likely that there is a hardware fault in either the receiver or the mouse and the keyboard.
@pfps Thanks for the reply and sorry about the inaccessible downstream report. It was filed by a semi-automated tool and it marks the ticket private by default out of abundance of caution because the attachments may contain sensitive data. If the reporter doesn't unmark the private flag, it remains so and I can't lift it. I copied your reply downstream and hope to hear from the reporter soon. I asked the reporter to respond here directly, but I can't guarantee they will.
I forgot to add that the reporter should include the debugging output from Solaar.
The C534 was paired with k220 nd M150, the C52E was paired with K830.
Nothing worked, so I decided to try to unpair them and then pair them again, and this is where the initial crash happened.

This is the output when I'm running the program with `-dd`:
[solaar debug.txt](https://github.com/pwr-Solaar/Solaar/files/5900659/solaar.debug.txt)

Two screenshots:
![Screenshot from 2021-01-31 23-08-23](https://user-images.githubusercontent.com/15404/106398282-a3810100-641a-11eb-80e6-a5d545b111ec.png)
![Screenshot from 2021-01-31 23-08-35](https://user-images.githubusercontent.com/15404/106398283-a4199780-641a-11eb-9476-8e070c49efbc.png)

I also have another ABRT "Solaar quit unexpectedly" error:  
```
window.py:200:_unpair_current_device:AssertionError

Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/solaar/ui/window.py", line 200, in _unpair_current_device
    assert bool(device)
AssertionError

Local variables in innermost frame:
trigger: <Gtk.Button object at 0x7f93e6adcc40 (GtkButton at 0x564cb90e0a40)>
device: <Device(2,None,? (200E),489A0850)>
```

Resolving patch:
diff --git a/lib/logitech_receiver/base_usb.py b/lib/logitech_receiver/base_usb.py
--- a/lib/logitech_receiver/base_usb.py
+++ b/lib/logitech_receiver/base_usb.py
@@ -33,6 +33,7 @@
 
 # max_devices is only used for receivers that do not support reading from _R.receiver_info offset 0x03, default to 1
 # may_unpair is only used for receivers that do not support reading from _R.receiver_info offset 0x03, default to False
+# unpair is for receivers that do support reading from _R.receiver_info offset 0x03, no default
 ## should this last be changed so that may_unpair is used for all receivers? writing to _R.receiver_pairing doesn't seem right
 # re_pairs determines whether a receiver pairs by replacing existing pairings, default to False
 ## currently only one receiver is so marked - should there be more?
@@ -58,6 +59,17 @@
     're_pairs': True
 }
 
+_nano_receiver_no_unpair = lambda product_id: {
+    'vendor_id': 0x046d,
+    'product_id': product_id,
+    'usb_interface': 1,
+    'hid_driver': _DRIVER,  # noqa: F821
+    'name': 'Nano Receiver',
+    'may_unpair': False,
+    'unpair': False,
+    're_pairs': True
+}
+
 _nano_receiver_max2 = lambda product_id: {
     'vendor_id': 0x046d,
     'product_id': product_id,
@@ -125,7 +137,7 @@
 NANO_RECEIVER_C521 = _nano_receiver(0xc521)
 NANO_RECEIVER_C525 = _nano_receiver(0xc525)
 NANO_RECEIVER_C526 = _nano_receiver(0xc526)
-NANO_RECEIVER_C52e = _nano_receiver(0xc52e)
+NANO_RECEIVER_C52e = _nano_receiver_no_unpair(0xc52e)
 NANO_RECEIVER_C531 = _nano_receiver(0xc531)
 NANO_RECEIVER_C534 = _nano_receiver_max2(0xc534)
 NANO_RECEIVER_C537 = _nano_receiver(0xc537)
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
@@ -69,7 +69,10 @@ def __init__(self, handle, device_info):
                 self.max_devices = product_info.get('max_devices', 1)
             # TODO _properly_ figure out which receivers do and which don't support unpairing
             # This code supposes that receivers that don't unpair support a pairing request for device index 0
-            self.may_unpair = self.write_register(_R.receiver_pairing) is None
+            if 'unpair' in product_info:
+                self.may_unpair = product_info['unpair']
+            else:
+                self.may_unpair = self.write_register(_R.receiver_pairing) is None
         else:  # handle receivers that don't have a serial number specially (i.e., c534)
             self.serial = None
             self.max_devices = product_info.get('max_devices', 1)


Test patch: