summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@digia.com>2014-05-26 14:56:49 +0200
committerAlex Blasche <alexander.blasche@digia.com>2014-05-26 14:56:49 +0200
commitf334ea4b196950c4074e7513626aabeef3d99d7f (patch)
treeccb07d59afbb60a92b80a061645c8013aab9b96c /src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
parent3910d9ffcc11db7b3beb7f2b6f0c1754103cfacb (diff)
parent552f1a164d627720942414915fb56ae7d3b7ef22 (diff)
Merge branch 'dev' into btle
Conflicts: examples/bluetooth/bluetooth.pro src/bluetooth/bluez/bluez.pri src/bluetooth/doc/src/bluetooth-index.qdoc src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp src/bluetooth/qbluetoothdeviceinfo.cpp src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp src/bluetooth/qbluetoothservicediscoveryagent_p.h src/bluetooth/qbluetoothservicediscoveryagent_qnx.cpp Change-Id: I88b22c51a4ee95b067ef8d2b2fddb5cbff4566f8
Diffstat (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp')
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp474
1 files changed, 425 insertions, 49 deletions
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
index fd0d9e3b..7d2f1b1c 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_bluez.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
@@ -48,31 +48,56 @@
#include "bluez/adapter_p.h"
#include "bluez/device_p.h"
#include "bluez/characteristic_p.h"
+#include "bluez/bluez5_helper_p.h"
+#include "bluez/objectmanager_p.h"
+#include "bluez/adapter1_bluez5_p.h"
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
#include <QtCore/QLoggingCategory>
#include <QtDBus/QDBusPendingCallWatcher>
-#include <QtCore/QUuid>
+#include <QtConcurrent/QtConcurrentRun>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
+static inline void convertAddress(quint64 from, quint8 (&to)[6])
+{
+ to[0] = (from >> 0) & 0xff;
+ to[1] = (from >> 8) & 0xff;
+ to[2] = (from >> 16) & 0xff;
+ to[3] = (from >> 24) & 0xff;
+ to[4] = (from >> 32) & 0xff;
+ to[5] = (from >> 40) & 0xff;
+}
+
QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(const QBluetoothAddress &deviceAdapter)
: error(QBluetoothServiceDiscoveryAgent::NoError), m_deviceAdapterAddress(deviceAdapter), state(Inactive), deviceDiscoveryAgent(0),
mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery), singleDevice(false),
- manager(0), adapter(0), device(0)
+ manager(0), managerBluez5(0), adapter(0), device(0)
{
- qRegisterMetaType<ServiceMap>("ServiceMap");
- qDBusRegisterMetaType<ServiceMap>();
+ if (isBluez5()) {
+ managerBluez5 = new OrgFreedesktopDBusObjectManagerInterface(
+ QStringLiteral("org.bluez"), QStringLiteral("/"),
+ QDBusConnection::systemBus());
+ qRegisterMetaType<QBluetoothServiceDiscoveryAgent::Error>("QBluetoothServiceDiscoveryAgent::Error");
+ } else {
+ qRegisterMetaType<ServiceMap>("ServiceMap");
+ qDBusRegisterMetaType<ServiceMap>();
- manager = new OrgBluezManagerInterface(QLatin1String("org.bluez"), QLatin1String("/"),
- QDBusConnection::systemBus());
+ manager = new OrgBluezManagerInterface(QStringLiteral("org.bluez"), QStringLiteral("/"),
+ QDBusConnection::systemBus());
+ }
}
QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate()
{
delete device;
delete manager;
+ delete managerBluez5;
delete adapter;
}
@@ -80,7 +105,12 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr
{
Q_Q(QBluetoothServiceDiscoveryAgent);
- qCDebug(QT_BT_BLUEZ) << "Full discovery on: " << address.toString();
+ qCDebug(QT_BT_BLUEZ) << "Discovery on: " << address.toString() << "Mode:" << DiscoveryMode();
+
+ if (managerBluez5) {
+ startBluez5(address);
+ return;
+ }
QDBusPendingReply<QDBusObjectPath> reply;
if (m_deviceAdapterAddress.isNull())
@@ -97,7 +127,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr
return;
}
- adapter = new OrgBluezAdapterInterface(QLatin1String("org.bluez"), reply.value().path(),
+ adapter = new OrgBluezAdapterInterface(QStringLiteral("org.bluez"), reply.value().path(),
QDBusConnection::systemBus());
if (m_deviceAdapterAddress.isNull()) {
@@ -118,6 +148,240 @@ void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &addr
}
+void QBluetoothServiceDiscoveryAgentPrivate::startBluez5(const QBluetoothAddress &address)
+{
+ Q_Q(QBluetoothServiceDiscoveryAgent);
+
+ if (foundHostAdapterPath.isEmpty()) {
+ // check that we match adapter addresses or use first if it wasn't specified
+
+ QDBusPendingReply<ManagedObjectList> reply = managerBluez5->GetManagedObjects();
+ reply.waitForFinished();
+ if (reply.isError()) {
+ discoveredDevices.clear();
+ error = QBluetoothServiceDiscoveryAgent::InputOutputError;
+ errorString = reply.error().message();
+ emit q->error(error);
+ _q_serviceDiscoveryFinished();
+ return;
+ }
+
+ const QString desiredAdapter = m_deviceAdapterAddress.toString();
+ foreach (const QDBusObjectPath &path, reply.value().keys()) {
+ const InterfaceList ifaceList = reply.value().value(path);
+ foreach (const QString &iface, ifaceList.keys()) {
+ if (iface == QStringLiteral("org.bluez.Adapter1")) {
+ if (m_deviceAdapterAddress.isNull()
+ || desiredAdapter == ifaceList.value(iface).
+ value(QStringLiteral("Address")).toString()) {
+ // use first adapter or we just matched one
+ foundHostAdapterPath = path.path();
+ }
+
+ if (!foundHostAdapterPath.isEmpty())
+ break;
+ }
+ }
+
+ if (!foundHostAdapterPath.isEmpty())
+ break;
+ }
+
+ if (foundHostAdapterPath.isEmpty()) {
+ // Cannot find a local adapter
+ // Abort any outstanding discoveries
+ discoveredDevices.clear();
+
+ error = QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError;
+ errorString = QBluetoothServiceDiscoveryAgent::tr("Cannot find local Bluetooth adapter");
+ emit q->error(error);
+ _q_serviceDiscoveryFinished();
+
+ return;
+ }
+ }
+
+ // ensure we didn't go offline yet
+ OrgBluezAdapter1Interface adapter(QStringLiteral("org.bluez"),
+ foundHostAdapterPath, QDBusConnection::systemBus());
+ if (!adapter.powered()) {
+ discoveredDevices.clear();
+
+ error = QBluetoothServiceDiscoveryAgent::PoweredOffError;
+ errorString = QBluetoothServiceDiscoveryAgent::tr("Local device is powered off");
+ emit q->error(error);
+
+ _q_serviceDiscoveryFinished();
+ return;
+ }
+
+ if (DiscoveryMode() == QBluetoothServiceDiscoveryAgent::MinimalDiscovery) {
+ performMinimalServiceDiscovery(address);
+ } else {
+ // we need to run the discovery in a different thread
+ // as it involves blocking calls
+ QtConcurrent::run(this, &QBluetoothServiceDiscoveryAgentPrivate::runSdpScan,
+ address, QBluetoothAddress(adapter.address()));
+ }
+}
+
+/*
+ * This function runs in a different thread. We need to be very careful what we
+ * access from here. That's why invokeMethod is used below.
+ */
+void QBluetoothServiceDiscoveryAgentPrivate::runSdpScan(
+ const QBluetoothAddress &remoteAddress, const QBluetoothAddress localAddress)
+{
+ Q_Q(QBluetoothServiceDiscoveryAgent);
+
+ // connect to SDP server
+ bdaddr_t local, remote;
+ convertAddress(localAddress.toUInt64(), local.b);
+ convertAddress(remoteAddress.toUInt64(), remote.b);
+
+ /* We use singleshot timer below because this function runs in a different
+ * thread than the rest of this class.
+ */
+
+ sdp_session_t *session = sdp_connect( &local, &remote, SDP_RETRY_IF_BUSY);
+ // try one more time if first attempt fails
+ if (!session)
+ session = sdp_connect( &local, &remote, SDP_RETRY_IF_BUSY);
+
+ qCDebug(QT_BT_BLUEZ) << "SDP for" << remoteAddress.toString() << session << qt_error_string(errno);
+ if (!session) {
+ if (singleDevice) {
+ // was sole device without result -> error
+ QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
+ Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
+ QBluetoothServiceDiscoveryAgent::InputOutputError),
+ Q_ARG(QString,
+ QBluetoothServiceDiscoveryAgent::tr("Unable to access device")),
+ Q_ARG(QStringList, QStringList()));
+ } else {
+ // go to next device
+ QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
+ Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
+ QBluetoothServiceDiscoveryAgent::NoError),
+ Q_ARG(QString, QString()),
+ Q_ARG(QStringList, QStringList()));
+ }
+
+ return;
+ }
+
+
+ // set the filter for service matches
+ uuid_t publicBrowseGroupUuid;
+ sdp_uuid16_create(&publicBrowseGroupUuid, QBluetoothUuid::PublicBrowseGroup);
+ sdp_list_t *serviceFilter;
+ serviceFilter = sdp_list_append(0, &publicBrowseGroupUuid);
+
+ uint32_t attributeRange = 0x0000ffff; //all attributes
+ sdp_list_t *attributes;
+ attributes = sdp_list_append(0, &attributeRange);
+
+ sdp_list_t* sdpResults;
+ int result = sdp_service_search_attr_req(session, serviceFilter, SDP_ATTR_REQ_RANGE,
+ attributes, &sdpResults);
+ sdp_list_free(attributes, 0);
+ sdp_list_free(serviceFilter, 0);
+
+ if (result != 0) {
+ qCDebug(QT_BT_BLUEZ) << "SDP search failed" << qt_error_string(errno);
+ sdp_close(session);
+ if (singleDevice) {
+ QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
+ Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
+ QBluetoothServiceDiscoveryAgent::InputOutputError),
+ Q_ARG(QString,
+ QBluetoothServiceDiscoveryAgent::tr("Unable to access device")),
+ Q_ARG(QStringList, QStringList()));
+ } else {
+ QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
+ Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
+ QBluetoothServiceDiscoveryAgent::NoError),
+ Q_ARG(QString, QString()),
+ Q_ARG(QStringList, QStringList()));
+ }
+ return;
+ }
+
+ qCDebug(QT_BT_BLUEZ) << "SDP search a success. Iterating results" << sdpResults;
+ QStringList xmlRecords;
+
+ // process the results
+ for ( ; sdpResults; sdpResults = sdpResults->next) {
+ sdp_record_t *record = (sdp_record_t *) sdpResults->data;
+
+ QByteArray xml = parseSdpRecord(record);
+ if (xml.isEmpty())
+ continue;
+
+ //qDebug() << xml;
+ xmlRecords.append(QString::fromUtf8(xml));
+ }
+
+ sdp_close(session);
+
+ QMetaObject::invokeMethod(q, "_q_finishSdpScan", Qt::QueuedConnection,
+ Q_ARG(QBluetoothServiceDiscoveryAgent::Error,
+ QBluetoothServiceDiscoveryAgent::NoError),
+ Q_ARG(QString, QString()),
+ Q_ARG(QStringList, xmlRecords));
+}
+
+void QBluetoothServiceDiscoveryAgentPrivate::_q_finishSdpScan(QBluetoothServiceDiscoveryAgent::Error errorCode,
+ const QString &errorDescription,
+ const QStringList &xmlRecords)
+{
+ Q_Q(QBluetoothServiceDiscoveryAgent);
+
+ if (errorCode != QBluetoothServiceDiscoveryAgent::NoError) {
+ qCWarning(QT_BT_BLUEZ) << "SDP search failed for"
+ << discoveredDevices.at(0).address().toString();
+ // We have an error which we need to indicate and stop further processing
+ discoveredDevices.clear();
+ error = errorCode;
+ errorString = errorDescription;
+ emit q->error(error);
+ } else if (!xmlRecords.isEmpty() && discoveryState() != Inactive) {
+ foreach (const QString &record, xmlRecords) {
+ bool isBtleService = false;
+ const QBluetoothServiceInfo serviceInfo = parseServiceXml(record, &isBtleService);
+
+ //apply uuidFilter
+ if (!uuidFilter.isEmpty()) {
+ bool serviceNameMatched = uuidFilter.contains(serviceInfo.serviceUuid());
+ bool serviceClassMatched = false;
+ foreach (const QBluetoothUuid &id, serviceInfo.serviceClassUuids()) {
+ if (uuidFilter.contains(id)) {
+ serviceClassMatched = true;
+ break;
+ }
+ }
+
+ if (!serviceNameMatched && !serviceClassMatched)
+ continue;
+ }
+
+ if (!serviceInfo.isValid())
+ continue;
+
+ if (!isDuplicatedService(serviceInfo)) {
+ discoveredServices.append(serviceInfo);
+ qCDebug(QT_BT_BLUEZ) << "Discovered services" << discoveredDevices.at(0).address().toString()
+ << serviceInfo.serviceName() << serviceInfo.serviceUuid()
+ << ">>>" << serviceInfo.serviceClassUuids();
+
+ emit q->serviceDiscovered(serviceInfo);
+ }
+ }
+ }
+
+ _q_serviceDiscoveryFinished();
+}
+
void QBluetoothServiceDiscoveryAgentPrivate::stop()
{
qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO << "Stop called";
@@ -156,7 +420,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_createdDevice(QDBusPendingCallWa
QDBusPendingReply<QDBusObjectPath> deviceObjectPath = *watcher;
if (deviceObjectPath.isError()) {
- if (deviceObjectPath.error().name() != QLatin1String("org.bluez.Error.AlreadyExists")) {
+ if (deviceObjectPath.error().name() != QStringLiteral("org.bluez.Error.AlreadyExists")) {
delete adapter;
adapter = 0;
_q_serviceDiscoveryFinished();
@@ -180,7 +444,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_createdDevice(QDBusPendingCallWa
}
}
- device = new OrgBluezDeviceInterface(QLatin1String("org.bluez"),
+ device = new OrgBluezDeviceInterface(QStringLiteral("org.bluez"),
deviceObjectPath.value().path(),
QDBusConnection::systemBus());
delete adapter;
@@ -255,19 +519,20 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_createdDevice(QDBusPendingCallWa
}
}
+// Bluez 4
void QBluetoothServiceDiscoveryAgentPrivate::_q_discoveredServices(QDBusPendingCallWatcher *watcher)
{
if (!device)
return;
qCDebug(QT_BT_BLUEZ) << Q_FUNC_INFO;
+ Q_Q(QBluetoothServiceDiscoveryAgent);
QDBusPendingReply<ServiceMap> reply = *watcher;
if (reply.isError()) {
qCDebug(QT_BT_BLUEZ) << "discoveredServices error: " << error << reply.error().message();
watcher->deleteLater();
if (singleDevice) {
- Q_Q(QBluetoothServiceDiscoveryAgent);
error = QBluetoothServiceDiscoveryAgent::UnknownError;
errorString = reply.error().message();
emit q->error(error);
@@ -282,60 +547,171 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_discoveredServices(QDBusPendingC
qCDebug(QT_BT_BLUEZ) << "Parsing xml" << discoveredDevices.at(0).address().toString() << discoveredDevices.count() << map.count();
- Q_Q(QBluetoothServiceDiscoveryAgent);
+
foreach (const QString &record, reply.value()) {
- QXmlStreamReader xml(record);
+ bool isBtleService = false;
+ const QBluetoothServiceInfo serviceInfo = parseServiceXml(record, &isBtleService);
- QBluetoothServiceInfo serviceInfo;
+ if (isBtleService) {
+ qCDebug(QT_BT_BLUEZ) << "Discovered BLE services" << discoveredDevices.at(0).address().toString()
+ << serviceInfo.serviceName() << serviceInfo.serviceUuid() << serviceInfo.serviceClassUuids();
+ continue;
+ }
+
+ if (!serviceInfo.isValid())
+ continue;
+
+ // Don't need to apply uuidFilter because Bluez 4 applies
+ // search pattern during DiscoverServices() call
+
+ Q_Q(QBluetoothServiceDiscoveryAgent);
+
+ if (!isDuplicatedService(serviceInfo)) {
+ discoveredServices.append(serviceInfo);
+ qCDebug(QT_BT_BLUEZ) << "Discovered services" << discoveredDevices.at(0).address().toString()
+ << serviceInfo.serviceName();
+ emit q->serviceDiscovered(serviceInfo);
+ }
+
+ // could stop discovery, check for state
+ if (discoveryState() == Inactive)
+ qCDebug(QT_BT_BLUEZ) << "Exit discovery after stop";
+ }
+
+ watcher->deleteLater();
+ delete device;
+ device = 0;
+
+ _q_serviceDiscoveryFinished();
+}
- bool btle = false; // Detecting potential BTLE services
- while (!xml.atEnd()) {
- xml.readNext();
+QBluetoothServiceInfo QBluetoothServiceDiscoveryAgentPrivate::parseServiceXml(
+ const QString& xmlRecord, bool *isBtleService)
+{
+ QXmlStreamReader xml(xmlRecord);
- if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == QStringLiteral("attribute")) {
- quint16 attributeId = xml.attributes().value(QStringLiteral("id")).toString().toUShort(0, 0);
+ QBluetoothServiceInfo serviceInfo;
+ serviceInfo.setDevice(discoveredDevices.at(0));
- if (xml.readNextStartElement()) {
- QVariant value = readAttributeValue(xml);
+ while (!xml.atEnd()) {
+ xml.readNext();
+
+ if (xml.tokenType() == QXmlStreamReader::StartElement &&
+ xml.name() == QLatin1String("attribute")) {
+ quint16 attributeId =
+ xml.attributes().value(QLatin1String("id")).toString().toUShort(0, 0);
+
+ if (xml.readNextStartElement()) {
+ QVariant value = readAttributeValue(xml);
+ if (isBtleService) {
if (attributeId == 1) {// Attribute with id 1 contains UUID of the service
- const QBluetoothServiceInfo::Sequence seq = value.value<QBluetoothServiceInfo::Sequence>();
+ const QBluetoothServiceInfo::Sequence seq =
+ value.value<QBluetoothServiceInfo::Sequence>();
for (int i = 0; i < seq.count(); i++) {
const QBluetoothUuid uuid = seq.at(i).value<QBluetoothUuid>();
if ((uuid.data1 & 0x1800) == 0x1800) {// We are taking into consideration that LE services starts at 0x1800
+ //TODO don't emit in the middle of nowhere
+ Q_Q(QBluetoothServiceDiscoveryAgent);
QLowEnergyServiceInfo leService(uuid);
leService.setDevice(discoveredDevices.at(0));
- btle = true;
+ *isBtleService = true;
emit q->serviceDiscovered(leService);
break;
}
}
}
- serviceInfo.setAttribute(attributeId, value);
}
+ serviceInfo.setAttribute(attributeId, value);
}
}
+ }
- if (!btle) {
- serviceInfo.setDevice(discoveredDevices.at(0));
- if (!serviceInfo.isValid())
- continue;
+ return serviceInfo;
+}
+
+void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress)
+{
+ if (foundHostAdapterPath.isEmpty()) {
+ _q_serviceDiscoveryFinished();
+ return;
+ }
+
+ Q_Q(QBluetoothServiceDiscoveryAgent);
+
+ QDBusPendingReply<ManagedObjectList> reply = managerBluez5->GetManagedObjects();
+ reply.waitForFinished();
+ if (reply.isError()) {
+ if (singleDevice) {
+ error = QBluetoothServiceDiscoveryAgent::InputOutputError;
+ errorString = reply.error().message();
+ emit q->error(error);
- discoveredServices.append(serviceInfo);
- qCDebug(QT_BT_BLUEZ) << "Discovered services" << discoveredDevices.at(0).address().toString();
- emit q->serviceDiscovered(serviceInfo);
}
+ _q_serviceDiscoveryFinished();
+ return;
+ }
- // could stop discovery, check for state
- if(discoveryState() == Inactive){
- qCDebug(QT_BT_BLUEZ) << "Exit discovery after stop";
- break;
+ QStringList uuidStrings;
+ foreach (const QDBusObjectPath &path, reply.value().keys()) {
+ const InterfaceList ifaceList = reply.value().value(path);
+ foreach (const QString &iface, ifaceList.keys()) {
+ if (iface == QStringLiteral("org.bluez.Device1")) {
+ const QVariantMap details = ifaceList.value(iface);
+ if (deviceAddress.toString()
+ == details.value(QStringLiteral("Address")).toString()) {
+ uuidStrings = details.value(QStringLiteral("UUIDs")).toStringList();
+ break;
+ }
+ }
}
+ if (!uuidStrings.isEmpty())
+ break;
}
- watcher->deleteLater();
- delete device;
- device = 0;
+ if (uuidStrings.isEmpty() || discoveredDevices.isEmpty()) {
+ // nothing found -> go to next uuid
+ _q_serviceDiscoveryFinished();
+ return;
+ }
+
+ qCDebug(QT_BT_BLUEZ) << "Minimal uuid list for" << deviceAddress.toString() << uuidStrings;
+
+ QBluetoothUuid uuid;
+ for (int i = 0; i < uuidStrings.count(); i++) {
+ uuid = QBluetoothUuid(uuidStrings.at(i));
+ if (uuid.isNull())
+ continue;
+
+ //apply uuidFilter
+ if (!uuidFilter.isEmpty() && !uuidFilter.contains(uuid))
+ continue;
+
+ // TODO deal with BTLE services under Bluez 5 -> right now they are normal services
+ QBluetoothServiceInfo serviceInfo;
+ serviceInfo.setDevice(discoveredDevices.at(0));
+
+ if (uuid.minimumSize() == 16) { // not derived from Bluetooth Base UUID
+ serviceInfo.setServiceUuid(uuid);
+ serviceInfo.setServiceName(QBluetoothServiceDiscoveryAgent::tr("Custom Service"));
+ } else {
+ // set uuid as service class id
+ QBluetoothServiceInfo::Sequence classId;
+ classId << QVariant::fromValue(uuid);
+ serviceInfo.setAttribute(QBluetoothServiceInfo::ServiceClassIds, classId);
+ QBluetoothUuid::ServiceClassUuid clsId
+ = static_cast<QBluetoothUuid::ServiceClassUuid>(uuid.data1 & 0xffff);
+ serviceInfo.setServiceName(QBluetoothUuid::serviceClassToString(clsId));
+ }
+
+ //don't include the service if we already discovered it before
+ if (!isDuplicatedService(serviceInfo)) {
+ discoveredServices << serviceInfo;
+ qCDebug(QT_BT_BLUEZ) << "Discovered services" << discoveredDevices.at(0).address().toString()
+ << serviceInfo.serviceName();
+ emit q->serviceDiscovered(serviceInfo);
+ }
+ }
_q_serviceDiscoveryFinished();
}
@@ -467,29 +843,29 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_discoveredGattCharacteristic(QDB
QVariant QBluetoothServiceDiscoveryAgentPrivate::readAttributeValue(QXmlStreamReader &xml)
{
if (xml.name() == QLatin1String("boolean")) {
- const QString value = xml.attributes().value(QLatin1String("value")).toString();
+ const QString value = xml.attributes().value(QStringLiteral("value")).toString();
xml.skipCurrentElement();
return value == QLatin1String("true");
} else if (xml.name() == QLatin1String("uint8")) {
- quint8 value = xml.attributes().value(QLatin1String("value")).toString().toUShort(0, 0);
+ quint8 value = xml.attributes().value(QStringLiteral("value")).toString().toUShort(0, 0);
xml.skipCurrentElement();
return value;
} else if (xml.name() == QLatin1String("uint16")) {
- quint16 value = xml.attributes().value(QLatin1String("value")).toString().toUShort(0, 0);
+ quint16 value = xml.attributes().value(QStringLiteral("value")).toString().toUShort(0, 0);
xml.skipCurrentElement();
return value;
} else if (xml.name() == QLatin1String("uint32")) {
- quint32 value = xml.attributes().value(QLatin1String("value")).toString().toUInt(0, 0);
+ quint32 value = xml.attributes().value(QStringLiteral("value")).toString().toUInt(0, 0);
xml.skipCurrentElement();
return value;
} else if (xml.name() == QLatin1String("uint64")) {
- quint64 value = xml.attributes().value(QLatin1String("value")).toString().toULongLong(0, 0);
+ quint64 value = xml.attributes().value(QStringLiteral("value")).toString().toULongLong(0, 0);
xml.skipCurrentElement();
return value;
} else if (xml.name() == QLatin1String("uuid")) {
QBluetoothUuid uuid;
- const QString value = xml.attributes().value(QLatin1String("value")).toString();
- if (value.startsWith(QLatin1String("0x"))) {
+ const QString value = xml.attributes().value(QStringLiteral("value")).toString();
+ if (value.startsWith(QStringLiteral("0x"))) {
if (value.length() == 6) {
quint16 v = value.toUShort(0, 0);
uuid = QBluetoothUuid(v);
@@ -503,8 +879,8 @@ QVariant QBluetoothServiceDiscoveryAgentPrivate::readAttributeValue(QXmlStreamRe
xml.skipCurrentElement();
return QVariant::fromValue(uuid);
} else if (xml.name() == QLatin1String("text")) {
- QString value = xml.attributes().value(QLatin1String("value")).toString();
- if (xml.attributes().value(QLatin1String("encoding")) == QLatin1String("hex"))
+ QString value = xml.attributes().value(QStringLiteral("value")).toString();
+ if (xml.attributes().value(QStringLiteral("encoding")) == QLatin1String("hex"))
value = QString::fromUtf8(QByteArray::fromHex(value.toLatin1()));
xml.skipCurrentElement();
return value;
@@ -520,7 +896,7 @@ QVariant QBluetoothServiceDiscoveryAgentPrivate::readAttributeValue(QXmlStreamRe
} else {
qCWarning(QT_BT_BLUEZ) << "unknown attribute type"
<< xml.name().toString()
- << xml.attributes().value(QLatin1String("value")).toString();
+ << xml.attributes().value(QStringLiteral("value")).toString();
xml.skipCurrentElement();
return QVariant();
}