diff options
author | Oliver Wolff <oliver.wolff@qt.io> | 2019-03-12 12:05:30 +0100 |
---|---|---|
committer | Oliver Wolff <oliver.wolff@qt.io> | 2019-03-19 09:50:38 +0000 |
commit | 2fd1ed79a65f2c9d1469795683f36e40c3bfa897 (patch) | |
tree | 216e7fd1092a1acabc6f840604df037d9373d5e5 /src | |
parent | ecc177dba5833ebf259d8af7af00a5e86f451fdc (diff) |
winrt: Implement manufacturer data
Fixes: QTBUG-71943
Change-Id: Idb0524dde871d4aa153f0170f926ae76679f14cb
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/bluetooth/qbluetoothdevicediscoveryagent_p.h | 6 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp | 132 | ||||
-rw-r--r-- | src/bluetooth/qbluetoothdeviceinfo.h | 3 |
3 files changed, 117 insertions, 24 deletions
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h index e4370180..3e76c13d 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h @@ -81,6 +81,9 @@ QT_END_NAMESPACE #ifdef QT_WINRT_BLUETOOTH #include <QtCore/QPointer> #include <QtCore/QTimer> + +using ManufacturerData = QHash<quint16, QByteArray>; +Q_DECLARE_METATYPE(ManufacturerData) #endif QT_BEGIN_NAMESPACE @@ -167,7 +170,8 @@ private: #ifdef QT_WINRT_BLUETOOTH private slots: void registerDevice(const QBluetoothDeviceInfo &info); - void updateDeviceRssi(const QBluetoothAddress &address, qint16 rssi); + void updateDeviceData(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields fields, + qint16 rssi, ManufacturerData manufacturerData); void onScanFinished(); private: diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp index 61f167de..1f96740c 100644 --- a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp +++ b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp @@ -52,6 +52,7 @@ #include <QtCore/QLoggingCategory> #include <QtCore/private/qeventdispatcher_winrt_p.h> +#include <robuffer.h> #include <wrl.h> #include <windows.devices.enumeration.h> #include <windows.devices.bluetooth.h> @@ -68,6 +69,7 @@ using namespace ABI::Windows::Devices; using namespace ABI::Windows::Devices::Bluetooth; using namespace ABI::Windows::Devices::Bluetooth::Advertisement; using namespace ABI::Windows::Devices::Enumeration; +using namespace ABI::Windows::Storage::Streams; QT_BEGIN_NAMESPACE @@ -79,6 +81,54 @@ Q_DECLARE_LOGGING_CATEGORY(QT_BT_WINRT) ret; \ } +#define WARN_AND_CONTINUE_IF_FAILED(msg) \ + if (FAILED(hr)) { \ + qCWarning(QT_BT_WINRT) << msg; \ + continue; \ + } + +static QByteArray byteArrayFromBuffer(const ComPtr<IBuffer> &buffer) +{ + ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteAccess; + HRESULT hr = buffer.As(&byteAccess); + Q_ASSERT_SUCCEEDED(hr); + char *data; + hr = byteAccess->Buffer(reinterpret_cast<byte **>(&data)); + Q_ASSERT_SUCCEEDED(hr); + UINT32 size; + hr = buffer->get_Length(&size); + Q_ASSERT_SUCCEEDED(hr); + return QByteArray(data, int(size)); +} + + +static ManufacturerData extractManufacturerData(ComPtr<IBluetoothLEAdvertisement> ad) +{ + ManufacturerData ret; + ComPtr<IVector<BluetoothLEManufacturerData*>> data; + HRESULT hr = ad->get_ManufacturerData(&data); + WARN_AND_RETURN_IF_FAILED("Could not obtain list of manufacturer data.", return ret); + quint32 size; + hr = data->get_Size(&size); + WARN_AND_RETURN_IF_FAILED("Could not obtain manufacturer data's list size.", return ret); + for (quint32 i = 0; i < size; ++i) { + ComPtr<IBluetoothLEManufacturerData> d; + hr = data->GetAt(i, &d); + WARN_AND_CONTINUE_IF_FAILED("Could not obtain manufacturer data."); + quint16 id; + hr = d->get_CompanyId(&id); + WARN_AND_CONTINUE_IF_FAILED("Could not obtain manufacturer data company id."); + ComPtr<IBuffer> buffer; + hr = d->get_Data(&buffer); + WARN_AND_CONTINUE_IF_FAILED("Could not obtain manufacturer data set."); + const QByteArray bufferData = byteArrayFromBuffer(buffer); + if (ret.contains(id)) + qCWarning(QT_BT_WINRT) << "Company ID already present in manufacturer data."; + ret.insert(id, bufferData); + } + return ret; +} + class QWinRTBluetoothDeviceDiscoveryWorker : public QObject { Q_OBJECT @@ -117,7 +167,8 @@ public slots: Q_SIGNALS: void deviceFound(const QBluetoothDeviceInfo &info); - void deviceRssiChanged(const QBluetoothAddress &address, qint16 rssi); + void deviceDataChanged(const QBluetoothAddress &address, QBluetoothDeviceInfo::Fields, + qint16 rssi, ManufacturerData manufacturerData); void scanFinished(); public: @@ -136,6 +187,7 @@ private: QMap<quint64, LEAdvertisingInfo> m_foundLEDevicesMap; #endif QMap<quint64, qint16> m_foundLEDevices; + QMap<quint64, ManufacturerData> m_foundLEManufacturerData; int m_pendingPairedDevices; ComPtr<IBluetoothDeviceStatics> m_deviceStatics; @@ -147,6 +199,8 @@ QWinRTBluetoothDeviceDiscoveryWorker::QWinRTBluetoothDeviceDiscoveryWorker(QBlue , m_pendingPairedDevices(0) { qRegisterMetaType<QBluetoothDeviceInfo>(); + qRegisterMetaType<QBluetoothDeviceInfo::Fields>(); + qRegisterMetaType<ManufacturerData>(); #ifdef CLASSIC_APP_BUILD CoInitialize(NULL); @@ -281,11 +335,20 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher() qint16 rssi; hr = args->get_RawSignalStrengthInDBm(&rssi); Q_ASSERT_SUCCEEDED(hr); + ComPtr<IBluetoothLEAdvertisement> ad; + hr = args->get_Advertisement(&ad); + Q_ASSERT_SUCCEEDED(hr); + const ManufacturerData manufacturerData = extractManufacturerData(ad); + QBluetoothDeviceInfo::Fields changedFields = QBluetoothDeviceInfo::Field::None; + if (!m_foundLEManufacturerData.contains(address)) { + m_foundLEManufacturerData.insert(address, manufacturerData); + changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData); + } else if (m_foundLEManufacturerData.value(address) != manufacturerData) { + m_foundLEManufacturerData[address] = manufacturerData; + changedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData); + } #if QT_CONFIG(winrt_btle_no_pairing) if (supportsNewLEApi()) { - ComPtr<IBluetoothLEAdvertisement> ad; - hr = args->get_Advertisement(&ad); - Q_ASSERT_SUCCEEDED(hr); ComPtr<IVector<GUID>> guids; hr = ad->get_ServiceUuids(&guids); Q_ASSERT_SUCCEEDED(hr); @@ -307,10 +370,9 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher() return S_OK; const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address); QVector<QBluetoothUuid> foundServices = adInfo.services; - bool rssiChanged = false; if (adInfo.rssi != rssi) { m_foundLEDevicesMap[address].rssi = rssi; - rssiChanged = true; + changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI); } bool newServiceAdded = false; for (const QBluetoothUuid &uuid : qAsConst(serviceUuids)) { @@ -320,10 +382,12 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher() } } if (!newServiceAdded) { - if (rssiChanged) { - QMetaObject::invokeMethod(this, "deviceRssiChanged", Qt::AutoConnection, + if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) { + QMetaObject::invokeMethod(this, "deviceDataChanged", Qt::AutoConnection, Q_ARG(QBluetoothAddress, QBluetoothAddress(address)), - Q_ARG(qint16, rssi)); + Q_ARG(QBluetoothDeviceInfo::Fields, changedFields), + Q_ARG(qint16, rssi), + Q_ARG(ManufacturerData, manufacturerData)); } return S_OK; } @@ -342,9 +406,14 @@ void QWinRTBluetoothDeviceDiscoveryWorker::setupLEDeviceWatcher() if (m_foundLEDevices.contains(address)) { if (m_foundLEDevices.value(address) != rssi) { m_foundLEDevices[address] = rssi; - QMetaObject::invokeMethod(this, "deviceRssiChanged", Qt::AutoConnection, + changedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI); + } + if (!changedFields.testFlag(QBluetoothDeviceInfo::Field::None)) { + QMetaObject::invokeMethod(this, "deviceDataChanged", Qt::AutoConnection, Q_ARG(QBluetoothAddress, QBluetoothAddress(address)), - Q_ARG(qint16, rssi)); + Q_ARG(QBluetoothDeviceInfo::Fields, changedFields), + Q_ARG(qint16, rssi), + Q_ARG(ManufacturerData, manufacturerData)); } return S_OK; } @@ -649,14 +718,18 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB uuids.append(QBluetoothUuid(uuid)); } const qint16 rssi = m_foundLEDevices.value(address); + const ManufacturerData manufacturerData = m_foundLEManufacturerData.value(address); qCDebug(QT_BT_WINRT) << "Discovered BTLE device: " << QString::number(address) << btName - << "Num UUIDs" << uuids.count() << "RSSI:" << rssi; + << "Num UUIDs" << uuids.count() << "RSSI:" << rssi + << "Num manufacturer data" << manufacturerData.count(); QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0); info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration); info.setServiceUuids(uuids); info.setRssi(rssi); + for (const quint16 key : manufacturerData.keys()) + info.setManufacturerData(key, manufacturerData.value(key)); info.setCached(true); QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection, @@ -723,14 +796,18 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB uuids.append(QBluetoothUuid(uuid)); } } + const ManufacturerData manufacturerData = m_foundLEManufacturerData.value(address); qCDebug(QT_BT_WINRT) << "Discovered BTLE device: " << QString::number(address) << btName - << "Num UUIDs" << uuids.count() << "RSSI:" << rssi; + << "Num UUIDs" << uuids.count() << "RSSI:" << rssi + << "Num manufacturer data" << manufacturerData.count(); QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0); info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration); info.setServiceUuids(uuids, QBluetoothDeviceInfo::DataIncomplete); info.setRssi(rssi); + for (quint16 key : manufacturerData.keys()) + info.setManufacturerData(key, manufacturerData.value(key)); info.setCached(true); QMetaObject::invokeMethod(this, "deviceFound", Qt::AutoConnection, @@ -776,8 +853,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent discoveredDevices.clear(); connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound, this, &QBluetoothDeviceDiscoveryAgentPrivate::registerDevice); - connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceRssiChanged, - this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceRssi); + connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceDataChanged, + this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData); connect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::scanFinished, this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished); worker->start(); @@ -832,16 +909,25 @@ void QBluetoothDeviceDiscoveryAgentPrivate::registerDevice(const QBluetoothDevic emit q->deviceDiscovered(info); } -void QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceRssi(const QBluetoothAddress &address, qint16 rssi) +void QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData(const QBluetoothAddress &address, + QBluetoothDeviceInfo::Fields fields, + qint16 rssi, + ManufacturerData manufacturerData) { + if (fields.testFlag(QBluetoothDeviceInfo::Field::None)) + return; + Q_Q(QBluetoothDeviceDiscoveryAgent); for (QList<QBluetoothDeviceInfo>::iterator iter = discoveredDevices.begin(); - iter != discoveredDevices.end(); ++iter) { + iter != discoveredDevices.end(); ++iter) { if (iter->address() == address) { - qCDebug(QT_BT_WINRT) << "Updating rssi for device" << iter->name() << iter->address() - << "from" << iter->rssi() << "to" << rssi; - iter->setRssi(rssi); - emit q->deviceUpdated(*iter, QBluetoothDeviceInfo::Field::RSSI); + qCDebug(QT_BT_WINRT) << "Updating data for device" << iter->name() << iter->address(); + if (fields.testFlag(QBluetoothDeviceInfo::Field::RSSI)) + iter->setRssi(rssi); + if (fields.testFlag(QBluetoothDeviceInfo::Field::ManufacturerData)) + for (quint16 key : manufacturerData.keys()) + iter->setManufacturerData(key, manufacturerData.value(key)); + emit q->deviceUpdated(*iter, fields); return; } } @@ -864,8 +950,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::disconnectAndClearWorker() this, &QBluetoothDeviceDiscoveryAgentPrivate::onScanFinished); disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceFound, q, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered); - disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceRssiChanged, - this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceRssi); + disconnect(worker, &QWinRTBluetoothDeviceDiscoveryWorker::deviceDataChanged, + this, &QBluetoothDeviceDiscoveryAgentPrivate::updateDeviceData); if (leScanTimer) { disconnect(leScanTimer, &QTimer::timeout, worker, &QWinRTBluetoothDeviceDiscoveryWorker::finishDiscovery); diff --git a/src/bluetooth/qbluetoothdeviceinfo.h b/src/bluetooth/qbluetoothdeviceinfo.h index db0de7cd..11cb2bea 100644 --- a/src/bluetooth/qbluetoothdeviceinfo.h +++ b/src/bluetooth/qbluetoothdeviceinfo.h @@ -284,5 +284,8 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QBluetoothDeviceInfo::ServiceClasses) QT_END_NAMESPACE Q_DECLARE_METATYPE(QBluetoothDeviceInfo) +#ifdef QT_WINRT_BLUETOOTH +Q_DECLARE_METATYPE(QBluetoothDeviceInfo::Fields) +#endif #endif |