tuhi: handle cold-plugged devices

When bluez restarts (or the tuhi daemon restarts), the values we have
in the bluez device's field ManufacturerData are quite not accurate.

When bluez restarts they are empty, and if the last time we saw the
device was for the pairing process, the device will still be marked
as in the pairing mode.

So we should mark the cold-plug sequence differently from the hot-plug
one, and we should be more confident in the current configuration we
have stored to export the currently known devices over dbus.

Fixes #13
This commit is contained in:
Benjamin Tissoires 2018-01-22 10:39:23 +01:00 committed by Peter Hutterer
parent ea890958d6
commit ca82af78de
2 changed files with 26 additions and 16 deletions

22
tuhi.py
View File

@ -253,18 +253,28 @@ class Tuhi(GObject.Object):
# restart discovery if some users are already in the listening mode # restart discovery if some users are already in the listening mode
self._on_listening_updated(None, None) self._on_listening_updated(None, None)
def _on_bluez_device_updated(self, manager, bluez_device): def _on_bluez_device_updated(self, manager, bluez_device, event=True):
if bluez_device.vendor_id != WACOM_COMPANY_ID:
return
pairing_device = Tuhi._is_pairing_device(bluez_device)
uuid = None uuid = None
if not pairing_device: # check if the device is already known by us
try: try:
config = self.config.devices[bluez_device.address] config = self.config.devices[bluez_device.address]
uuid = config['uuid'] uuid = config['uuid']
except KeyError: except KeyError:
pass
if uuid is None and bluez_device.vendor_id != WACOM_COMPANY_ID:
return
# if event is set, the device has been 'hotplugged' in the bluez stack
# so ManufacturerData is reliable. Else, consider the device not in
# the pairing mode
pairing_device = False
if event:
pairing_device = Tuhi._is_pairing_device(bluez_device)
if not pairing_device:
if uuid is None:
logger.info('{}: device without config, must be paired first'.format(bluez_device.address)) logger.info('{}: device without config, must be paired first'.format(bluez_device.address))
return return
logger.debug('{}: UUID {}'.format(bluez_device.address, uuid)) logger.debug('{}: UUID {}'.format(bluez_device.address, uuid))

View File

@ -265,7 +265,7 @@ class BlueZDeviceManager(GObject.Object):
""" """
__gsignals__ = { __gsignals__ = {
"device-added": "device-added":
(GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)), (GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT, GObject.TYPE_BOOLEAN)),
"device-updated": "device-updated":
(GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)), (GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)),
"discovery-started": "discovery-started":
@ -300,7 +300,7 @@ class BlueZDeviceManager(GObject.Object):
# object path length and process them in order, this way we're # object path length and process them in order, this way we're
# guaranteed that the objects we need already exist. # guaranteed that the objects we need already exist.
for obj in self._om.get_objects(): for obj in self._om.get_objects():
self._process_object(obj) self._process_object(obj, event=False)
def _discovery_timeout_expired(self): def _discovery_timeout_expired(self):
self.stop_discovery() self.stop_discovery()
@ -382,7 +382,7 @@ class BlueZDeviceManager(GObject.Object):
"""Callback for ObjectManager's object-added""" """Callback for ObjectManager's object-added"""
objpath = obj.get_object_path() objpath = obj.get_object_path()
logger.debug('Object added: {}'.format(objpath)) logger.debug('Object added: {}'.format(objpath))
needs_resolve = self._process_object(obj) needs_resolve = self._process_object(obj, event=True)
# we had at least one characteristic added, need to resolve the # we had at least one characteristic added, need to resolve the
# devices. # devices.
@ -396,13 +396,13 @@ class BlueZDeviceManager(GObject.Object):
objpath = obj.get_object_path() objpath = obj.get_object_path()
logger.debug('Object removed: {}'.format(objpath)) logger.debug('Object removed: {}'.format(objpath))
def _process_object(self, obj): def _process_object(self, obj, event=True):
"""Process a single DBusProxyObject""" """Process a single DBusProxyObject"""
if obj.get_interface(ORG_BLUEZ_ADAPTER1) is not None: if obj.get_interface(ORG_BLUEZ_ADAPTER1) is not None:
self._process_adapter(obj) self._process_adapter(obj)
elif obj.get_interface(ORG_BLUEZ_DEVICE1) is not None: elif obj.get_interface(ORG_BLUEZ_DEVICE1) is not None:
self._process_device(obj) self._process_device(obj, event)
elif obj.get_interface(ORG_BLUEZ_GATTCHARACTERISTIC1) is not None: elif obj.get_interface(ORG_BLUEZ_GATTCHARACTERISTIC1) is not None:
return True return True
@ -412,11 +412,11 @@ class BlueZDeviceManager(GObject.Object):
objpath = obj.get_object_path() objpath = obj.get_object_path()
logger.debug('Adapter: {}'.format(objpath)) logger.debug('Adapter: {}'.format(objpath))
def _process_device(self, obj): def _process_device(self, obj, event=True):
dev = BlueZDevice(self._om, obj) dev = BlueZDevice(self._om, obj)
self.devices.append(dev) self.devices.append(dev)
dev.connect("updated", self._on_device_updated) dev.connect("updated", self._on_device_updated)
self.emit("device-added", dev) self.emit("device-added", dev, event)
def _process_characteristic(self, obj): def _process_characteristic(self, obj):
objpath = obj.get_object_path() objpath = obj.get_object_path()