summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bluetooth/android/devicediscoverybroadcastreceiver.cpp23
-rw-r--r--src/bluetooth/bluez/bluez5_helper.cpp2
-rw-r--r--src/bluetooth/bluez/bluez5_helper_p.h3
-rw-r--r--src/bluetooth/bluez/device1_bluez5_p.h6
-rw-r--r--src/bluetooth/bluez/org.bluez.Device1.xml4
-rw-r--r--src/bluetooth/darwin/btledeviceinquiry.mm16
-rw-r--r--src/bluetooth/darwin/btutility.mm8
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp7
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp14
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm8
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_p.h4
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp83
-rw-r--r--src/bluetooth/qbluetoothdeviceinfo.cpp90
-rw-r--r--src/bluetooth/qbluetoothdeviceinfo.h7
-rw-r--r--src/bluetooth/qbluetoothdeviceinfo_p.h1
15 files changed, 251 insertions, 25 deletions
diff --git a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
index 869d948b..228cdb0d 100644
--- a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
+++ b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
@@ -250,6 +250,9 @@ enum ADType {
ADType128BitUuidComplete = 0x07,
ADTypeShortenedLocalName = 0x08,
ADTypeCompleteLocalName = 0x09,
+ ADTypeServiceData16Bit = 0x16,
+ ADTypeServiceData32Bit = 0x20,
+ ADTypeServiceData128Bit = 0x21,
ADTypeManufacturerSpecificData = 0xff,
// .. more will be added when required
};
@@ -542,6 +545,25 @@ QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(const
foundService =
QBluetoothUuid(qToBigEndian<quint128>(qFromLittleEndian<quint128>(dataPtr)));
break;
+ case ADTypeServiceData16Bit:
+ if (nBytes >= 3) {
+ info.setServiceData(QBluetoothUuid(qFromLittleEndian<quint16>(dataPtr)),
+ QByteArray(dataPtr + 2, nBytes - 3));
+ }
+ break;
+ case ADTypeServiceData32Bit:
+ if (nBytes >= 5) {
+ info.setServiceData(QBluetoothUuid(qFromLittleEndian<quint32>(dataPtr)),
+ QByteArray(dataPtr + 4, nBytes - 5));
+ }
+ break;
+ case ADTypeServiceData128Bit:
+ if (nBytes >= 17) {
+ info.setServiceData(QBluetoothUuid(qToBigEndian<quint128>(
+ qFromLittleEndian<quint128>(dataPtr))),
+ QByteArray(dataPtr + 16, nBytes - 17));
+ }
+ break;
case ADTypeManufacturerSpecificData:
if (nBytes >= 3) {
info.setManufacturerData(qFromLittleEndian<quint16>(dataPtr),
@@ -592,4 +614,3 @@ QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(const
}
QT_END_NAMESPACE
-
diff --git a/src/bluetooth/bluez/bluez5_helper.cpp b/src/bluetooth/bluez/bluez5_helper.cpp
index 8133b36a..d4af7d51 100644
--- a/src/bluetooth/bluez/bluez5_helper.cpp
+++ b/src/bluetooth/bluez/bluez5_helper.cpp
@@ -75,6 +75,7 @@ void initializeBluez5()
qDBusRegisterMetaType<InterfaceList>();
qDBusRegisterMetaType<ManagedObjectList>();
qDBusRegisterMetaType<ManufacturerDataList>();
+ qDBusRegisterMetaType<ServiceDataList>();
QDBusPendingReply<ManagedObjectList> reply = manager.GetManagedObjects();
reply.waitForFinished();
@@ -190,6 +191,7 @@ QVersionNumber bluetoothdVersion()
qDBusRegisterMetaType<InterfaceList>();
qDBusRegisterMetaType<ManagedObjectList>();
qDBusRegisterMetaType<ManufacturerDataList>();
+ qDBusRegisterMetaType<ServiceDataList>();
qCDebug(QT_BT_BLUEZ) << "Detecting bluetoothd version";
//Order of matching
diff --git a/src/bluetooth/bluez/bluez5_helper_p.h b/src/bluetooth/bluez/bluez5_helper_p.h
index 58b87da8..7f3d1c04 100644
--- a/src/bluetooth/bluez/bluez5_helper_p.h
+++ b/src/bluetooth/bluez/bluez5_helper_p.h
@@ -53,15 +53,18 @@
#include <QtCore/QObject>
#include <QtDBus/QtDBus>
+#include <QtBluetooth/QBluetoothUuid>
#include <QtBluetooth/QBluetoothAddress>
#include <QtBluetooth/private/qtbluetoothglobal_p.h>
typedef QMap<QString, QVariantMap> InterfaceList;
typedef QMap<QDBusObjectPath, InterfaceList> ManagedObjectList;
typedef QMap<quint16, QDBusVariant> ManufacturerDataList;
+typedef QMap<QString, QDBusVariant> ServiceDataList;
Q_DECLARE_METATYPE(InterfaceList)
Q_DECLARE_METATYPE(ManufacturerDataList)
+Q_DECLARE_METATYPE(ServiceDataList)
Q_DECLARE_METATYPE(ManagedObjectList)
QT_BEGIN_NAMESPACE
diff --git a/src/bluetooth/bluez/device1_bluez5_p.h b/src/bluetooth/bluez/device1_bluez5_p.h
index b9523a56..c03a1bd8 100644
--- a/src/bluetooth/bluez/device1_bluez5_p.h
+++ b/src/bluetooth/bluez/device1_bluez5_p.h
@@ -96,9 +96,9 @@ public:
inline short rSSI() const
{ return qvariant_cast< short >(property("RSSI")); }
- Q_PROPERTY(QVariantMap ServiceData READ serviceData)
- inline QVariantMap serviceData() const
- { return qvariant_cast< QVariantMap >(property("ServiceData")); }
+ Q_PROPERTY(ServiceDataList ServiceData READ serviceData)
+ inline ServiceDataList serviceData() const
+ { return qvariant_cast< ServiceDataList >(property("ServiceData")); }
Q_PROPERTY(bool ServicesResolved READ servicesResolved)
inline bool servicesResolved() const
diff --git a/src/bluetooth/bluez/org.bluez.Device1.xml b/src/bluetooth/bluez/org.bluez.Device1.xml
index 554d0b53..cd4cba77 100644
--- a/src/bluetooth/bluez/org.bluez.Device1.xml
+++ b/src/bluetooth/bluez/org.bluez.Device1.xml
@@ -29,10 +29,10 @@
<property name="Adapter" type="o" access="read"></property>
<!-- ManufacturerData & ServiceData introduced by Bluez 5.31 -->
<property name="ManufacturerData" type="a{qv}" access="read">
- <annotation name="org.qtproject.QtDBus.QtTypeName" value="ManufacturerDataList"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName" value="ManufacturerDataList"/>
</property>
<property name="ServiceData" type="a{sv}" access="read">
- <annotation name="org.qtproject.QtDBus.QtTypeName" value="QVariantMap"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName" value="ServiceDataList"/>
</property>
<!-- TxPower and ServicesResolved introduced by Bluez 5.42 -->
<property name="TxPower" type="n" access="read"></property>
diff --git a/src/bluetooth/darwin/btledeviceinquiry.mm b/src/bluetooth/darwin/btledeviceinquiry.mm
index 38ed5f45..6cc61955 100644
--- a/src/bluetooth/darwin/btledeviceinquiry.mm
+++ b/src/bluetooth/darwin/btledeviceinquiry.mm
@@ -83,6 +83,7 @@ struct AdvertisementData {
QString localName;
QList<QBluetoothUuid> serviceUuids;
QHash<quint16, QByteArray> manufacturerData;
+ QHash<QBluetoothUuid, QByteArray> serviceData;
// TODO: other keys probably?
AdvertisementData(NSDictionary *AdvertisementData);
};
@@ -108,6 +109,13 @@ AdvertisementData::AdvertisementData(NSDictionary *advertisementData)
serviceUuids << qt_uuid(cbUuid);
}
+ NSDictionary *advdict = [advertisementData objectForKey:CBAdvertisementDataServiceDataKey];
+ if (advdict) {
+ [advdict enumerateKeysAndObjectsUsingBlock:^(CBUUID *key, NSData *val, BOOL *) {
+ serviceData.insert(qt_uuid(key), QByteArray::fromNSData(static_cast<NSData *>(val)));
+ }];
+ }
+
value = [advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey];
if (value && [value isKindOfClass:[NSData class]]) {
QByteArray data = QByteArray::fromNSData(static_cast<NSData *>(value));
@@ -359,10 +367,14 @@ QT_USE_NAMESPACE
if (qtAdvData.serviceUuids.size())
newDeviceInfo.setServiceUuids(qtAdvData.serviceUuids);
- const QList<quint16> keys = qtAdvData.manufacturerData.keys();
- for (quint16 key : keys)
+ const QList<quint16> keysManufacturer = qtAdvData.manufacturerData.keys();
+ for (quint16 key : keysManufacturer)
newDeviceInfo.setManufacturerData(key, qtAdvData.manufacturerData.value(key));
+ const QList<QBluetoothUuid> keysService = qtAdvData.serviceData.keys();
+ for (QBluetoothUuid key : keysService)
+ newDeviceInfo.setServiceData(key, qtAdvData.serviceData.value(key));
+
// CoreBluetooth scans only for LE devices.
newDeviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration);
emit notifier->deviceDiscovered(newDeviceInfo);
diff --git a/src/bluetooth/darwin/btutility.mm b/src/bluetooth/darwin/btutility.mm
index 859624d4..2faa8911 100644
--- a/src/bluetooth/darwin/btutility.mm
+++ b/src/bluetooth/darwin/btutility.mm
@@ -182,8 +182,7 @@ QBluetoothUuid qt_uuid(CBUUID *uuid)
{
// Apples' docs say "128 bit" and "16-bit UUIDs are implicitly
// pre-filled with the Bluetooth Base UUID."
- // But Core Bluetooth can return CBUUID objects of length 2
- // (16-bit, so they are not pre-filled?).
+ // But Core Bluetooth can return CBUUID objects of length 2, 4, and 16.
if (!uuid)
return QBluetoothUuid();
@@ -195,6 +194,9 @@ QBluetoothUuid qt_uuid(CBUUID *uuid)
// Seems to be in big-endian.
const uchar *const src = static_cast<const uchar *>(uuid.data.bytes);
return QBluetoothUuid(qFromBigEndian<quint16>(src));
+ } else if (uuid.data.length == 4) {
+ const uchar *const src = static_cast<const uchar *>(uuid.data.bytes);
+ return QBluetoothUuid(qFromBigEndian<quint32>(src));
} else if (uuid.data.length == 16) {
quint128 qtUuidData = {};
const quint8 *const source = static_cast<const quint8 *>(uuid.data.bytes);
@@ -203,7 +205,7 @@ QBluetoothUuid qt_uuid(CBUUID *uuid)
return QBluetoothUuid(qtUuidData);
}
- qCDebug(QT_BT_DARWIN) << "qt_uuid, invalid CBUUID, 2 or 16 bytes expected, but got "
+ qCDebug(QT_BT_DARWIN) << "qt_uuid, invalid CBUUID, 2, 4, or 16 bytes expected, but got "
<< uuid.data.length << " bytes length";
return QBluetoothUuid();
}
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
index b2744164..d5ac2bc3 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
@@ -345,6 +345,13 @@ void QBluetoothDeviceDiscoveryAgentPrivate::processDiscoveredDevices(
discoveredDevices[i].setManufacturerData(key, info.manufacturerData(key));
updatedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData);
}
+ if (discoveredDevices[i].serviceData() != info.serviceData()) {
+ qCDebug(QT_BT_ANDROID) << "Updating service data for" << info.address();
+ const QList<QBluetoothUuid> keys = info.serviceIds();
+ for (auto key : keys)
+ discoveredDevices[i].setServiceData(key, info.serviceData(key));
+ updatedFields.setFlag(QBluetoothDeviceInfo::Field::ServiceData);
+ }
if (lowEnergySearchTimeout > 0) {
if (discoveredDevices[i] != info) {
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp
index 471f6a62..f509f649 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_bluez.cpp
@@ -276,11 +276,18 @@ static QBluetoothDeviceInfo createDeviceInfoFromBluez5Device(const QVariantMap&
}
const ManufacturerDataList deviceManufacturerData = qdbus_cast<ManufacturerDataList>(properties[QStringLiteral("ManufacturerData")]);
- const QList<quint16> keys = deviceManufacturerData.keys();
- for (quint16 key : keys)
+ const QList<quint16> keysManufacturer = deviceManufacturerData.keys();
+ for (quint16 key : keysManufacturer)
deviceInfo.setManufacturerData(
key, deviceManufacturerData.value(key).variant().toByteArray());
+ const ServiceDataList deviceServiceData =
+ qdbus_cast<ServiceDataList>(properties[QStringLiteral("ServiceData")]);
+ const QList<QString> keysService = deviceServiceData.keys();
+ for (QString key : keysService)
+ deviceInfo.setServiceData(QBluetoothUuid(key),
+ deviceServiceData.value(key).variant().toByteArray());
+
return deviceInfo;
}
@@ -305,7 +312,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QString &devicePat
<< "Num UUIDs" << deviceInfo.serviceUuids().count()
<< "total device" << discoveredDevices.count() << "cached"
<< "RSSI" << deviceInfo.rssi()
- << "Num ManufacturerData" << deviceInfo.manufacturerData().size();
+ << "Num ManufacturerData" << deviceInfo.manufacturerData().size()
+ << "Num ServiceData" << deviceInfo.serviceData().size();
// Cache the properties so we do not have to access dbus every time to get a value
devicesProperties[devicePath] = properties;
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm
index 01a71db8..635e91eb 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm
@@ -522,6 +522,14 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QBluetoothDeviceIn
updatedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData);
}
+ if (discoveredDevices[i].serviceData() != newDeviceInfo.serviceData()) {
+ qCDebug(QT_BT_DARWIN) << "Updating service data for" << newDeviceInfo.address();
+ const QList<QBluetoothUuid> keys = newDeviceInfo.serviceIds();
+ for (auto key : keys)
+ discoveredDevices[i].setServiceData(key, newDeviceInfo.serviceData(key));
+ updatedFields.setFlag(QBluetoothDeviceInfo::Field::ServiceData);
+ }
+
if (lowEnergySearchTimeout > 0) {
if (discoveredDevices[i] != newDeviceInfo) {
discoveredDevices.replace(i, newDeviceInfo);
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
index a1abf75a..c1260305 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
@@ -89,7 +89,9 @@ QT_END_NAMESPACE
#include <QtCore/QTimer>
using ManufacturerData = QHash<quint16, QByteArray>;
+using ServiceData = QHash<QBluetoothUuid, QByteArray>;
Q_DECLARE_METATYPE(ManufacturerData)
+Q_DECLARE_METATYPE(ServiceData)
#endif
QT_BEGIN_NAMESPACE
@@ -175,7 +177,7 @@ private:
private slots:
void registerDevice(const QBluetoothDeviceInfo &info);
void updateDeviceData(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields fields,
- qint16 rssi, ManufacturerData manufacturerData);
+ qint16 rssi, ManufacturerData manufacturerData, ServiceData serviceData);
void onErrorOccured(QBluetoothDeviceDiscoveryAgent::Error e);
void onScanFinished();
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
index 1aa0c6c9..bc047644 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
@@ -47,6 +47,7 @@
#include <QtCore/QLoggingCategory>
#include <QtCore/qmutex.h>
#include <QtCore/private/qfunctions_winrt_p.h>
+#include <QtCore/qendian.h>
#include <robuffer.h>
#include <wrl.h>
@@ -90,6 +91,15 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINDOWS)
continue; \
}
+// Endianness conversion for quint128 doesn't exist in qtendian.h
+inline quint128 qbswap(const quint128 src)
+{
+ quint128 dst;
+ for (int i = 0; i < 16; i++)
+ dst.data[i] = src.data[15 - i];
+ return dst;
+}
+
static ManufacturerData extractManufacturerData(ComPtr<IBluetoothLEAdvertisement> ad)
{
ManufacturerData ret;
@@ -117,6 +127,54 @@ static ManufacturerData extractManufacturerData(ComPtr<IBluetoothLEAdvertisement
return ret;
}
+static ServiceData extractServiceData(ComPtr<IBluetoothLEAdvertisement> ad)
+{
+ ServiceData ret;
+
+ int serviceDataTypes[3] = { 0x16, 0x20, 0x21 };
+
+ for (const auto &serviceDataType : serviceDataTypes) {
+ ComPtr<IVectorView<BluetoothLEAdvertisementDataSection *>> data_sections;
+ HRESULT hr = ad->GetSectionsByType(serviceDataType, &data_sections);
+ WARN_AND_RETURN_IF_FAILED("Could not obtain list of advertisement data sections.",
+ return ret);
+
+ quint32 size;
+ hr = data_sections->get_Size(&size);
+ WARN_AND_RETURN_IF_FAILED("Could not obtain advertisement data sections list size.",
+ return ret);
+
+ for (quint32 i = 0; i < size; ++i) {
+ ComPtr<IBluetoothLEAdvertisementDataSection> d;
+ hr = data_sections->GetAt(i, &d);
+ WARN_AND_CONTINUE_IF_FAILED("Could not obtain service data.");
+
+ BYTE datatype;
+ hr = d->get_DataType(&datatype);
+ WARN_AND_CONTINUE_IF_FAILED("Could not obtain service data type.");
+
+ ComPtr<IBuffer> buffer;
+ hr = d->get_Data(&buffer);
+ WARN_AND_CONTINUE_IF_FAILED("Could not obtain service data buffer.");
+ const QByteArray bufferData = byteArrayFromBuffer(buffer);
+
+ if (datatype == 0x16) {
+ ret.insert(QBluetoothUuid(qFromLittleEndian<quint16>(bufferData.constData())),
+ bufferData + 2);
+ } else if (datatype == 0x20) {
+ ret.insert(QBluetoothUuid(qFromLittleEndian<quint32>(bufferData.constData())),
+ bufferData + 4);
+ } else if (datatype == 0x21) {
+ ret.insert(QBluetoothUuid(qToBigEndian<quint128>(
+ qFromLittleEndian<quint128>(bufferData.constData()))),
+ bufferData + 16);
+ }
+ }
+ }
+
+ return ret;
+}
+
class QWinRTBluetoothDeviceDiscoveryWorker : public QObject
{
Q_OBJECT
@@ -155,7 +213,7 @@ public slots:
Q_SIGNALS:
void deviceFound(const QBluetoothDeviceInfo &info);
void deviceDataChanged(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields,
- qint16 rssi, ManufacturerData manufacturerData);
+ qint16 rssi, ManufacturerData manufacturerData, ServiceData serviceData);
void errorOccured(QBluetoothDeviceDiscoveryAgent::Error error);
void scanFinished();
@@ -169,6 +227,7 @@ private:
struct LEAdvertisingInfo {
QList<QBluetoothUuid> services;
ManufacturerData manufacturerData;
+ ServiceData serviceData;
qint16 rssi = 0;
};
@@ -336,6 +395,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEAdvertisementReceived
QBluetoothDeviceDiscoveryAgent::Error::UnknownError,
return S_OK);
const ManufacturerData manufacturerData = extractManufacturerData(ad);
+ const ServiceData serviceData = extractServiceData(ad);
QBluetoothDeviceInfo::Fields changedFields = QBluetoothDeviceInfo::Field::None;
ComPtr<IVector<GUID>> guids;
hr = ad->get_ServiceUuids(&guids);
@@ -373,6 +433,11 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEAdvertisementReceived
if (adInfo.manufacturerData != m_foundLEDevicesMap[address].manufacturerData)
changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData);
}
+ if (adInfo.serviceData != serviceData) {
+ m_foundLEDevicesMap[address].serviceData.insert(serviceData);
+ if (adInfo.serviceData != m_foundLEDevicesMap[address].serviceData)
+ changedFields.setFlag((QBluetoothDeviceInfo::Field::ServiceData));
+ }
bool newServiceAdded = false;
for (const QBluetoothUuid &uuid : qAsConst(serviceUuids)) {
if (!foundServices.contains(uuid)) {
@@ -386,7 +451,8 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEAdvertisementReceived
Q_ARG(QBluetoothAddress, QBluetoothAddress(address)),
Q_ARG(QBluetoothDeviceInfo::Fields, changedFields),
Q_ARG(qint16, rssi),
- Q_ARG(ManufacturerData, manufacturerData));
+ Q_ARG(ManufacturerData, manufacturerData),
+ Q_ARG(ServiceData, serviceData));
}
return S_OK;
}
@@ -395,6 +461,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEAdvertisementReceived
LEAdvertisingInfo info;
info.services = std::move(serviceUuids);
info.manufacturerData = std::move(manufacturerData);
+ info.serviceData = std::move(serviceData);
info.rssi = rssi;
m_foundLEDevicesMap.insert(address, info);
}
@@ -700,6 +767,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address);
const ManufacturerData manufacturerData = adInfo.manufacturerData;
+ const ServiceData serviceData = adInfo.serviceData;
const qint16 rssi = adInfo.rssi;
// Use the services obtained from the advertisement data if the device is not paired
if (!isPaired) {
@@ -732,7 +800,8 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
qCDebug(QT_BT_WINDOWS) << "Discovered BTLE device: " << QString::number(address) << btName
<< "Num UUIDs" << uuids.count() << "RSSI:" << rssi
- << "Num manufacturer data" << manufacturerData.count();
+ << "Num manufacturer data" << manufacturerData.count()
+ << "Num service data" << serviceData.count();
QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0);
info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration);
@@ -740,6 +809,8 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
info.setRssi(rssi);
for (quint16 key : manufacturerData.keys())
info.setManufacturerData(key, manufacturerData.value(key));
+ for (QBluetoothUuid key : serviceData.keys())
+ info.setServiceData(key, serviceData.value(key));
info.setCached(true);
QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection,
@@ -838,7 +909,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::registerDevice(const QBluetoothDevic
void QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData(const QBluetoothAddress &address,
QBluetoothDeviceInfo::Fields fields,
qint16 rssi,
- ManufacturerData manufacturerData)
+ ManufacturerData manufacturerData,
+ ServiceData serviceData)
{
if (fields.testFlag(QBluetoothDeviceInfo::Field::None))
return;
@@ -853,6 +925,9 @@ void QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData(const QBluetoothAdd
if (fields.testFlag(QBluetoothDeviceInfo::Field::ManufacturerData))
for (quint16 key : manufacturerData.keys())
iter->setManufacturerData(key, manufacturerData.value(key));
+ if (fields.testFlag(QBluetoothDeviceInfo::Field::ServiceData))
+ for (QBluetoothUuid key : serviceData.keys())
+ iter->setServiceData(key, serviceData.value(key));
emit q->deviceUpdated(*iter, fields);
return;
}
diff --git a/src/bluetooth/qbluetoothdeviceinfo.cpp b/src/bluetooth/qbluetoothdeviceinfo.cpp
index 36d24b91..41d1f4af 100644
--- a/src/bluetooth/qbluetoothdeviceinfo.cpp
+++ b/src/bluetooth/qbluetoothdeviceinfo.cpp
@@ -80,6 +80,7 @@ QT_BEGIN_NAMESPACE
\value None None of the values changed.
\value RSSI The \l rssi() value of the device changed.
\value ManufacturerData The \l manufacturerData() field changed
+ \value ServiceData The \l serviceData() field changed
\value All Matches every possible field.
\since 5.12
@@ -396,6 +397,7 @@ QBluetoothDeviceInfo &QBluetoothDeviceInfo::operator=(const QBluetoothDeviceInfo
d->cached = other.d_func()->cached;
d->serviceUuids = other.d_func()->serviceUuids;
d->manufacturerData = other.d_func()->manufacturerData;
+ d->serviceData = other.d_func()->serviceData;
d->rssi = other.d_func()->rssi;
d->deviceCoreConfiguration = other.d_func()->deviceCoreConfiguration;
d->deviceUuid = other.d_func()->deviceUuid;
@@ -441,6 +443,8 @@ bool QBluetoothDeviceInfo::equals(const QBluetoothDeviceInfo &a, const QBluetoot
return false;
if (a.d_func()->manufacturerData != b.d_func()->manufacturerData)
return false;
+ if (a.d_func()->serviceData != b.d_func()->serviceData)
+ return false;
if (a.d_func()->deviceCoreConfiguration != b.d_func()->deviceCoreConfiguration)
return false;
if (a.d_func()->deviceUuid != b.d_func()->deviceUuid)
@@ -533,9 +537,9 @@ void QBluetoothDeviceInfo::setServiceUuids(const QList<QBluetoothUuid> &uuids)
}
/*!
- Returns the list of service UUIDS supported by the device. Most commonly this
- list of uuids represents custom uuids or a uuid value specified by
- \l QBluetoothUuid::ServiceClassUuid.
+ Returns the list of service UUIDs supported by the device. Most commonly this
+ list of UUIDs represents custom service UUIDs or a service UUID value specified
+ by \l QBluetoothUuid::ServiceClassUuid.
\sa serviceUuids()
\since 6.0
@@ -547,7 +551,7 @@ QList<QBluetoothUuid> QBluetoothDeviceInfo::serviceUuids() const
}
/*!
- Returns all manufacturer ids attached to this device information.
+ Returns all manufacturer IDs from advertisement packets attached to this device information.
\sa manufacturerData(), setManufacturerData()
@@ -556,7 +560,7 @@ QList<QBluetoothUuid> QBluetoothDeviceInfo::serviceUuids() const
QList<quint16> QBluetoothDeviceInfo::manufacturerIds() const
{
Q_D(const QBluetoothDeviceInfo);
- return d->manufacturerData.keys().toVector();
+ return d->manufacturerData.keys().toList();
}
/*!
@@ -613,7 +617,7 @@ bool QBluetoothDeviceInfo::setManufacturerData(quint16 manufacturerId, const QBy
}
/*!
- Returns the complete set of all manufacturer data.
+ Returns the complete set of all manufacturer data from advertisement packets.
Some devices may provide multiple manufacturer data entries per manufacturer ID.
An example might be a Bluetooth Low Energy device that sends a different manufacturer data via
@@ -630,6 +634,80 @@ QMultiHash<quint16, QByteArray> QBluetoothDeviceInfo::manufacturerData() const
}
/*!
+ Returns all service data IDs from advertisement packets attached to this device information.
+
+ \sa serviceData(), setServiceData()
+ \since 6.3
+ */
+QList<QBluetoothUuid> QBluetoothDeviceInfo::serviceIds() const
+{
+ Q_D(const QBluetoothDeviceInfo);
+ return d->serviceData.keys().toList();
+}
+
+/*!
+ Returns the data associated with the given \a serviceId.
+
+ Service data is defined by
+ the Supplement to the Bluetooth Core Specification and consists of two segments:
+
+ \list
+ \li Service UUID
+ \li Sequence of arbitrary data octets
+ \endlist
+
+ \note The remote device may provide multiple data entries per \a serviceId.
+ This function only returns the first entry. If all entries are needed use
+ \l serviceData() which returns a multi hash.
+
+ \sa serviceIds(), setServiceData()
+ \since 6.3
+ */
+QByteArray QBluetoothDeviceInfo::serviceData(const QBluetoothUuid &serviceId) const
+{
+ Q_D(const QBluetoothDeviceInfo);
+ return d->serviceData.value(serviceId);
+}
+
+/*!
+ Sets the advertised service \a data for the given \a serviceId.
+ Returns \c true if it was inserted, \c false if it was already known.
+
+ \sa serviceData
+ \since 6.3
+*/
+bool QBluetoothDeviceInfo::setServiceData(const QBluetoothUuid &serviceId, const QByteArray &data)
+{
+ Q_D(QBluetoothDeviceInfo);
+ auto it = d->serviceData.constFind(serviceId);
+ while (it != d->serviceData.cend() && it.key() == serviceId) {
+ if (*it == data)
+ return false;
+ it++;
+ }
+
+ d->serviceData.insert(serviceId, data);
+ return true;
+}
+
+/*!
+ Returns the complete set of all service data from advertisement packets.
+
+ Some devices may provide multiple service data entries per service data ID.
+ An example might be a Bluetooth Low Energy device that sends a different service data via
+ advertisement packets and scan response packets respectively. Therefore the returned hash table
+ may have multiple entries per service data ID or hash key.
+
+ \sa setServiceData
+ \since 6.3
+*/
+QMultiHash<QBluetoothUuid, QByteArray> QBluetoothDeviceInfo::serviceData() const
+{
+ Q_D(const QBluetoothDeviceInfo);
+ return d->serviceData;
+}
+
+/*!
Sets the CoreConfigurations of the device to \a coreConfigs. This will help to make a difference
between regular and Low Energy devices.
diff --git a/src/bluetooth/qbluetoothdeviceinfo.h b/src/bluetooth/qbluetoothdeviceinfo.h
index 3219e629..6fd250ec 100644
--- a/src/bluetooth/qbluetoothdeviceinfo.h
+++ b/src/bluetooth/qbluetoothdeviceinfo.h
@@ -41,6 +41,7 @@
#define QBLUETOOTHDEVICEINFO_H
#include <QtBluetooth/qtbluetoothglobal.h>
+#include <QtBluetooth/QBluetoothUuid>
#include <QtCore/qbytearray.h>
#include <QtCore/qlist.h>
@@ -195,6 +196,7 @@ public:
None = 0x0000,
RSSI = 0x0001,
ManufacturerData = 0x0002,
+ ServiceData = 0x0004,
All = 0x7fff
};
Q_DECLARE_FLAGS(Fields, Field)
@@ -249,6 +251,11 @@ public:
bool setManufacturerData(quint16 manufacturerId, const QByteArray &data);
QMultiHash<quint16, QByteArray> manufacturerData() const;
+ QList<QBluetoothUuid> serviceIds() const;
+ QByteArray serviceData(const QBluetoothUuid &serviceId) const;
+ bool setServiceData(const QBluetoothUuid &serviceId, const QByteArray &data);
+ QMultiHash<QBluetoothUuid, QByteArray> serviceData() const;
+
void setCoreConfigurations(QBluetoothDeviceInfo::CoreConfigurations coreConfigs);
QBluetoothDeviceInfo::CoreConfigurations coreConfigurations() const;
diff --git a/src/bluetooth/qbluetoothdeviceinfo_p.h b/src/bluetooth/qbluetoothdeviceinfo_p.h
index 25c70960..854ab00f 100644
--- a/src/bluetooth/qbluetoothdeviceinfo_p.h
+++ b/src/bluetooth/qbluetoothdeviceinfo_p.h
@@ -78,6 +78,7 @@ public:
QList<QBluetoothUuid> serviceUuids;
QMultiHash<quint16, QByteArray> manufacturerData;
+ QMultiHash<QBluetoothUuid, QByteArray> serviceData;
QBluetoothDeviceInfo::CoreConfigurations deviceCoreConfiguration = QBluetoothDeviceInfo::UnknownCoreConfiguration;
QBluetoothUuid deviceUuid;