correctly handle out-of-process pairing and unpairing
This commit is contained in:
parent
3319feeb73
commit
bd3198f6f0
|
@ -124,6 +124,8 @@ def _process_hidpp10_notification(device, status, n):
|
||||||
status.clear()
|
status.clear()
|
||||||
device.wpid = None
|
device.wpid = None
|
||||||
device.status = None
|
device.status = None
|
||||||
|
if device.number in device.receiver:
|
||||||
|
del device.receiver[device.number]
|
||||||
status.changed(active=False, alert=_ALERT.ALL, reason='unpaired')
|
status.changed(active=False, alert=_ALERT.ALL, reason='unpaired')
|
||||||
else:
|
else:
|
||||||
_log.warn("%s: disconnection with unknown type %02X: %s", device, n.address, n)
|
_log.warn("%s: disconnection with unknown type %02X: %s", device, n.address, n)
|
||||||
|
|
|
@ -60,6 +60,8 @@ class PairedDevice(object):
|
||||||
self._polling_rate = None
|
self._polling_rate = None
|
||||||
self._power_switch = None
|
self._power_switch = None
|
||||||
|
|
||||||
|
# _log.debug("new PairedDevice(%s, %s, %s)", receiver, number, link_notification)
|
||||||
|
|
||||||
if link_notification is not None:
|
if link_notification is not None:
|
||||||
self.online = bool(ord(link_notification.data[0:1]) & 0x40)
|
self.online = bool(ord(link_notification.data[0:1]) & 0x40)
|
||||||
self.wpid = _strhex(link_notification.data[2:3] + link_notification.data[1:2])
|
self.wpid = _strhex(link_notification.data[2:3] + link_notification.data[1:2])
|
||||||
|
@ -81,7 +83,7 @@ class PairedDevice(object):
|
||||||
device_info = self.receiver.read_register(_R.receiver_info, 0x04)
|
device_info = self.receiver.read_register(_R.receiver_info, 0x04)
|
||||||
if device_info is None:
|
if device_info is None:
|
||||||
_log.error("failed to read Nano wpid for device %d of %s", number, receiver)
|
_log.error("failed to read Nano wpid for device %d of %s", number, receiver)
|
||||||
raise _base.NoSuchDevice(nuber=number, receiver=receiver, error="read Nano wpid")
|
raise _base.NoSuchDevice(number=number, receiver=receiver, error="read Nano wpid")
|
||||||
|
|
||||||
self.wpid = _strhex(device_info[3:5])
|
self.wpid = _strhex(device_info[3:5])
|
||||||
self._polling_rate = 0
|
self._polling_rate = 0
|
||||||
|
@ -437,17 +439,25 @@ class Receiver(object):
|
||||||
return self.register_new_device(key)
|
return self.register_new_device(key)
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
|
key = int(key)
|
||||||
|
|
||||||
if self._devices.get(key) is None:
|
if self._devices.get(key) is None:
|
||||||
raise IndexError(key)
|
raise IndexError(key)
|
||||||
|
|
||||||
dev = self._devices[key]
|
dev = self._devices[key]
|
||||||
|
if not dev:
|
||||||
|
if key in self._devices:
|
||||||
|
del self._devices[key]
|
||||||
|
return
|
||||||
|
|
||||||
action = 0x03
|
action = 0x03
|
||||||
reply = self.write_register(_R.receiver_pairing, action, int(key))
|
reply = self.write_register(_R.receiver_pairing, action, key)
|
||||||
if reply:
|
if reply:
|
||||||
# invalidate the device
|
# invalidate the device
|
||||||
dev.online = False
|
dev.online = False
|
||||||
dev.wpid = None
|
dev.wpid = None
|
||||||
del self._devices[key]
|
if key in self._devices:
|
||||||
|
del self._devices[key]
|
||||||
_log.warn("%s unpaired device %s", self, dev)
|
_log.warn("%s unpaired device %s", self, dev)
|
||||||
else:
|
else:
|
||||||
_log.error("%s failed to unpair device %s", self, dev)
|
_log.error("%s failed to unpair device %s", self, dev)
|
||||||
|
|
|
@ -223,7 +223,12 @@ def pair_device(receiver, args):
|
||||||
receiver.set_lock(False, timeout=timeout)
|
receiver.set_lock(False, timeout=timeout)
|
||||||
print ("Pairing: turn your new device on (timing out in", timeout, "seconds).")
|
print ("Pairing: turn your new device on (timing out in", timeout, "seconds).")
|
||||||
|
|
||||||
while receiver.status.lock_open:
|
# the lock-open notification may come slightly later, wait for it a bit
|
||||||
|
from time import time as timestamp
|
||||||
|
pairing_start = timestamp()
|
||||||
|
patience = 5 # seconds
|
||||||
|
|
||||||
|
while receiver.status.lock_open or timestamp() - pairing_start < patience:
|
||||||
n = base.read(receiver.handle)
|
n = base.read(receiver.handle)
|
||||||
if n:
|
if n:
|
||||||
n = base.make_notification(*n)
|
n = base.make_notification(*n)
|
||||||
|
@ -239,7 +244,8 @@ def pair_device(receiver, args):
|
||||||
dev = receiver.status.new_device
|
dev = receiver.status.new_device
|
||||||
print ("Paired device %d: %s [%s:%s:%s]" % (dev.number, dev.name, dev.wpid, dev.codename, dev.serial))
|
print ("Paired device %d: %s [%s:%s:%s]" % (dev.number, dev.name, dev.wpid, dev.codename, dev.serial))
|
||||||
else:
|
else:
|
||||||
_fail(receiver.status[status.KEYS.ERROR])
|
error = receiver.status[status.KEYS.ERROR] or 'no device detected?'
|
||||||
|
_fail(error)
|
||||||
|
|
||||||
|
|
||||||
def unpair_device(receiver, args):
|
def unpair_device(receiver, args):
|
||||||
|
|
|
@ -139,8 +139,9 @@ class ReceiverListener(_listener.EventsListener):
|
||||||
|
|
||||||
assert device.receiver == self.receiver
|
assert device.receiver == self.receiver
|
||||||
if not device:
|
if not device:
|
||||||
# device was unpaired, and since the object is weakref'ed
|
# Device was unpaired, and isn't valid anymore.
|
||||||
# it won't be valid for much longer
|
# We replace it with a ghost so that the UI has something to work
|
||||||
|
# with while cleaning up.
|
||||||
_log.warn("device %s was unpaired, ghosting", device)
|
_log.warn("device %s was unpaired, ghosting", device)
|
||||||
device = _ghost(device)
|
device = _ghost(device)
|
||||||
|
|
||||||
|
@ -190,7 +191,7 @@ class ReceiverListener(_listener.EventsListener):
|
||||||
if _log.isEnabledFor(_INFO):
|
if _log.isEnabledFor(_INFO):
|
||||||
_log.info("%s: pairing detected new device", self.receiver)
|
_log.info("%s: pairing detected new device", self.receiver)
|
||||||
self.receiver.status.new_device = dev
|
self.receiver.status.new_device = dev
|
||||||
else:
|
elif dev:
|
||||||
if dev.online is None:
|
if dev.online is None:
|
||||||
dev.ping()
|
dev.ping()
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ GLib.threads_init()
|
||||||
|
|
||||||
|
|
||||||
def _error_dialog(reason, object):
|
def _error_dialog(reason, object):
|
||||||
_log.error("%s: %s", reason, object)
|
_log.error("error: %s %s", reason, object)
|
||||||
|
|
||||||
if reason == 'permissions':
|
if reason == 'permissions':
|
||||||
title = 'Permissions error'
|
title = 'Permissions error'
|
||||||
|
|
|
@ -6,6 +6,13 @@ from __future__ import absolute_import, division, print_function, unicode_litera
|
||||||
|
|
||||||
from gi.repository import Gtk, Gdk
|
from gi.repository import Gtk, Gdk
|
||||||
|
|
||||||
|
from logging import getLogger
|
||||||
|
_log = getLogger(__name__)
|
||||||
|
del getLogger
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
def make(name, label, function, *args):
|
def make(name, label, function, *args):
|
||||||
action = Gtk.Action(name, label, label, None)
|
action = Gtk.Action(name, label, label, None)
|
||||||
|
@ -77,4 +84,5 @@ def unpair(window, device):
|
||||||
try:
|
try:
|
||||||
del receiver[device_number]
|
del receiver[device_number]
|
||||||
except:
|
except:
|
||||||
|
_log.exception("unpairing %s", device)
|
||||||
error_dialog('unpair', device)
|
error_dialog('unpair', device)
|
||||||
|
|
Loading…
Reference in New Issue