From 7326f1789db31fb69c98d7e37a25f08549c73454 Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Mon, 17 Feb 2014 11:54:35 +0100 Subject: Fix some BTLE service discovery issues 1.) In Bluez avoid incomplete and/or premature finish of service discovery process. 2.) Add Testcode for QBluetoothServiceInfo::serviceDiscovered(QLowEnergyServiceInfo) to bttestui application Change-Id: I037a6303862dcf2e29aef4b761731b13c85b29aa Reviewed-by: Nedim Hadzic Reviewed-by: Alex Blasche --- .../qbluetoothservicediscoveryagent_bluez.cpp | 41 ++++++++++++---------- tests/bttestui/btlocaldevice.cpp | 14 +++++++- tests/bttestui/btlocaldevice.h | 1 + 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp index 9c65f056..c3a7a3e4 100644 --- a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp +++ b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp @@ -176,28 +176,26 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_createdDevice(QDBusPendingCallWa delete adapter; adapter = 0; + QVariantMap deviceProperties; + QString classType; QDBusPendingReply deviceReply = device->GetProperties(); deviceReply.waitForFinished(); - if (deviceReply.isError()) { - qCDebug(QT_BT_BLUEZ) << "GetProperties error: " << error << deviceObjectPath.error().name(); - //TODO if we abort here who deletes device? - //TODO what happens to still pending discoveredDevices? - return; + if (!deviceReply.isError()) { + deviceProperties = deviceReply.value(); + classType = deviceProperties.value(QStringLiteral("Class")).toString(); } - QVariantMap deviceProperties = deviceReply.value(); - QString classType = deviceProperties.value(QStringLiteral("Class")).toString(); + /* * Low Energy services in bluez are represented as the list of the paths that can be * accessed with org.bluez.Characteristic */ //QDBusArgument services = v.value(QLatin1String("Services")).value(); const QStringList deviceUuids = deviceProperties.value(QStringLiteral("UUIDs")).toStringList(); - for (int i = 0; i < deviceUuids.size(); i++) { QString b = deviceUuids.at(i); b = b.remove(QLatin1Char('{')).remove(QLatin1Char('}')); - //TODO this should be bit field and not String operations + //TODO this should be bit field and not string operations const QString leServiceCheck = QString(b.at(4)) + QString(b.at(5)); /* * In this part we want to emit only Bluetooth Low Energy service. BLE services @@ -207,27 +205,34 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_createdDevice(QDBusPendingCallWa //TODO where is the uuidFilter match -> uuidFilter could contain a BLE uuid if ((leServiceCheck == QStringLiteral("18") || b.contains(QStringLiteral("000000000000"))) && uuidFilter.size() == 0) { + qCDebug(QT_BT_BLUEZ) << "Discovered BLE service" << deviceUuids.at(i) << leServiceCheck << uuidFilter.size() << b; QBluetoothUuid uuid(b); QLowEnergyServiceInfo lowEnergyService(uuid); //TODO Fix m_DeviceAdapterAddress may not be the actual address lowEnergyService.d_ptr->adapterAddress = m_deviceAdapterAddress; lowEnergyService.setDevice(discoveredDevices.at(0)); - q_ptr->serviceDiscovered(lowEnergyService); + emit q->serviceDiscovered(lowEnergyService); } - } + /* * Bluez v4.1 does not have extra bit which gives information if device is Bluetooth * Low Energy device and the way to discover it is with Class property of the Bluetooth device. * Low Energy devices do not have property Class. - * In case we have have LE device finish service discovery; otherwise search for regular services. + * In case we have LE device finish service discovery; otherwise search for regular services. */ - if (classType.isEmpty()) //is BLE device - //TODO is is not correct why finish here? We have other devices to discover... - //finished signal should not be emitted by this class - //Furthermore there is the assumption here that a BLE device cannot have std Bt service. Is that true? - q_ptr->finished(); - else { + if (classType.isEmpty()) { //is BLE device or device properties above not retrievable + qCDebug(QT_BT_BLUEZ) << "Discovered BLE-only device. Normal service discovery skipped."; + delete device; + device = 0; + + if (singleDevice && deviceReply.isError()) { + error = QBluetoothServiceDiscoveryAgent::InputOutputError; + errorString = QBluetoothServiceDiscoveryAgent::tr("Unable to access device"); + emit q->error(error); + } + _q_serviceDiscoveryFinished(); + } else { QString pattern; foreach (const QBluetoothUuid &uuid, uuidFilter) pattern += uuid.toString().remove(QLatin1Char('{')).remove(QLatin1Char('}')) + QLatin1Char(' '); diff --git a/tests/bttestui/btlocaldevice.cpp b/tests/bttestui/btlocaldevice.cpp index b73a2a73..60df26d5 100644 --- a/tests/bttestui/btlocaldevice.cpp +++ b/tests/bttestui/btlocaldevice.cpp @@ -80,6 +80,8 @@ BtLocalDevice::BtLocalDevice(QObject *parent) : serviceAgent = new QBluetoothServiceDiscoveryAgent(this); connect(serviceAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)), this, SLOT(serviceDiscovered(QBluetoothServiceInfo))); + connect(serviceAgent, SIGNAL(serviceDiscovered(QLowEnergyServiceInfo)), + this, SLOT(leServiceDiscovered(QLowEnergyServiceInfo))); connect(serviceAgent, SIGNAL(finished()), this, SLOT(serviceDiscoveryFinished())); connect(serviceAgent, SIGNAL(canceled()), @@ -271,9 +273,13 @@ void BtLocalDevice::stopServiceDiscovery() void BtLocalDevice::serviceDiscovered(const QBluetoothServiceInfo &info) { + QStringList classIds; + const QList classIdsList = info.serviceClassUuids(); + foreach (const QBluetoothUuid &id, classIdsList) + classIds.append(id.toString()); qDebug() << "$$ Found new service" << info.device().address().toString() - << info.serviceUuid() << info.serviceName() << info.serviceDescription(); + << info.serviceUuid() << info.serviceName() << info.serviceDescription() << classIds; if (info.serviceUuid() == QBluetoothUuid(QString(TEST_SERVICE_UUID)) || info.serviceClassUuids().contains(QBluetoothUuid(QString(TEST_SERVICE_UUID)))) @@ -294,6 +300,12 @@ void BtLocalDevice::serviceDiscovered(const QBluetoothServiceInfo &info) } } +void BtLocalDevice::leServiceDiscovered(const QLowEnergyServiceInfo &info) +{ + qDebug() << "$$ Found new BTLE service" << info.device().address().toString() + << info.uuid() << info.name(); +} + void BtLocalDevice::serviceDiscoveryFinished() { qDebug() << "###### Service Discovery Finished"; diff --git a/tests/bttestui/btlocaldevice.h b/tests/bttestui/btlocaldevice.h index 759599b7..a9571ecc 100644 --- a/tests/bttestui/btlocaldevice.h +++ b/tests/bttestui/btlocaldevice.h @@ -89,6 +89,7 @@ public slots: void startServiceDiscovery(bool isMinimalDiscovery); void stopServiceDiscovery(); void serviceDiscovered(const QBluetoothServiceInfo &info); + void leServiceDiscovered(const QLowEnergyServiceInfo &leInfo); void serviceDiscoveryFinished(); void serviceDiscoveryCanceled(); void serviceDiscoveryError(QBluetoothServiceDiscoveryAgent::Error error); -- cgit v1.2.3