correctly handle out-of-process pairing and unpairing

This commit is contained in:
Daniel Pavel 2013-07-05 16:04:45 +02:00
parent 3319feeb73
commit bd3198f6f0
6 changed files with 36 additions and 9 deletions

View File

@ -124,6 +124,8 @@ def _process_hidpp10_notification(device, status, n):
status.clear()
device.wpid = None
device.status = None
if device.number in device.receiver:
del device.receiver[device.number]
status.changed(active=False, alert=_ALERT.ALL, reason='unpaired')
else:
_log.warn("%s: disconnection with unknown type %02X: %s", device, n.address, n)

View File

@ -60,6 +60,8 @@ class PairedDevice(object):
self._polling_rate = None
self._power_switch = None
# _log.debug("new PairedDevice(%s, %s, %s)", receiver, number, link_notification)
if link_notification is not None:
self.online = bool(ord(link_notification.data[0:1]) & 0x40)
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)
if device_info is None:
_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._polling_rate = 0
@ -437,17 +439,25 @@ class Receiver(object):
return self.register_new_device(key)
def __delitem__(self, key):
key = int(key)
if self._devices.get(key) is None:
raise IndexError(key)
dev = self._devices[key]
if not dev:
if key in self._devices:
del self._devices[key]
return
action = 0x03
reply = self.write_register(_R.receiver_pairing, action, int(key))
reply = self.write_register(_R.receiver_pairing, action, key)
if reply:
# invalidate the device
dev.online = False
dev.wpid = None
del self._devices[key]
if key in self._devices:
del self._devices[key]
_log.warn("%s unpaired device %s", self, dev)
else:
_log.error("%s failed to unpair device %s", self, dev)

View File

@ -223,7 +223,12 @@ def pair_device(receiver, args):
receiver.set_lock(False, timeout=timeout)
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)
if n:
n = base.make_notification(*n)
@ -239,7 +244,8 @@ def pair_device(receiver, args):
dev = receiver.status.new_device
print ("Paired device %d: %s [%s:%s:%s]" % (dev.number, dev.name, dev.wpid, dev.codename, dev.serial))
else:
_fail(receiver.status[status.KEYS.ERROR])
error = receiver.status[status.KEYS.ERROR] or 'no device detected?'
_fail(error)
def unpair_device(receiver, args):

View File

@ -139,8 +139,9 @@ class ReceiverListener(_listener.EventsListener):
assert device.receiver == self.receiver
if not device:
# device was unpaired, and since the object is weakref'ed
# it won't be valid for much longer
# Device was unpaired, and isn't valid anymore.
# 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)
device = _ghost(device)
@ -190,7 +191,7 @@ class ReceiverListener(_listener.EventsListener):
if _log.isEnabledFor(_INFO):
_log.info("%s: pairing detected new device", self.receiver)
self.receiver.status.new_device = dev
else:
elif dev:
if dev.online is None:
dev.ping()

View File

@ -14,7 +14,7 @@ GLib.threads_init()
def _error_dialog(reason, object):
_log.error("%s: %s", reason, object)
_log.error("error: %s %s", reason, object)
if reason == 'permissions':
title = 'Permissions error'

View File

@ -6,6 +6,13 @@ from __future__ import absolute_import, division, print_function, unicode_litera
from gi.repository import Gtk, Gdk
from logging import getLogger
_log = getLogger(__name__)
del getLogger
#
#
#
def make(name, label, function, *args):
action = Gtk.Action(name, label, label, None)
@ -77,4 +84,5 @@ def unpair(window, device):
try:
del receiver[device_number]
except:
_log.exception("unpairing %s", device)
error_dialog('unpair', device)