summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf4
-rw-r--r--examples/bluetooth/btchat/main.cpp1
-rw-r--r--examples/bluetooth/btchat/remoteselector.cpp10
-rw-r--r--examples/bluetooth/btfiletransfer/main.cpp1
-rw-r--r--examples/bluetooth/btfiletransfer/pindisplay.h2
-rw-r--r--examples/bluetooth/btfiletransfer/progress.h6
-rw-r--r--examples/bluetooth/btfiletransfer/remoteselector.cpp25
-rw-r--r--examples/bluetooth/btfiletransfer/remoteselector.h4
-rw-r--r--examples/bluetooth/btscanner/device.h2
-rw-r--r--examples/bluetooth/btscanner/main.cpp1
-rw-r--r--examples/bluetooth/btscanner/service.h2
-rw-r--r--examples/bluetooth/chat/qmlchat.cpp1
-rw-r--r--examples/bluetooth/heartrate-game/main.cpp1
-rw-r--r--examples/bluetooth/lowenergyscanner/device.cpp12
-rw-r--r--examples/bluetooth/lowenergyscanner/main.cpp1
-rw-r--r--examples/bluetooth/picturetransfer/filetransfer.h2
-rw-r--r--examples/bluetooth/picturetransfer/main.cpp1
-rw-r--r--examples/bluetooth/pingpong/main.cpp1
-rw-r--r--examples/bluetooth/scanner/qmlscanner.cpp1
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java54
-rw-r--r--src/bluetooth/android/devicediscoverybroadcastreceiver.cpp4
-rw-r--r--src/bluetooth/bluetooth.pro25
-rw-r--r--src/bluetooth/osx/btdelegates.cpp76
-rw-r--r--src/bluetooth/osx/btdelegates_p.h149
-rw-r--r--src/bluetooth/osx/btraii.mm110
-rw-r--r--src/bluetooth/osx/btraii_p.h136
-rw-r--r--src/bluetooth/osx/osxbt.pri13
-rw-r--r--src/bluetooth/osx/osxbtdeviceinquiry.mm24
-rw-r--r--src/bluetooth/osx/osxbtdeviceinquiry_p.h24
-rw-r--r--src/bluetooth/osx/osxbtnotifier_p.h1
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp3
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm (renamed from src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm)327
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm458
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_p.h63
-rw-r--r--src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp6
-rw-r--r--src/bluetooth/qlowenergycharacteristic.h2
-rw-r--r--src/bluetooth/qlowenergycontroller.cpp38
-rw-r--r--src/bluetooth/qlowenergycontroller.h5
-rw-r--r--src/bluetooth/qlowenergycontroller_bluezdbus.cpp10
-rw-r--r--src/bluetooth/qlowenergycontroller_darwin.mm (renamed from src/bluetooth/qlowenergycontroller_osx.mm)1019
-rw-r--r--src/bluetooth/qlowenergycontroller_darwin_p.h (renamed from src/bluetooth/qlowenergycontroller_osx_p.h)111
-rw-r--r--src/bluetooth/qlowenergycontrollerbase.cpp2
-rw-r--r--src/bluetooth/qlowenergycontrollerbase_p.h22
-rw-r--r--src/bluetooth/qlowenergydescriptor.h2
-rw-r--r--src/bluetooth/qlowenergyservice.cpp19
-rw-r--r--src/bluetooth/qlowenergyservice.h1
-rw-r--r--src/bluetooth/qlowenergyservice_osx.mm277
-rw-r--r--src/nfc/qnearfieldtagtype2.cpp7
-rw-r--r--src/nfc/qnearfieldtarget.cpp13
-rw-r--r--src/nfc/qqmlndefrecord.cpp5
-rw-r--r--tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp10
-rw-r--r--tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp6
52 files changed, 1215 insertions, 1885 deletions
diff --git a/.qmake.conf b/.qmake.conf
index f8cda0e7..1581612e 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,3 +1,5 @@
load(qt_build_config)
-MODULE_VERSION = 5.13.0
+DEFINES += QT_NO_JAVA_STYLE_ITERATORS
+
+MODULE_VERSION = 5.14.0
diff --git a/examples/bluetooth/btchat/main.cpp b/examples/bluetooth/btchat/main.cpp
index 5c7bbf75..e728efd2 100644
--- a/examples/bluetooth/btchat/main.cpp
+++ b/examples/bluetooth/btchat/main.cpp
@@ -56,6 +56,7 @@
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
Chat d;
diff --git a/examples/bluetooth/btchat/remoteselector.cpp b/examples/bluetooth/btchat/remoteselector.cpp
index 2bd1efcc..ec5d207c 100644
--- a/examples/bluetooth/btchat/remoteselector.cpp
+++ b/examples/bluetooth/btchat/remoteselector.cpp
@@ -114,17 +114,15 @@ void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo)
<< serviceInfo.protocolServiceMultiplexer();
qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel();
#endif
- QMapIterator<QListWidgetItem *, QBluetoothServiceInfo> i(m_discoveredServices);
- while (i.hasNext()){
- i.next();
- if (serviceInfo.device().address() == i.value().device().address()){
+ const QBluetoothAddress address = serviceInfo.device().address();
+ for (const QBluetoothServiceInfo &info : qAsConst(m_discoveredServices)) {
+ if (info.device().address() == address)
return;
- }
}
QString remoteName;
if (serviceInfo.device().name().isEmpty())
- remoteName = serviceInfo.device().address().toString();
+ remoteName = address.toString();
else
remoteName = serviceInfo.device().name();
diff --git a/examples/bluetooth/btfiletransfer/main.cpp b/examples/bluetooth/btfiletransfer/main.cpp
index 2c2b6df5..1871e207 100644
--- a/examples/bluetooth/btfiletransfer/main.cpp
+++ b/examples/bluetooth/btfiletransfer/main.cpp
@@ -54,6 +54,7 @@
int main(int argc, char *argv[])
{
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
RemoteSelector d;
diff --git a/examples/bluetooth/btfiletransfer/pindisplay.h b/examples/bluetooth/btfiletransfer/pindisplay.h
index b7ad8866..7acc517e 100644
--- a/examples/bluetooth/btfiletransfer/pindisplay.h
+++ b/examples/bluetooth/btfiletransfer/pindisplay.h
@@ -64,7 +64,7 @@ class pinDisplay : public QDialog
Q_OBJECT
public:
- explicit pinDisplay(QString title, QString pin, QWidget *parent = 0);
+ explicit pinDisplay(QString title, QString pin, QWidget *parent = nullptr);
~pinDisplay();
void setOkCancel();
diff --git a/examples/bluetooth/btfiletransfer/progress.h b/examples/bluetooth/btfiletransfer/progress.h
index 64a19ca0..afd72153 100644
--- a/examples/bluetooth/btfiletransfer/progress.h
+++ b/examples/bluetooth/btfiletransfer/progress.h
@@ -52,7 +52,7 @@
#define PROGRESS_H
#include <QDialog>
-#include <QTime>
+#include <QElapsedTimer>
QT_FORWARD_DECLARE_CLASS(QBluetoothTransferReply)
@@ -69,7 +69,7 @@ class Progress : public QDialog
Q_OBJECT
public:
- explicit Progress(QWidget *parent = 0);
+ explicit Progress(QWidget *parent = nullptr);
~Progress();
void setStatus(QString title, QString filename);
@@ -81,7 +81,7 @@ public Q_SLOTS:
private:
Ui::Progress *ui;
- QTime start;
+ QElapsedTimer start;
};
#endif // PROGRESS_H
diff --git a/examples/bluetooth/btfiletransfer/remoteselector.cpp b/examples/bluetooth/btfiletransfer/remoteselector.cpp
index 766bd028..b3c60cb3 100644
--- a/examples/bluetooth/btfiletransfer/remoteselector.cpp
+++ b/examples/bluetooth/btfiletransfer/remoteselector.cpp
@@ -171,18 +171,17 @@ void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo)
// new QListWidgetItem(QString::fromLatin1("%1\t%2\t%3").arg(serviceInfo.device().address().toString(),
// serviceInfo.device().name(), serviceInfo.serviceName()));
- QMutableMapIterator<int, QBluetoothServiceInfo> i(m_discoveredServices);
- while (i.hasNext()){
- i.next();
- if (serviceInfo.device().address() == i.value().device().address()){
- i.setValue(serviceInfo);
+ const QBluetoothAddress address = serviceInfo.device().address();
+ for (QBluetoothServiceInfo &info : m_discoveredServices) {
+ if (info.device().address() == address){
+ info = serviceInfo;
return;
}
}
int row = ui->remoteDevices->rowCount();
ui->remoteDevices->insertRow(row);
- QTableWidgetItem *item = new QTableWidgetItem(serviceInfo.device().address().toString());
+ QTableWidgetItem *item = new QTableWidgetItem(address.toString());
ui->remoteDevices->setItem(row, 0, item);
item = new QTableWidgetItem(serviceInfo.device().name());
ui->remoteDevices->setItem(row, 1, item);
@@ -190,9 +189,7 @@ void RemoteSelector::serviceDiscovered(const QBluetoothServiceInfo &serviceInfo)
ui->remoteDevices->setItem(row, 2, item);
- QBluetoothLocalDevice::Pairing p;
-
- p = m_localDevice->pairingStatus(serviceInfo.device().address());
+ QBluetoothLocalDevice::Pairing p = m_localDevice->pairingStatus(address);
ui->remoteDevices->blockSignals(true);
@@ -275,13 +272,11 @@ void RemoteSelector::on_stopButton_clicked()
m_discoveryAgent->stop();
}
-QString RemoteSelector::addressToName(const QBluetoothAddress &address)
+QString RemoteSelector::addressToName(const QBluetoothAddress &address) const
{
- QMapIterator<int, QBluetoothServiceInfo> i(m_discoveredServices);
- while (i.hasNext()){
- i.next();
- if (i.value().device().address() == address)
- return i.value().device().name();
+ for (const QBluetoothServiceInfo &info : m_discoveredServices) {
+ if (info.device().address() == address)
+ return info.device().name();
}
return address.toString();
}
diff --git a/examples/bluetooth/btfiletransfer/remoteselector.h b/examples/bluetooth/btfiletransfer/remoteselector.h
index b0850c41..8266c8c4 100644
--- a/examples/bluetooth/btfiletransfer/remoteselector.h
+++ b/examples/bluetooth/btfiletransfer/remoteselector.h
@@ -78,7 +78,7 @@ class RemoteSelector : public QDialog
Q_OBJECT
public:
- explicit RemoteSelector(QWidget *parent = 0);
+ explicit RemoteSelector(QWidget *parent = nullptr);
~RemoteSelector();
void startDiscovery(const QBluetoothUuid &uuid);
@@ -95,7 +95,7 @@ private:
QPointer<pinDisplay> m_pindisplay;
bool m_pairingError;
- QString addressToName(const QBluetoothAddress &address);
+ QString addressToName(const QBluetoothAddress &address) const;
public Q_SLOTS:
void startDiscovery();
diff --git a/examples/bluetooth/btscanner/device.h b/examples/bluetooth/btscanner/device.h
index 7111e1ec..35dc7965 100644
--- a/examples/bluetooth/btscanner/device.h
+++ b/examples/bluetooth/btscanner/device.h
@@ -67,7 +67,7 @@ class DeviceDiscoveryDialog : public QDialog
Q_OBJECT
public:
- DeviceDiscoveryDialog(QWidget *parent = 0);
+ DeviceDiscoveryDialog(QWidget *parent = nullptr);
~DeviceDiscoveryDialog();
public slots:
diff --git a/examples/bluetooth/btscanner/main.cpp b/examples/bluetooth/btscanner/main.cpp
index ca762802..a84dcda9 100644
--- a/examples/bluetooth/btscanner/main.cpp
+++ b/examples/bluetooth/btscanner/main.cpp
@@ -54,6 +54,7 @@
int main(int argc, char *argv[])
{
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
DeviceDiscoveryDialog d;
diff --git a/examples/bluetooth/btscanner/service.h b/examples/bluetooth/btscanner/service.h
index 94748dad..93d1e12b 100644
--- a/examples/bluetooth/btscanner/service.h
+++ b/examples/bluetooth/btscanner/service.h
@@ -66,7 +66,7 @@ class ServiceDiscoveryDialog : public QDialog
Q_OBJECT
public:
- ServiceDiscoveryDialog(const QString &name, const QBluetoothAddress &address, QWidget *parent = 0);
+ ServiceDiscoveryDialog(const QString &name, const QBluetoothAddress &address, QWidget *parent = nullptr);
~ServiceDiscoveryDialog();
public slots:
diff --git a/examples/bluetooth/chat/qmlchat.cpp b/examples/bluetooth/chat/qmlchat.cpp
index e7ce3f3a..6c8d2fa7 100644
--- a/examples/bluetooth/chat/qmlchat.cpp
+++ b/examples/bluetooth/chat/qmlchat.cpp
@@ -62,6 +62,7 @@
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication application(argc, argv);
QList<QBluetoothHostInfo> infos = QBluetoothLocalDevice::allDevices();
diff --git a/examples/bluetooth/heartrate-game/main.cpp b/examples/bluetooth/heartrate-game/main.cpp
index 099f82a7..05557c05 100644
--- a/examples/bluetooth/heartrate-game/main.cpp
+++ b/examples/bluetooth/heartrate-game/main.cpp
@@ -60,6 +60,7 @@
int main(int argc, char *argv[])
{
QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
ConnectionHandler connectionHandler;
diff --git a/examples/bluetooth/lowenergyscanner/device.cpp b/examples/bluetooth/lowenergyscanner/device.cpp
index 82179db1..d860457e 100644
--- a/examples/bluetooth/lowenergyscanner/device.cpp
+++ b/examples/bluetooth/lowenergyscanner/device.cpp
@@ -152,12 +152,12 @@ void Device::scanServices(const QString &address)
// We need the current device for service discovery.
for (auto d: qAsConst(devices)) {
- auto device = qobject_cast<DeviceInfo *>(d);
- if (!device)
- continue;
-
- if (device->getAddress() == address )
- currentDevice.setDevice(device->getDevice());
+ if (auto device = qobject_cast<DeviceInfo *>(d)) {
+ if (device->getAddress() == address ) {
+ currentDevice.setDevice(device->getDevice());
+ break;
+ }
+ }
}
if (!currentDevice.getDevice().isValid()) {
diff --git a/examples/bluetooth/lowenergyscanner/main.cpp b/examples/bluetooth/lowenergyscanner/main.cpp
index 351ab13a..f223b028 100644
--- a/examples/bluetooth/lowenergyscanner/main.cpp
+++ b/examples/bluetooth/lowenergyscanner/main.cpp
@@ -59,6 +59,7 @@
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
Device d;
diff --git a/examples/bluetooth/picturetransfer/filetransfer.h b/examples/bluetooth/picturetransfer/filetransfer.h
index 5e2e08f9..4dee32fe 100644
--- a/examples/bluetooth/picturetransfer/filetransfer.h
+++ b/examples/bluetooth/picturetransfer/filetransfer.h
@@ -59,7 +59,7 @@ class FileTransfer : public QObject
Q_OBJECT
Q_PROPERTY(float progress READ getProgress NOTIFY progressChanged)
public:
- explicit FileTransfer(QObject *parent = 0);
+ explicit FileTransfer(QObject *parent = nullptr);
float getProgress() { return m_progress;}
signals:
diff --git a/examples/bluetooth/picturetransfer/main.cpp b/examples/bluetooth/picturetransfer/main.cpp
index b4a1e670..4622e87e 100644
--- a/examples/bluetooth/picturetransfer/main.cpp
+++ b/examples/bluetooth/picturetransfer/main.cpp
@@ -58,6 +58,7 @@
int main(int argc, char *argv[])
{
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication application(argc, argv);
//! [Transfer-2]
QQuickView view;
diff --git a/examples/bluetooth/pingpong/main.cpp b/examples/bluetooth/pingpong/main.cpp
index fc1029de..7c34b135 100644
--- a/examples/bluetooth/pingpong/main.cpp
+++ b/examples/bluetooth/pingpong/main.cpp
@@ -58,6 +58,7 @@
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
PingPong pingPong;
QQmlApplicationEngine engine;
diff --git a/examples/bluetooth/scanner/qmlscanner.cpp b/examples/bluetooth/scanner/qmlscanner.cpp
index 4ead2364..2dbc0c27 100644
--- a/examples/bluetooth/scanner/qmlscanner.cpp
+++ b/examples/bluetooth/scanner/qmlscanner.cpp
@@ -56,6 +56,7 @@
int main(int argc, char *argv[])
{
//QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication application(argc, argv);
const QString mainQmlApp(QStringLiteral("qrc:/scanner.qml"));
QQuickView view;
diff --git a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java
index 6c548f84..9f10c32a 100644
--- a/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java
+++ b/src/android/bluetooth/src/org/qtproject/qt5/android/bluetooth/QtBluetoothLE.java
@@ -1,6 +1,6 @@
/****************************************************************************
**
- ** Copyright (C) 2016 The Qt Company Ltd.
+ ** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtBluetooth module of the Qt Toolkit.
@@ -47,6 +47,11 @@ import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
+import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanResult;
+import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
@@ -90,6 +95,9 @@ public class QtBluetoothLE {
private final int RUNNABLE_TIMEOUT = 3000; // 3 seconds
private final Handler timeoutHandler = new Handler(Looper.getMainLooper());
+ /* New BTLE scanner setup since Android SDK v21 */
+ private BluetoothLeScanner mBluetoothLeScanner = null;
+
private class TimeoutRunnable implements Runnable {
public TimeoutRunnable(int handle) { pendingJobHandle = handle; }
@Override
@@ -123,6 +131,7 @@ public class QtBluetoothLE {
@SuppressWarnings("WeakerAccess")
public QtBluetoothLE() {
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
}
public QtBluetoothLE(final String remoteAddress, Context context) {
@@ -131,7 +140,6 @@ public class QtBluetoothLE {
mRemoteGattAddress = remoteAddress;
}
-
/*************************************************************/
/* Device scan */
/*************************************************************/
@@ -144,27 +152,45 @@ public class QtBluetoothLE {
return true;
if (isEnabled) {
- mLeScanRunning = mBluetoothAdapter.startLeScan(leScanCallback);
+ Log.d(TAG, "New BTLE scanning API");
+ ScanSettings.Builder settingsBuilder = new ScanSettings.Builder();
+ settingsBuilder = settingsBuilder.setScanMode(ScanSettings.SCAN_MODE_BALANCED);
+ ScanSettings settings = settingsBuilder.build();
+
+ List<ScanFilter> filterList = new ArrayList<ScanFilter>(2);
+
+ mBluetoothLeScanner.startScan(filterList, settings, leScanCallback21);
+ mLeScanRunning = true;
} else {
- mBluetoothAdapter.stopLeScan(leScanCallback);
+ mBluetoothLeScanner.stopScan(leScanCallback21);
mLeScanRunning = false;
}
return (mLeScanRunning == isEnabled);
}
- // Device scan callback
- private final BluetoothAdapter.LeScanCallback leScanCallback =
- new BluetoothAdapter.LeScanCallback() {
+ // Device scan callback (SDK v21+)
+ private final ScanCallback leScanCallback21 = new ScanCallback() {
+ @Override
+ public void onScanResult(int callbackType, ScanResult result) {
+ super.onScanResult(callbackType, result);
+ leScanResult(qtObject, result.getDevice(), result.getRssi(), result.getScanRecord().getBytes());
+ }
- @Override
- public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
- if (qtObject == 0)
- return;
+ @Override
+ public void onBatchScanResults(List<ScanResult> results) {
+ super.onBatchScanResults(results);
+ for (ScanResult result : results)
+ leScanResult(qtObject, result.getDevice(), result.getRssi(), result.getScanRecord().getBytes());
- leScanResult(qtObject, device, rssi, scanRecord);
- }
- };
+ }
+
+ @Override
+ public void onScanFailed(int errorCode) {
+ super.onScanFailed(errorCode);
+ Log.d(TAG, "BTLE device scan failed with " + errorCode);
+ }
+ };
public native void leScanResult(long qtObject, BluetoothDevice device, int rssi, byte[] scanRecord);
diff --git a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
index 99245af3..f1f50516 100644
--- a/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
+++ b/src/bluetooth/android/devicediscoverybroadcastreceiver.cpp
@@ -516,7 +516,7 @@ QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(JNIEnv
const char *scanRecordBuffer = reinterpret_cast<const char *>(elems);
const int scanRecordLength = env->GetArrayLength(scanRecord);
- QList<QBluetoothUuid> serviceUuids;
+ QVector<QBluetoothUuid> serviceUuids;
int i = 0;
// Spec 4.2, Vol 3, Part C, Chapter 11
@@ -567,7 +567,7 @@ QBluetoothDeviceInfo DeviceDiscoveryBroadcastReceiver::retrieveDeviceInfo(JNIEnv
serviceUuids.append(foundService);
}
- info.setServiceUuids(serviceUuids, QBluetoothDeviceInfo::DataIncomplete);
+ info.setServiceUuids(serviceUuids);
env->ReleaseByteArrayElements(scanRecord, elems, JNI_ABORT);
}
diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro
index b104a902..974d8e8a 100644
--- a/src/bluetooth/bluetooth.pro
+++ b/src/bluetooth/bluetooth.pro
@@ -162,42 +162,34 @@ qtConfig(bluez) {
include(osx/osxbt.pri)
OBJECTIVE_SOURCES += \
qbluetoothlocaldevice_osx.mm \
- qbluetoothdevicediscoveryagent_osx.mm \
+ qbluetoothdevicediscoveryagent_darwin.mm \
qbluetoothserviceinfo_osx.mm \
qbluetoothservicediscoveryagent_osx.mm \
qbluetoothsocket_osx.mm \
qbluetoothserver_osx.mm \
qbluetoothtransferreply_osx.mm \
- qlowenergycontroller_osx.mm \
- qlowenergyservice_osx.mm
+ qlowenergycontroller_darwin.mm
PRIVATE_HEADERS += qbluetoothsocket_osx_p.h \
qbluetoothserver_osx_p.h \
qbluetoothtransferreply_osx_p.h \
- qbluetoothtransferreply_osx_p.h \
- qlowenergycontroller_osx_p.h
+ qlowenergycontroller_darwin_p.h
- SOURCES -= qbluetoothdevicediscoveryagent.cpp
SOURCES -= qbluetoothserviceinfo.cpp
SOURCES -= qbluetoothservicediscoveryagent.cpp
SOURCES -= qbluetoothsocket.cpp
SOURCES -= qbluetoothsocketbase.cpp
SOURCES -= qbluetoothserver.cpp
- SOURCES -= qlowenergyservice_p.cpp
- SOURCES -= qlowenergyservice.cpp
- SOURCES -= qlowenergycontroller.cpp
- SOURCES -= qlowenergycontrollerbase.cpp
} else:ios|tvos {
DEFINES += QT_IOS_BLUETOOTH
LIBS_PRIVATE += -framework Foundation -framework CoreBluetooth
OBJECTIVE_SOURCES += \
- qbluetoothdevicediscoveryagent_ios.mm \
- qlowenergycontroller_osx.mm \
- qlowenergyservice_osx.mm
+ qbluetoothdevicediscoveryagent_darwin.mm \
+ qlowenergycontroller_darwin.mm
PRIVATE_HEADERS += \
- qlowenergycontroller_osx_p.h \
+ qlowenergycontroller_darwin_p.h \
qbluetoothsocket_dummy_p.h
include(osx/osxbt.pri)
@@ -207,11 +199,6 @@ qtConfig(bluez) {
qbluetoothservicediscoveryagent_p.cpp \
qbluetoothsocket_dummy.cpp \
qbluetoothserver_p.cpp
-
- SOURCES -= qbluetoothdevicediscoveryagent.cpp
- SOURCES -= qlowenergyservice.cpp
- SOURCES -= qlowenergycontroller.cpp
- SOURCES -= qlowenergycontrollerbase.cpp
} else: qtConfig(winrt_bt) {
DEFINES += QT_WINRT_BLUETOOTH
!winrt {
diff --git a/src/bluetooth/osx/btdelegates.cpp b/src/bluetooth/osx/btdelegates.cpp
new file mode 100644
index 00000000..531ca1df
--- /dev/null
+++ b/src/bluetooth/osx/btdelegates.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "btdelegates_p.h"
+
+#if defined(Q_OS_MACOS)
+
+QT_BEGIN_NAMESPACE
+
+namespace DarwinBluetooth {
+
+DeviceInquiryDelegate::~DeviceInquiryDelegate()
+{
+}
+
+PairingDelegate::~PairingDelegate()
+{
+}
+
+SDPInquiryDelegate::~SDPInquiryDelegate()
+{
+}
+
+ChannelDelegate::~ChannelDelegate()
+{
+}
+
+ConnectionMonitor::~ConnectionMonitor()
+{
+}
+
+SocketListener::~SocketListener()
+{
+}
+
+} // namespace DarwinBluetooth
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/bluetooth/osx/btdelegates_p.h b/src/bluetooth/osx/btdelegates_p.h
new file mode 100644
index 00000000..11fbcc28
--- /dev/null
+++ b/src/bluetooth/osx/btdelegates_p.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BTDELEGATES_P_H
+#define BTDELEGATES_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qbluetoothdevicediscoveryagent.h"
+#include "qlowenergycontroller.h"
+#include "qbluetooth.h"
+
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qglobal.h>
+
+#if defined(Q_OS_MACOS)
+
+#include <IOKit/IOReturn.h>
+
+#include <cstdint>
+
+QT_BEGIN_NAMESPACE
+
+class QLowEnergyServicePrivate;
+class QBluetoothAddress;
+class QByteArray;
+
+namespace DarwinBluetooth {
+
+class DeviceInquiryDelegate
+{
+public:
+ virtual ~DeviceInquiryDelegate();
+
+ virtual void inquiryFinished() = 0;
+ virtual void error(IOReturn error) = 0;
+ virtual void classicDeviceFound(void *ioBluetoothDevice) = 0;
+};
+
+class PairingDelegate
+{
+public:
+ using BluetoothNumericValue = uint32_t;
+ using BluetoothPasskey = BluetoothNumericValue;
+
+ virtual ~PairingDelegate();
+
+ virtual void connecting(void *pair) = 0;
+ virtual void requestPIN(void *pair) = 0;
+ virtual void requestUserConfirmation(void *pair,
+ BluetoothNumericValue) = 0;
+ virtual void passkeyNotification(void *pair,
+ BluetoothPasskey passkey) = 0;
+ virtual void error(void *pair, IOReturn errorCode) = 0;
+ virtual void pairingFinished(void *pair) = 0;
+};
+
+class SDPInquiryDelegate {
+public:
+ virtual ~SDPInquiryDelegate();
+
+ virtual void SDPInquiryFinished(void *ioBluetoothDevice) = 0;
+ virtual void SDPInquiryError(void *ioBluetoothDevice, IOReturn errorCode) = 0;
+};
+
+// L2CAP and RFCOMM.
+class ChannelDelegate
+{
+public:
+ virtual ~ChannelDelegate();
+
+ virtual void setChannelError(IOReturn errorCode) = 0;
+ virtual void channelOpenComplete() = 0;
+ virtual void channelClosed() = 0;
+
+ virtual void readChannelData(void *data, std::size_t size) = 0;
+ virtual void writeComplete() = 0;
+};
+
+class ConnectionMonitor {
+public:
+ virtual ~ConnectionMonitor();
+
+ virtual void deviceConnected(const QBluetoothAddress &address) = 0;
+ virtual void deviceDisconnected(const QBluetoothAddress &address) = 0;
+};
+
+class SocketListener
+{
+public:
+ virtual ~SocketListener();
+
+ virtual void openNotifyRFCOMM(void *rfcommChannel) = 0;
+ virtual void openNotifyL2CAP(void *l2capChannel) = 0;
+};
+
+
+} // namespace DarwinBluetooth
+
+QT_END_NAMESPACE
+
+#endif // Q_OS_MACOS
+
+#endif // DARWINBTDELEGATES_P_H
diff --git a/src/bluetooth/osx/btraii.mm b/src/bluetooth/osx/btraii.mm
new file mode 100644
index 00000000..a1bf2a8d
--- /dev/null
+++ b/src/bluetooth/osx/btraii.mm
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "btraii_p.h"
+
+#include <qdebug.h>
+
+#include <Foundation/Foundation.h>
+
+#include <utility>
+
+QT_BEGIN_NAMESPACE
+
+namespace DarwinBluetooth {
+
+StrongReference::StrongReference(void *object, RetainPolicy policy)
+ : objCInstance(object)
+{
+ if (policy == RetainPolicy::doInitialRetain)
+ objCInstance = [getAs<NSObject>() retain];
+}
+
+StrongReference::StrongReference(const StrongReference &other)
+{
+ objCInstance = [other.getAs<NSObject>() retain];
+}
+
+StrongReference::StrongReference(StrongReference &&other)
+{
+ std::swap(objCInstance, other.objCInstance);
+}
+
+StrongReference::~StrongReference()
+{
+ [getAs<NSObject>() release];
+}
+
+StrongReference &StrongReference::operator = (const StrongReference &other) noexcept
+{
+ if (this != &other) {
+ [getAs<NSObject>() release];
+ objCInstance = [other.getAs<NSObject>() retain];
+ }
+
+ return *this;
+}
+
+StrongReference &StrongReference::operator = (StrongReference &&other) noexcept
+{
+ swap(other);
+ return *this;
+}
+
+void StrongReference::reset()
+{
+ [getAs<NSObject>() release];
+ objCInstance = nullptr;
+}
+
+void StrongReference::reset(void *obj, RetainPolicy policy)
+{
+ [getAs<NSObject>() release];
+ objCInstance = obj;
+
+ if (policy == RetainPolicy::doInitialRetain) {
+ auto newInstance = static_cast<NSObject *>(obj);
+ Q_ASSERT(newInstance);
+ objCInstance = [newInstance retain];
+ }
+}
+
+} // namespace DarwinBluetooth
+
+QT_END_NAMESPACE
diff --git a/src/bluetooth/osx/btraii_p.h b/src/bluetooth/osx/btraii_p.h
new file mode 100644
index 00000000..6053d63b
--- /dev/null
+++ b/src/bluetooth/osx/btraii_p.h
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BTRAII_P_H
+#define BTRAII_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+#include <utility>
+
+QT_BEGIN_NAMESPACE
+
+namespace DarwinBluetooth {
+
+enum class RetainPolicy
+{
+ noInitialRetain,
+ doInitialRetain
+};
+
+// The class StrongReference and its descendant ScopedGuard
+// are RAII classes dealing with raw pointers to NSObject class
+// and its descendants (and thus hiding Objective-C's retain/
+// release semantics). The header itself is meant to be included
+// into *.cpp files so it's a pure C++ code without any Objective-C
+// syntax. Thus it's a bit clunky - the type information is 'erased'
+// and has to be enforced by the code using these smart pointers.
+// That's because these types are Objective-C classes - thus require
+// Objective-C compiler to work. Member-function template 'getAs' is
+// a convenience shortcut giving the desired pointer type in
+// Objective-C++ files (*.mm).
+
+// TODO: on top of these classes I can build ObjCStrongReference (it's
+// now inside osxbtutils_p.h, a template class that does have type
+// information needed but works only in Objective-C++ environment.
+class StrongReference
+{
+public:
+ StrongReference() = default;
+ StrongReference(void *object, RetainPolicy policy);
+ StrongReference(const StrongReference &other);
+ StrongReference(StrongReference &&other);
+
+ ~StrongReference();
+
+ StrongReference &operator = (const StrongReference &other) noexcept;
+ StrongReference &operator = (StrongReference &&other) noexcept;
+
+ void swap(StrongReference &other) noexcept
+ {
+ std::swap(objCInstance, other.objCInstance);
+ }
+
+ void reset();
+ void reset(void *newInstance, RetainPolicy policy);
+
+ template<class ObjCType>
+ ObjCType *getAs() const
+ {
+ return static_cast<ObjCType *>(objCInstance);
+ }
+
+ operator bool() const
+ {
+ return !!objCInstance;
+ }
+
+private:
+ void *objCInstance = nullptr;
+};
+
+class ScopedPointer final : public StrongReference
+{
+public:
+ ScopedPointer() = default;
+ ScopedPointer(void *instance, RetainPolicy policy)
+ : StrongReference(instance, policy)
+ {
+ }
+
+private:
+ Q_DISABLE_COPY_MOVE(ScopedPointer)
+};
+
+} // namespace DarwinBluetooth
+
+QT_END_NAMESPACE
+
+#endif // BTRAII_P_H
diff --git a/src/bluetooth/osx/osxbt.pri b/src/bluetooth/osx/osxbt.pri
index b7ac0535..89276310 100644
--- a/src/bluetooth/osx/osxbt.pri
+++ b/src/bluetooth/osx/osxbt.pri
@@ -1,8 +1,15 @@
-SOURCES += osx/uistrings.cpp osx/osxbtnotifier.cpp
+SOURCES += osx/uistrings.cpp \
+ osx/osxbtnotifier.cpp \
+ osx/btdelegates.cpp
+
PRIVATE_HEADERS += osx/uistrings_p.h \
- osx/osxbtgcdtimer_p.h
+ osx/osxbtgcdtimer_p.h \
+ osx/btraii_p.h \
+ osx/btdelegates_p.h
+
-OBJECTIVE_SOURCES += osx/osxbtgcdtimer.mm
+OBJECTIVE_SOURCES += osx/osxbtgcdtimer.mm \
+ osx/btraii.mm
#QMAKE_CXXFLAGS_WARN_ON += -Wno-nullability-completeness
CONFIG(osx) {
diff --git a/src/bluetooth/osx/osxbtdeviceinquiry.mm b/src/bluetooth/osx/osxbtdeviceinquiry.mm
index 57cd73e1..3a77c1f7 100644
--- a/src/bluetooth/osx/osxbtdeviceinquiry.mm
+++ b/src/bluetooth/osx/osxbtdeviceinquiry.mm
@@ -43,30 +43,16 @@
#include <QtCore/qloggingcategory.h>
#include <QtCore/qdebug.h>
-QT_BEGIN_NAMESPACE
-
-namespace OSXBluetooth {
-
-DeviceInquiryDelegate::~DeviceInquiryDelegate()
-{
-}
-
-}
-
-
-QT_END_NAMESPACE
-
QT_USE_NAMESPACE
-
@implementation QT_MANGLE_NAMESPACE(OSXBTDeviceInquiry)
{
IOBluetoothDeviceInquiry *m_inquiry;
bool m_active;
- QT_PREPEND_NAMESPACE(OSXBluetooth::DeviceInquiryDelegate) *m_delegate;//C++ "delegate"
+ DarwinBluetooth::DeviceInquiryDelegate *m_delegate;//C++ "delegate"
}
-- (id)initWithDelegate:(OSXBluetooth::DeviceInquiryDelegate *)delegate
+- (id)initWithDelegate:(DarwinBluetooth::DeviceInquiryDelegate *)delegate
{
if (self = [super init]) {
Q_ASSERT_X(delegate, Q_FUNC_INFO, "invalid device inquiry delegate (null)");
@@ -158,9 +144,9 @@ QT_USE_NAMESPACE
// QtBluetooth has not too many error codes, 'UnknownError' is not really
// useful, report the actual error code here:
qCWarning(QT_BT_OSX) << "IOKit error code: " << error;
- m_delegate->error(sender, error);
+ m_delegate->error(error);
} else {
- m_delegate->inquiryFinished(sender);
+ m_delegate->inquiryFinished();
}
}
@@ -171,7 +157,7 @@ QT_USE_NAMESPACE
return;
Q_ASSERT_X(m_delegate, Q_FUNC_INFO, "invalid device inquiry delegate (null)");
- m_delegate->deviceFound(sender, device);
+ m_delegate->classicDeviceFound(device);
}
- (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry *)sender
diff --git a/src/bluetooth/osx/osxbtdeviceinquiry_p.h b/src/bluetooth/osx/osxbtdeviceinquiry_p.h
index 0fec2db2..86ed3fdf 100644
--- a/src/bluetooth/osx/osxbtdeviceinquiry_p.h
+++ b/src/bluetooth/osx/osxbtdeviceinquiry_p.h
@@ -52,36 +52,16 @@
//
#include "osxbluetooth_p.h"
+#include "btdelegates_p.h"
#include <QtCore/qglobal.h>
#include <Foundation/Foundation.h>
#include <IOKit/IOReturn.h>
-@class QT_MANGLE_NAMESPACE(OSXBTDeviceInquiry);
-
-QT_BEGIN_NAMESPACE
-
-namespace OSXBluetooth {
-
-class DeviceInquiryDelegate {
-public:
- typedef QT_MANGLE_NAMESPACE(OSXBTDeviceInquiry) DeviceInquiryObjC;
-
- virtual ~DeviceInquiryDelegate();
-
- virtual void inquiryFinished(IOBluetoothDeviceInquiry *inq) = 0;
- virtual void error(IOBluetoothDeviceInquiry *inq, IOReturn error) = 0;
- virtual void deviceFound(IOBluetoothDeviceInquiry *inq, IOBluetoothDevice *device) = 0;
-};
-
-}
-
-QT_END_NAMESPACE
-
@interface QT_MANGLE_NAMESPACE(OSXBTDeviceInquiry) : NSObject<IOBluetoothDeviceInquiryDelegate>
-- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(OSXBluetooth::DeviceInquiryDelegate) *)delegate;
+- (id)initWithDelegate:(QT_PREPEND_NAMESPACE(DarwinBluetooth::DeviceInquiryDelegate) *)delegate;
- (void)dealloc;
- (bool)isActive;
diff --git a/src/bluetooth/osx/osxbtnotifier_p.h b/src/bluetooth/osx/osxbtnotifier_p.h
index dca6c268..397214d0 100644
--- a/src/bluetooth/osx/osxbtnotifier_p.h
+++ b/src/bluetooth/osx/osxbtnotifier_p.h
@@ -96,7 +96,6 @@ Q_SIGNALS:
void CBManagerError(QLowEnergyController::Error error);
void CBManagerError(const QBluetoothUuid &serviceUuid, QLowEnergyController::Error error);
void CBManagerError(const QBluetoothUuid &serviceUuid, QLowEnergyService::ServiceError error);
-
};
}
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
index 443be14d..2f0524d4 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_android.cpp
@@ -363,7 +363,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::processDiscoveredDevices(
discoveredDevices.append(info);
qCDebug(QT_BT_ANDROID) << "Device found: " << info.name() << info.address().toString()
- << "isLeScanResult:" << isLeResult;
+ << "isLeScanResult:" << isLeResult
+ << "Manufacturer data size:" << info.manufacturerData().size();
emit q->deviceDiscovered(info);
}
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm
index f62ca0dd..d9883d28 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_osx.mm
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_darwin.mm
@@ -37,11 +37,14 @@
**
****************************************************************************/
+#include "qbluetoothdevicediscoveryagent_p.h"
#include "qbluetoothdevicediscoveryagent.h"
+
#include "osx/osxbtledeviceinquiry_p.h"
+#ifdef Q_OS_MACOS
#include "osx/osxbtdeviceinquiry_p.h"
-#include "qbluetoothlocaldevice.h"
#include "osx/osxbtsdpinquiry_p.h"
+#endif // Q_OS_MACOS
#include "qbluetoothdeviceinfo.h"
#include "osx/osxbtnotifier_p.h"
#include "osx/osxbtutility_p.h"
@@ -51,13 +54,14 @@
#include "qbluetoothaddress.h"
#include "osx/uistrings_p.h"
#include "qbluetoothuuid.h"
+#include "osx/btraii_p.h"
#include <QtCore/qloggingcategory.h>
#include <QtCore/qscopedpointer.h>
+#include <QtCore/qvector.h>
#include <QtCore/qglobal.h>
#include <QtCore/qstring.h>
#include <QtCore/qdebug.h>
-#include <QtCore/qlist.h>
#include <Foundation/Foundation.h>
@@ -75,108 +79,42 @@ void registerQDeviceDiscoveryMetaType()
initDone = true;
}
}
+#ifdef Q_OS_MACOS
+using InquiryObjC = QT_MANGLE_NAMESPACE(OSXBTDeviceInquiry);
+#endif // Q_OS_MACOS
-}//namespace
-
-class QBluetoothDeviceDiscoveryAgentPrivate : public QObject,
- public OSXBluetooth::DeviceInquiryDelegate
-{
- friend class QBluetoothDeviceDiscoveryAgent;
-public:
- template<class T>
- using ObjCScopedPointer = OSXBluetooth::ObjCScopedPointer<T>;
- using LEDeviceInquiryObjC = QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry);
-
- QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress & address,
- QBluetoothDeviceDiscoveryAgent *q);
-
- ~QBluetoothDeviceDiscoveryAgentPrivate() override;
-
- bool isValid() const;
- bool isActive() const;
-
- void start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods);
- void startClassic();
- void startLE();
- void stop();
-
-private:
- enum AgentState {
- NonActive,
- ClassicScan,
- LEScan
- };
-
- // DeviceInquiryDelegate:
- void inquiryFinished(IOBluetoothDeviceInquiry *inq) override;
- void error(IOBluetoothDeviceInquiry *inq, IOReturn error) override;
- void deviceFound(IOBluetoothDeviceInquiry *inq, IOBluetoothDevice *device) override;
-
- void LEinquiryFinished();
- void LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error);
- void LEnotSupported();
-
- // Check if it's a really new device/updated info and emit
- // q_ptr->deviceDiscovered.
- void deviceFound(const QBluetoothDeviceInfo &newDeviceInfo);
-
- void setError(IOReturn error, const QString &text = QString());
- void setError(QBluetoothDeviceDiscoveryAgent::Error,
- const QString &text = QString());
-
- QBluetoothDeviceDiscoveryAgent *q_ptr;
- AgentState agentState;
-
- QBluetoothAddress adapterAddress;
+using LEInquiryObjC = QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry);
- bool startPending;
- bool stopPending;
-
- QBluetoothDeviceDiscoveryAgent::Error lastError;
- QString errorString;
-
- QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType;
-
- using DeviceInquiry = ObjCScopedPointer<DeviceInquiryObjC>;
- DeviceInquiry inquiry;
-
- using LEDeviceInquiry = ObjCScopedPointer<LEDeviceInquiryObjC>;
- LEDeviceInquiry inquiryLE;
-
- using HostController = ObjCScopedPointer<IOBluetoothHostController>;
- HostController hostController;
-
- using DevicesList = QList<QBluetoothDeviceInfo>;
- DevicesList discoveredDevices;
-
- int lowEnergySearchTimeout;
- QBluetoothDeviceDiscoveryAgent::DiscoveryMethods requestedMethods;
-};
+} //namespace
QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress &adapter,
QBluetoothDeviceDiscoveryAgent *q) :
- q_ptr(q),
+ inquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry),
+ lastError(QBluetoothDeviceDiscoveryAgent::NoError),
agentState(NonActive),
adapterAddress(adapter),
startPending(false),
stopPending(false),
- lastError(QBluetoothDeviceDiscoveryAgent::NoError),
- inquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry),
lowEnergySearchTimeout(OSXBluetooth::defaultLEScanTimeoutMS),
- requestedMethods(QBluetoothDeviceDiscoveryAgent::ClassicMethod
- | QBluetoothDeviceDiscoveryAgent::LowEnergyMethod)
+#ifdef Q_OS_MACOS
+ requestedMethods(QBluetoothDeviceDiscoveryAgent::ClassicMethod | QBluetoothDeviceDiscoveryAgent::LowEnergyMethod),
+#else
+ requestedMethods(QBluetoothDeviceDiscoveryAgent::ClassicMethod),
+#endif // Q_OS_MACOS
+ q_ptr(q)
{
registerQDeviceDiscoveryMetaType();
Q_ASSERT_X(q != nullptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- HostController controller([[IOBluetoothHostController defaultController] retain]);
- if (!controller || [controller powerState] != kBluetoothHCIPowerStateON) {
+#ifdef Q_OS_MACOS
+ IOBluetoothHostController *hostController = [IOBluetoothHostController defaultController];
+ if (!hostController || [hostController powerState] != kBluetoothHCIPowerStateON) {
qCCritical(QT_BT_OSX) << "no default host controller or adapter is off";
return;
}
-
- hostController.reset(controller.take());
+ controller.reset(hostController, DarwinBluetooth::RetainPolicy::doInitialRetain);
+#endif
}
QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
@@ -185,7 +123,7 @@ QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
// We want the LE scan to stop as soon as possible.
if (dispatch_queue_t leQueue = OSXBluetooth::qt_LE_queue()) {
// Local variable to be retained ...
- LEDeviceInquiryObjC *inq = inquiryLE.data();
+ LEInquiryObjC *inq = inquiryLE.getAs<LEInquiryObjC>();
dispatch_sync(leQueue, ^{
[inq stop];
});
@@ -193,11 +131,6 @@ QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
}
}
-bool QBluetoothDeviceDiscoveryAgentPrivate::isValid() const
-{
- return hostController && [hostController powerState] == kBluetoothHCIPowerStateON;
-}
-
bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const
{
if (startPending)
@@ -211,12 +144,19 @@ bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const
void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods)
{
- Q_ASSERT(isValid());
Q_ASSERT(!isActive());
Q_ASSERT(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError);
Q_ASSERT(methods & (QBluetoothDeviceDiscoveryAgent::ClassicMethod
| QBluetoothDeviceDiscoveryAgent::LowEnergyMethod));
+#ifdef Q_OS_MACOS
+ if (!controller) {
+ setError(QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError);
+ emit q_ptr->error(lastError);
+ return;
+ }
+#endif // Q_OS_MACOS
+
requestedMethods = methods;
if (stopPending) {
@@ -230,16 +170,18 @@ void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent
agentState = NonActive;
discoveredDevices.clear();
setError(QBluetoothDeviceDiscoveryAgent::NoError);
-
+#ifdef Q_OS_MACOS
if (requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod)
return startClassic();
+#endif // Q_OS_MACOS
startLE();
}
+#ifdef Q_OS_MACOS
+
void QBluetoothDeviceDiscoveryAgentPrivate::startClassic()
{
- Q_ASSERT(isValid());
Q_ASSERT(!isActive());
Q_ASSERT(lastError == QBluetoothDeviceDiscoveryAgent::NoError);
Q_ASSERT(requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod);
@@ -249,7 +191,9 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startClassic()
if (!inquiry) {
// The first Classic scan for this DDA.
- inquiry.reset([[DeviceInquiryObjC alloc]initWithDelegate:this]);
+ inquiry.reset([[InquiryObjC alloc] initWithDelegate:this],
+ DarwinBluetooth::RetainPolicy::noInitialRetain);
+
if (!inquiry) {
qCCritical(QT_BT_OSX) << "failed to initialize an Classic device inquiry";
setError(QBluetoothDeviceDiscoveryAgent::UnknownError,
@@ -261,7 +205,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startClassic()
agentState = ClassicScan;
- const IOReturn res = [inquiry start];
+ const IOReturn res = [inquiry.getAs<InquiryObjC>() start];
if (res != kIOReturnSuccess) {
setError(res, QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STARTED));
agentState = NonActive;
@@ -269,9 +213,10 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startClassic()
}
}
+#endif // Q_OS_MACOS
+
void QBluetoothDeviceDiscoveryAgentPrivate::startLE()
{
- Q_ASSERT(isValid());
Q_ASSERT(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError);
Q_ASSERT(requestedMethods & QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
@@ -291,7 +236,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startLE()
this, DeviceMemFunPtr(&QBluetoothDeviceDiscoveryAgentPrivate::deviceFound));
// Check queue and create scanner:
- inquiryLE.reset([[LEDeviceInquiryObjC alloc] initWithNotifier:notifier.data()]);
+ inquiryLE.reset([[LEInquiryObjC alloc] initWithNotifier:notifier.data()],
+ DarwinBluetooth::RetainPolicy::noInitialRetain);
if (inquiryLE)
notifier.take(); // Whatever happens next, inquiryLE is already the owner ...
@@ -307,7 +253,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startLE()
// Now start in on LE queue:
agentState = LEScan;
// We need the local variable so that it's retained ...
- LEDeviceInquiryObjC *inq = inquiryLE.data();
+ LEInquiryObjC *inq = inquiryLE.getAs<LEInquiryObjC>();
dispatch_async(leQueue, ^{
[inq startWithTimeout:lowEnergySearchTimeout];
});
@@ -315,7 +261,6 @@ void QBluetoothDeviceDiscoveryAgentPrivate::startLE()
void QBluetoothDeviceDiscoveryAgentPrivate::stop()
{
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "called on invalid device discovery agent");
Q_ASSERT_X(isActive(), Q_FUNC_INFO, "called whithout active inquiry");
Q_ASSERT_X(lastError != QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError,
Q_FUNC_INFO, "called with invalid bluetooth adapter");
@@ -328,8 +273,9 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop()
setError(QBluetoothDeviceDiscoveryAgent::NoError);
+#ifdef Q_OS_MACOS
if (agentState == ClassicScan) {
- const IOReturn res = [inquiry stop];
+ const IOReturn res = [inquiry.getAs<InquiryObjC>() stop];
if (res != kIOReturnSuccess) {
qCWarning(QT_BT_OSX) << "failed to stop";
startPending = prevStart;
@@ -338,10 +284,14 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop()
emit q_ptr->error(lastError);
}
} else {
+#else
+ {
+ Q_UNUSED(prevStart)
+#endif // Q_OS_MACOS
dispatch_queue_t leQueue(qt_LE_queue());
Q_ASSERT(leQueue);
// We need the local variable so that it's retained ...
- LEDeviceInquiryObjC *inq = inquiryLE.data();
+ LEInquiryObjC *inq = inquiryLE.getAs<LEInquiryObjC>();
dispatch_sync(leQueue, ^{
[inq stop];
});
@@ -351,12 +301,10 @@ void QBluetoothDeviceDiscoveryAgentPrivate::stop()
}
}
-void QBluetoothDeviceDiscoveryAgentPrivate::inquiryFinished(IOBluetoothDeviceInquiry *inq)
-{
- Q_UNUSED(inq)
-
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid device discovery agent"); //We can never be here.
+#ifdef Q_OS_MACOS
+void QBluetoothDeviceDiscoveryAgentPrivate::inquiryFinished()
+{
// The subsequent start(LE) function (if any)
// will (re)set the correct state.
agentState = NonActive;
@@ -381,12 +329,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::inquiryFinished(IOBluetoothDeviceInq
}
}
-void QBluetoothDeviceDiscoveryAgentPrivate::error(IOBluetoothDeviceInquiry *inq, IOReturn error)
+void QBluetoothDeviceDiscoveryAgentPrivate::error(IOReturn error)
{
- Q_UNUSED(inq)
-
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid device discovery agent");
-
startPending = false;
stopPending = false;
@@ -395,12 +339,11 @@ void QBluetoothDeviceDiscoveryAgentPrivate::error(IOBluetoothDeviceInquiry *inq,
emit q_ptr->error(lastError);
}
-void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(IOBluetoothDeviceInquiry *inq, IOBluetoothDevice *device)
+void QBluetoothDeviceDiscoveryAgentPrivate::classicDeviceFound(void *obj)
{
- Q_UNUSED(inq)
-
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid device discovery agent");
+ auto device = static_cast<IOBluetoothDevice *>(obj);
Q_ASSERT_X(device, Q_FUNC_INFO, "invalid IOBluetoothDevice (nil)");
+
Q_ASSERT_X(agentState == ClassicScan, Q_FUNC_INFO,
"invalid agent state (expected classic scan)");
@@ -417,7 +360,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(IOBluetoothDeviceInquiry
if (device.name)
deviceName = QString::fromNSString(device.name);
- const qint32 classOfDevice(device.classOfDevice);
+ const auto classOfDevice = qint32(device.classOfDevice);
QBluetoothDeviceInfo deviceInfo(deviceAddress, deviceName, classOfDevice);
deviceInfo.setCoreConfigurations(QBluetoothDeviceInfo::BaseRateCoreConfiguration);
@@ -439,6 +382,8 @@ void QBluetoothDeviceDiscoveryAgentPrivate::setError(IOReturn error, const QStri
setError(QBluetoothDeviceDiscoveryAgent::UnknownError, text);
}
+#endif // Q_OS_MACOS
+
void QBluetoothDeviceDiscoveryAgentPrivate::setError(QBluetoothDeviceDiscoveryAgent::Error error, const QString &text)
{
lastError = error;
@@ -459,14 +404,14 @@ void QBluetoothDeviceDiscoveryAgentPrivate::setError(QBluetoothDeviceDiscoveryAg
case QBluetoothDeviceDiscoveryAgent::InputOutputError:
errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_IO);
break;
+ case QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError:
+ errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_NOTSUPPORTED);
+ break;
case QBluetoothDeviceDiscoveryAgent::UnknownError:
default:
errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_UNKNOWN_ERROR);
}
}
-
- if (lastError != QBluetoothDeviceDiscoveryAgent::NoError)
- qCDebug(QT_BT_OSX) << "error set:"<<errorString;
}
void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error)
@@ -487,6 +432,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported()
{
qCDebug(QT_BT_OSX) << "no Bluetooth LE support";
+#ifdef Q_OS_MACOS
if (requestedMethods & QBluetoothDeviceDiscoveryAgent::ClassicMethod) {
// Having both Classic | LE means this is not an error.
LEinquiryFinished();
@@ -497,6 +443,13 @@ void QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported()
// as UnsupportedDiscoveryMethod.
LEinquiryError(QBluetoothDeviceDiscoveryAgent::UnsupportedDiscoveryMethod);
}
+#else
+ inquiryLE.reset();
+ startPending = false;
+ stopPending = false;
+ setError(QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError);
+ emit q_ptr->error(lastError);
+#endif
}
void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryFinished()
@@ -522,8 +475,12 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QBluetoothDeviceIn
// Core Bluetooth does not allow us to access addresses, we have to use uuid instead.
// This uuid has nothing to do with uuids in Bluetooth in general (it's generated by
// Apple's framework using some algorithm), but it's a 128-bit uuid after all.
- const bool isLE = newDeviceInfo.coreConfigurations() == QBluetoothDeviceInfo::LowEnergyCoreConfiguration;
-
+ const bool isLE =
+#ifdef Q_OS_MACOS
+ newDeviceInfo.coreConfigurations() == QBluetoothDeviceInfo::LowEnergyCoreConfiguration;
+#else
+ true;
+#endif // Q_OS_MACOS
for (int i = 0, e = discoveredDevices.size(); i < e; ++i) {
if (isLE) {
if (discoveredDevices[i].deviceUuid() == newDeviceInfo.deviceUuid()) {
@@ -564,6 +521,7 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QBluetoothDeviceIn
return;
}
} else {
+#ifdef Q_OS_MACOS
if (discoveredDevices[i].address() == newDeviceInfo.address()) {
if (discoveredDevices[i] == newDeviceInfo)
return;
@@ -572,6 +530,9 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QBluetoothDeviceIn
emit q_ptr->deviceDiscovered(newDeviceInfo);
return;
}
+#else
+ Q_UNREACHABLE();
+#endif // Q_OS_MACOS
}
}
@@ -579,125 +540,13 @@ void QBluetoothDeviceDiscoveryAgentPrivate::deviceFound(const QBluetoothDeviceIn
emit q_ptr->deviceDiscovered(newDeviceInfo);
}
-QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent(QObject *parent) :
- QObject(parent),
- d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate(QBluetoothAddress(), this))
-{
-}
-
-QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent(
- const QBluetoothAddress &deviceAdapter, QObject *parent) :
- QObject(parent),
- d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate(deviceAdapter, this))
-{
- if (!deviceAdapter.isNull()) {
- const QList<QBluetoothHostInfo> localDevices = QBluetoothLocalDevice::allDevices();
- for (const QBluetoothHostInfo &hostInfo : localDevices) {
- if (hostInfo.address() == deviceAdapter)
- return;
- }
- d_ptr->setError(InvalidBluetoothAdapterError);
- }
-}
-
-QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent()
-{
- delete d_ptr;
-}
-
-QBluetoothDeviceDiscoveryAgent::InquiryType QBluetoothDeviceDiscoveryAgent::inquiryType() const
-{
- return d_ptr->inquiryType;
-}
-
-void QBluetoothDeviceDiscoveryAgent::setInquiryType(InquiryType type)
-{
- d_ptr->inquiryType = type;
-}
-
-QList<QBluetoothDeviceInfo> QBluetoothDeviceDiscoveryAgent::discoveredDevices() const
-{
- return d_ptr->discoveredDevices;
-}
-
QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods()
{
+#ifdef Q_OS_MACOS
return ClassicMethod | LowEnergyMethod;
-}
-
-void QBluetoothDeviceDiscoveryAgent::start()
-{
- start(supportedDiscoveryMethods());
-}
-
-void QBluetoothDeviceDiscoveryAgent::start(DiscoveryMethods methods)
-{
- if (methods == NoMethod)
- return;
-
- if ((supportedDiscoveryMethods() & methods) != methods) {
- d_ptr->lastError = UnsupportedDiscoveryMethod;
- d_ptr->errorString = tr("One or more device discovery methods "
- "are not supported on this platform");
- emit error(d_ptr->lastError);
- return;
- }
-
- if (d_ptr->lastError != InvalidBluetoothAdapterError) {
- if (d_ptr->isValid()) {
- if (!isActive())
- d_ptr->start(methods);
- } else {
- // We previously failed to initialize d_ptr correctly:
- // either some memory allocation problem or
- // no BT adapter found.
- d_ptr->setError(InvalidBluetoothAdapterError);
- emit error(InvalidBluetoothAdapterError);
- }
- }
-}
-
-void QBluetoothDeviceDiscoveryAgent::stop()
-{
- if (d_ptr->isValid()) {
- if (isActive() && d_ptr->lastError != InvalidBluetoothAdapterError)
- d_ptr->stop();
- }
-}
-
-bool QBluetoothDeviceDiscoveryAgent::isActive() const
-{
- if (d_ptr->isValid())
- return d_ptr->isActive();
-
- return false;
-}
-
-QBluetoothDeviceDiscoveryAgent::Error QBluetoothDeviceDiscoveryAgent::error() const
-{
- return d_ptr->lastError;
-}
-
-QString QBluetoothDeviceDiscoveryAgent::errorString() const
-{
- return d_ptr->errorString;
-}
-
-void QBluetoothDeviceDiscoveryAgent::setLowEnergyDiscoveryTimeout(int timeout)
-{
- // cannot deliberately turn it off
- if (timeout < 0) {
- qCDebug(QT_BT_OSX) << "The Bluetooth Low Energy device discovery timeout cannot be negative.";
- return;
- }
-
- d_ptr->lowEnergySearchTimeout = timeout;
- return;
-}
-
-int QBluetoothDeviceDiscoveryAgent::lowEnergyDiscoveryTimeout() const
-{
- return d_ptr->lowEnergySearchTimeout;
+#else
+ return LowEnergyMethod;
+#endif // Q_OS_MACOS
}
QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm b/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm
deleted file mode 100644
index 059f244d..00000000
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_ios.mm
+++ /dev/null
@@ -1,458 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtBluetooth module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qbluetoothdevicediscoveryagent.h"
-#include "osx/osxbtledeviceinquiry_p.h"
-#include "qbluetoothlocaldevice.h"
-#include "qbluetoothdeviceinfo.h"
-#include "osx/osxbtnotifier_p.h"
-#include "osx/osxbtutility_p.h"
-#include "osx/uistrings_p.h"
-#include "qbluetoothuuid.h"
-
-#include <QtCore/qloggingcategory.h>
-#include <QtCore/qobject.h>
-#include <QtCore/qglobal.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qdebug.h>
-#include <QtCore/qlist.h>
-
-#include <CoreBluetooth/CoreBluetooth.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace
-{
-
-void registerQDeviceDiscoveryMetaType()
-{
- static bool initDone = false;
- if (!initDone) {
- qRegisterMetaType<QBluetoothDeviceInfo>();
- qRegisterMetaType<QBluetoothDeviceDiscoveryAgent::Error>();
- initDone = true;
- }
-}
-
-}//namespace
-
-class QBluetoothDeviceDiscoveryAgentPrivate : public QObject
-{
- friend class QBluetoothDeviceDiscoveryAgent;
-
-public:
- QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress &address,
- QBluetoothDeviceDiscoveryAgent *q);
- virtual ~QBluetoothDeviceDiscoveryAgentPrivate();
-
- bool isActive() const;
-
- void start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods m);
- void stop();
-
-private:
- using LEDeviceInquiryObjC = QT_MANGLE_NAMESPACE(OSXBTLEDeviceInquiry);
-
- void LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error);
- void LEnotSupported();
- void LEdeviceFound(const QBluetoothDeviceInfo &info);
- void LEinquiryFinished();
-
- void setError(QBluetoothDeviceDiscoveryAgent::Error, const QString &text = QString());
-
- QBluetoothDeviceDiscoveryAgent *q_ptr;
-
- QBluetoothDeviceDiscoveryAgent::Error lastError;
- QString errorString;
-
- QBluetoothDeviceDiscoveryAgent::InquiryType inquiryType;
-
- using LEDeviceInquiry = OSXBluetooth::ObjCScopedPointer<LEDeviceInquiryObjC>;
- LEDeviceInquiry inquiryLE;
-
- using DevicesList = QList<QBluetoothDeviceInfo>;
- DevicesList discoveredDevices;
-
- bool startPending;
- bool stopPending;
-
- int lowEnergySearchTimeout;
-};
-
-QBluetoothDeviceDiscoveryAgentPrivate::QBluetoothDeviceDiscoveryAgentPrivate(const QBluetoothAddress &adapter,
- QBluetoothDeviceDiscoveryAgent *q) :
- q_ptr(q),
- lastError(QBluetoothDeviceDiscoveryAgent::NoError),
- inquiryType(QBluetoothDeviceDiscoveryAgent::GeneralUnlimitedInquiry),
- startPending(false),
- stopPending(false),
- lowEnergySearchTimeout(OSXBluetooth::defaultLEScanTimeoutMS)
-{
- Q_UNUSED(adapter);
-
- registerQDeviceDiscoveryMetaType();
- Q_ASSERT_X(q != nullptr, Q_FUNC_INFO, "invalid q_ptr (null)");
-}
-
-QBluetoothDeviceDiscoveryAgentPrivate::~QBluetoothDeviceDiscoveryAgentPrivate()
-{
- if (inquiryLE) {
- // We want the LE scan to stop as soon as possible.
- if (dispatch_queue_t leQueue = OSXBluetooth::qt_LE_queue()) {
- // Local variable to be retained ...
- LEDeviceInquiryObjC *inq = inquiryLE.data();
- dispatch_sync(leQueue, ^{
- [inq stop];
- });
- }
- }
-}
-
-bool QBluetoothDeviceDiscoveryAgentPrivate::isActive() const
-{
- if (startPending)
- return true;
- if (stopPending)
- return false;
-
- return inquiryLE;
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods /*methods*/)
-{
- Q_ASSERT_X(!isActive(), Q_FUNC_INFO, "called on active device discovery agent");
-
- if (stopPending) {
- startPending = true;
- return;
- }
-
- using namespace OSXBluetooth;
-
- QScopedPointer<LECBManagerNotifier> notifier(new LECBManagerNotifier);
- // Connections:
- using ErrMemFunPtr = void (LECBManagerNotifier::*)(QBluetoothDeviceDiscoveryAgent::Error);
- notifier->connect(notifier.data(), ErrMemFunPtr(&LECBManagerNotifier::CBManagerError),
- this, &QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryError);
- notifier->connect(notifier.data(), &LECBManagerNotifier::LEnotSupported,
- this, &QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported);
- notifier->connect(notifier.data(), &LECBManagerNotifier::discoveryFinished,
- this, &QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryFinished);
- notifier->connect(notifier.data(), &LECBManagerNotifier::deviceDiscovered,
- this, &QBluetoothDeviceDiscoveryAgentPrivate::LEdeviceFound);
-
- inquiryLE.reset([[LEDeviceInquiryObjC alloc] initWithNotifier:notifier.data()]);
- if (inquiryLE)
- notifier.take(); // Whatever happens next, inquiryLE is already the owner ...
-
- dispatch_queue_t leQueue(qt_LE_queue());
- if (!leQueue || !inquiryLE) {
- setError(QBluetoothDeviceDiscoveryAgent::UnknownError,
- QCoreApplication::translate(DEV_DISCOVERY, DD_NOT_STARTED));
- emit q_ptr->error(lastError);
- return;
- }
-
- discoveredDevices.clear();
- setError(QBluetoothDeviceDiscoveryAgent::NoError);
-
- // Create a local variable - to have a strong referece in a block.
- LEDeviceInquiryObjC *inq = inquiryLE.data();
- dispatch_async(leQueue, ^{
- [inq startWithTimeout:lowEnergySearchTimeout];
- });
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::stop()
-{
- Q_ASSERT_X(isActive(), Q_FUNC_INFO, "called whithout active inquiry");
-
- startPending = false;
- stopPending = true;
-
- dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- Q_ASSERT(leQueue);
-
- setError(QBluetoothDeviceDiscoveryAgent::NoError);
-
- // Create a local variable - to have a strong referece in a block.
- LEDeviceInquiryObjC *inq = inquiryLE.data();
- dispatch_sync(leQueue, ^{
- [inq stop];
- });
- // We consider LE scan to be stopped immediately and
- // do not care about this LEDeviceInquiry object anymore.
- LEinquiryFinished();
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error)
-{
- // At the moment the only error reported by osxbtledeviceinquiry
- // can be 'powered off' error, it happens
- // after the LE scan started (so we have LE support and this is
- // a real PoweredOffError).
- Q_ASSERT_X(error == QBluetoothDeviceDiscoveryAgent::PoweredOffError,
- Q_FUNC_INFO, "unexpected error");
-
- inquiryLE.reset();
-
- startPending = false;
- stopPending = false;
- setError(error);
- emit q_ptr->error(lastError);
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::LEnotSupported()
-{
- inquiryLE.reset();
-
- startPending = false;
- stopPending = false;
- setError(QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError);
- emit q_ptr->error(lastError);
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::LEdeviceFound(const QBluetoothDeviceInfo &newDeviceInfo)
-{
- // Update, append or discard.
- for (int i = 0, e = discoveredDevices.size(); i < e; ++i) {
- if (discoveredDevices[i].deviceUuid() == newDeviceInfo.deviceUuid()) {
- QBluetoothDeviceInfo::Fields updatedFields = QBluetoothDeviceInfo::Field::None;
- if (discoveredDevices[i].rssi() != newDeviceInfo.rssi()) {
- qCDebug(QT_BT_OSX) << "Updating RSSI for" << newDeviceInfo.address()
- << newDeviceInfo.rssi();
- discoveredDevices[i].setRssi(newDeviceInfo.rssi());
- updatedFields.setFlag(QBluetoothDeviceInfo::Field::RSSI);
- }
-
- if (discoveredDevices[i].manufacturerData() != newDeviceInfo.manufacturerData()) {
- qCDebug(QT_BT_OSX) << "Updating manufacturer data for" << newDeviceInfo.address();
- const QVector<quint16> keys = newDeviceInfo.manufacturerIds();
- for (auto key: keys)
- discoveredDevices[i].setManufacturerData(key, newDeviceInfo.manufacturerData(key));
- updatedFields.setFlag(QBluetoothDeviceInfo::Field::ManufacturerData);
- }
-
- if (lowEnergySearchTimeout > 0) {
- if (discoveredDevices[i] != newDeviceInfo) {
- discoveredDevices.replace(i, newDeviceInfo);
- emit q_ptr->deviceDiscovered(newDeviceInfo);
- } else {
- if (!updatedFields.testFlag(QBluetoothDeviceInfo::Field::None))
- emit q_ptr->deviceUpdated(discoveredDevices[i], updatedFields);
- }
-
- return;
- }
-
- discoveredDevices.replace(i, newDeviceInfo);
- emit q_ptr->deviceDiscovered(newDeviceInfo);
-
- if (!updatedFields.testFlag(QBluetoothDeviceInfo::Field::None))
- emit q_ptr->deviceUpdated(discoveredDevices[i], updatedFields);
-
- return;
- }
- }
-
- discoveredDevices.append(newDeviceInfo);
- emit q_ptr->deviceDiscovered(newDeviceInfo);
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::LEinquiryFinished()
-{
- inquiryLE.reset();
-
- if (stopPending && !startPending) {
- stopPending = false;
- emit q_ptr->canceled();
- } else if (startPending) {
- startPending = false;
- stopPending = false;
- // always the same method for start() on iOS
- // classic search not supported
- start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
- } else {
- emit q_ptr->finished();
- }
-}
-
-void QBluetoothDeviceDiscoveryAgentPrivate::setError(QBluetoothDeviceDiscoveryAgent::Error error,
- const QString &text)
-{
- lastError = error;
-
- if (text.length() > 0) {
- errorString = text;
- } else {
- switch (lastError) {
- case QBluetoothDeviceDiscoveryAgent::NoError:
- errorString = QString();
- break;
- case QBluetoothDeviceDiscoveryAgent::PoweredOffError:
- errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_POWERED_OFF);
- break;
- case QBluetoothDeviceDiscoveryAgent::InvalidBluetoothAdapterError:
- errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_INVALID_ADAPTER);
- break;
- case QBluetoothDeviceDiscoveryAgent::InputOutputError:
- errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_IO);
- break;
- case QBluetoothDeviceDiscoveryAgent::UnsupportedPlatformError:
- errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_NOTSUPPORTED);
- break;
- case QBluetoothDeviceDiscoveryAgent::UnknownError:
- default:
- errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_UNKNOWN_ERROR);
- }
- }
-}
-
-QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent(QObject *parent) :
- QObject(parent),
- d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate(QBluetoothAddress(), this))
-{
-}
-
-QBluetoothDeviceDiscoveryAgent::QBluetoothDeviceDiscoveryAgent(
- const QBluetoothAddress &deviceAdapter, QObject *parent) :
- QObject(parent),
- d_ptr(new QBluetoothDeviceDiscoveryAgentPrivate(deviceAdapter, this))
-{
- if (!deviceAdapter.isNull()) {
- qCWarning(QT_BT_OSX) << "local device address is "
- "not available, provided address is ignored";
- d_ptr->setError(InvalidBluetoothAdapterError);
- }
-}
-
-QBluetoothDeviceDiscoveryAgent::~QBluetoothDeviceDiscoveryAgent()
-{
- delete d_ptr;
-}
-
-QBluetoothDeviceDiscoveryAgent::InquiryType QBluetoothDeviceDiscoveryAgent::inquiryType() const
-{
- return d_ptr->inquiryType;
-}
-
-void QBluetoothDeviceDiscoveryAgent::setInquiryType(QBluetoothDeviceDiscoveryAgent::InquiryType type)
-{
- d_ptr->inquiryType = type;
-}
-
-QList<QBluetoothDeviceInfo> QBluetoothDeviceDiscoveryAgent::discoveredDevices() const
-{
- return d_ptr->discoveredDevices;
-}
-
-QBluetoothDeviceDiscoveryAgent::DiscoveryMethods QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods()
-{
- return LowEnergyMethod;
-}
-
-void QBluetoothDeviceDiscoveryAgent::start()
-{
- if (d_ptr->lastError != InvalidBluetoothAdapterError) {
- if (!isActive())
- d_ptr->start(supportedDiscoveryMethods());
- else
- qCDebug(QT_BT_OSX) << "already started";
- }
-}
-
-void QBluetoothDeviceDiscoveryAgent::start(DiscoveryMethods methods)
-{
- if (methods == NoMethod)
- return;
-
- DiscoveryMethods supported =
- QBluetoothDeviceDiscoveryAgent::supportedDiscoveryMethods();
-
- if (!((supported & methods) == methods)) {
- d_ptr->lastError = UnsupportedDiscoveryMethod;
- d_ptr->errorString = QBluetoothDeviceDiscoveryAgent::tr("One or more device discovery methods "
- "are not supported on this platform");
- emit error(d_ptr->lastError);
- return;
- }
-
- if (!isActive() && d_ptr->lastError != InvalidBluetoothAdapterError)
- d_ptr->start(methods);
-}
-
-void QBluetoothDeviceDiscoveryAgent::stop()
-{
- if (isActive() && d_ptr->lastError != InvalidBluetoothAdapterError)
- d_ptr->stop();
-}
-
-bool QBluetoothDeviceDiscoveryAgent::isActive() const
-{
- return d_ptr->isActive();
-}
-
-QBluetoothDeviceDiscoveryAgent::Error QBluetoothDeviceDiscoveryAgent::error() const
-{
- return d_ptr->lastError;
-}
-
-QString QBluetoothDeviceDiscoveryAgent::errorString() const
-{
- return d_ptr->errorString;
-}
-
-int QBluetoothDeviceDiscoveryAgent::lowEnergyDiscoveryTimeout() const
-{
- return d_ptr->lowEnergySearchTimeout;
-}
-
-void QBluetoothDeviceDiscoveryAgent::setLowEnergyDiscoveryTimeout(int timeout)
-{
- // cannot deliberately turn it off
- if (timeout < 0) {
- qCDebug(QT_BT_OSX) << "The Bluetooth Low Energy device discovery timeout cannot be negative.";
- return;
- }
-
- d_ptr->lowEnergySearchTimeout = timeout;
- return;
-}
-
-QT_END_NAMESPACE
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
index 3e76c13d..a59c6a94 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_p.h
@@ -58,6 +58,11 @@
#include <QtCore/QTimer>
#endif
+#ifdef Q_OS_DARWIN
+#include "osx/btdelegates_p.h"
+#include "osx/btraii_p.h"
+#endif // Q_OS_DARWIN
+
#include <QtCore/QVariantMap>
#include <QtBluetooth/QBluetoothAddress>
@@ -93,11 +98,14 @@ class QWinRTBluetoothDeviceDiscoveryWorker;
#endif
class QBluetoothDeviceDiscoveryAgentPrivate
-#if defined(QT_ANDROID_BLUETOOTH) || defined(QT_WINRT_BLUETOOTH)
+#if defined(QT_ANDROID_BLUETOOTH) || defined(QT_WINRT_BLUETOOTH) || defined(Q_OS_DARWIN)
: public QObject
+#if defined(Q_OS_MACOS)
+ , public DarwinBluetooth::DeviceInquiryDelegate
+#endif // Q_OS_MACOS
{
Q_OBJECT
-#else
+#else // BlueZ
{
#endif
Q_DECLARE_PUBLIC(QBluetoothDeviceDiscoveryAgent)
@@ -180,6 +188,57 @@ private:
QTimer *leScanTimer;
#endif
+#ifdef Q_OS_DARWIN
+
+ void startLE();
+
+#ifdef Q_OS_MACOS
+
+ void startClassic();
+
+ // Classic (IOBluetooth) inquiry delegate's methods:
+ void inquiryFinished() override;
+ void error(IOReturn error) override;
+ void classicDeviceFound(void *device) override;
+ // Classic (IOBluetooth) errors:
+ void setError(IOReturn error, const QString &text = QString());
+
+#endif // Q_OS_MACOS
+
+ // LE scan delegates (CoreBluetooth, all Darwin OSes):
+ void LEinquiryFinished();
+ void LEinquiryError(QBluetoothDeviceDiscoveryAgent::Error error);
+ void LEnotSupported();
+
+ // LE errors:
+ void setError(QBluetoothDeviceDiscoveryAgent::Error,
+ const QString &text = QString());
+
+ // Both LE and Classic devices go there:
+ void deviceFound(const QBluetoothDeviceInfo &newDeviceInfo);
+
+ enum AgentState {
+ NonActive,
+ ClassicScan, // macOS (IOBluetooth) only
+ LEScan
+ } agentState;
+
+ QBluetoothAddress adapterAddress;
+
+ bool startPending;
+ bool stopPending;
+
+#ifdef Q_OS_MACOS
+
+ DarwinBluetooth::ScopedPointer controller;
+ DarwinBluetooth::ScopedPointer inquiry;
+
+#endif // Q_OS_MACOS
+
+ DarwinBluetooth::ScopedPointer inquiryLE;
+
+#endif // Q_OS_DARWIN
+
int lowEnergySearchTimeout;
QBluetoothDeviceDiscoveryAgent::DiscoveryMethods requestedMethods;
QBluetoothDeviceDiscoveryAgent *q_ptr;
diff --git a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
index 177b8082..9d306053 100644
--- a/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
+++ b/src/bluetooth/qbluetoothdevicediscoveryagent_winrt.cpp
@@ -758,13 +758,13 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
boolean isPaired;
hr = pairing->get_IsPaired(&isPaired);
Q_ASSERT_SUCCEEDED(hr);
- QList<QBluetoothUuid> uuids;
+ QVector<QBluetoothUuid> uuids;
const LEAdvertisingInfo adInfo = m_foundLEDevicesMap.value(address);
const qint16 rssi = adInfo.rssi;
// Use the services obtained from the advertisement data if the device is not paired
if (!isPaired) {
- uuids = adInfo.services.toList();
+ uuids = adInfo.services;
} else {
IVectorView <GenericAttributeProfile::GattDeviceService *> *deviceServices;
hr = device->get_GattServices(&deviceServices);
@@ -790,7 +790,7 @@ HRESULT QWinRTBluetoothDeviceDiscoveryWorker::onBluetoothLEDeviceFound(ComPtr<IB
QBluetoothDeviceInfo info(QBluetoothAddress(address), btName, 0);
info.setCoreConfigurations(QBluetoothDeviceInfo::LowEnergyCoreConfiguration);
- info.setServiceUuids(uuids, QBluetoothDeviceInfo::DataIncomplete);
+ info.setServiceUuids(uuids);
info.setRssi(rssi);
for (quint16 key : manufacturerData.keys())
info.setManufacturerData(key, manufacturerData.value(key));
diff --git a/src/bluetooth/qlowenergycharacteristic.h b/src/bluetooth/qlowenergycharacteristic.h
index 9b27d621..d5d783c2 100644
--- a/src/bluetooth/qlowenergycharacteristic.h
+++ b/src/bluetooth/qlowenergycharacteristic.h
@@ -101,7 +101,7 @@ protected:
friend class QLowEnergyControllerPrivateBluez;
friend class QLowEnergyControllerPrivateBluezDBus;
friend class QLowEnergyControllerPrivateCommon;
- friend class QLowEnergyControllerPrivateOSX;
+ friend class QLowEnergyControllerPrivateDarwin;
friend class QLowEnergyControllerPrivateWinRT;
friend class QLowEnergyControllerPrivateWinRTNew;
QLowEnergyCharacteristicPrivate *data = nullptr;
diff --git a/src/bluetooth/qlowenergycontroller.cpp b/src/bluetooth/qlowenergycontroller.cpp
index 8fc044fb..3cf0d920 100644
--- a/src/bluetooth/qlowenergycontroller.cpp
+++ b/src/bluetooth/qlowenergycontroller.cpp
@@ -60,6 +60,8 @@
#if QT_CONFIG(winrt_btle_no_pairing)
#include "qlowenergycontroller_winrt_new_p.h"
#endif
+#elif defined(Q_OS_DARWIN)
+#include "qlowenergycontroller_darwin_p.h"
#else
#include "qlowenergycontroller_p.h"
#endif
@@ -321,6 +323,9 @@ static QLowEnergyControllerPrivate *privateController(QLowEnergyController::Role
qCDebug(QT_BT_WINRT) << "Using pre 15063 low energy controller";
return new QLowEnergyControllerPrivateWinRT();
#endif
+#elif defined(Q_OS_DARWIN)
+ Q_UNUSED(role)
+ return new QLowEnergyControllerPrivateDarwin();
#else
Q_UNUSED(role);
return new QLowEnergyControllerPrivateCommon();
@@ -344,6 +349,9 @@ QLowEnergyController::QLowEnergyController(
QObject *parent)
: QObject(parent)
{
+ // Note: a central created using this ctor is useless
+ // on Darwin - no way to use addresses when connecting.
+
d_ptr = privateController(CentralRole);
Q_D(QLowEnergyController);
@@ -373,11 +381,12 @@ QLowEnergyController::QLowEnergyController(
QObject *parent)
: QObject(parent)
{
- d_ptr = privateController(CentralRole);
+ d_ptr = privateController(CentralRole);
Q_D(QLowEnergyController);
d->q_ptr = this;
d->role = CentralRole;
+ d->deviceUuid = remoteDeviceInfo.deviceUuid();
d->remoteDevice = remoteDeviceInfo.address();
d->localAdapter = QBluetoothLocalDevice().address();
d->addressType = QLowEnergyController::PublicAddress;
@@ -406,6 +415,8 @@ QLowEnergyController::QLowEnergyController(
QObject *parent)
: QObject(parent)
{
+ // Note: a central create using this ctor is useless on
+ // Darwin (CoreBluetooth does not work with addresses).
d_ptr = privateController(CentralRole);
Q_D(QLowEnergyController);
@@ -432,6 +443,29 @@ QLowEnergyController *QLowEnergyController::createCentral(const QBluetoothDevice
return new QLowEnergyController(remoteDevice, parent);
}
+/*!
+ Returns a new instance of this class with \a parent.
+
+ The \a remoteDevice must contain the address of the remote Bluetooth Low
+ Energy device to which this object should attempt to connect later on.
+
+ The connection is established via \a localDevice. If \a localDevice is invalid,
+ the local default device is automatically selected. If \a localDevice specifies
+ a local device that is not a local Bluetooth adapter, \l error() is set to
+ \l InvalidBluetoothAdapterError once \l connectToDevice() is called.
+
+ Note that specifying the local device to be used for the connection is only
+ possible when using BlueZ. All other platforms do not support this feature.
+
+ \since 5.13
+ */
+QLowEnergyController *QLowEnergyController::createCentral(const QBluetoothAddress &remoteDevice,
+ const QBluetoothAddress &localDevice,
+ QObject *parent)
+{
+ return new QLowEnergyController(remoteDevice, localDevice, parent);
+}
+
/*!
Returns a new object of this class that is in the \l PeripheralRole and has the
@@ -511,7 +545,7 @@ QBluetoothAddress QLowEnergyController::remoteAddress() const
*/
QBluetoothUuid QLowEnergyController::remoteDeviceUuid() const
{
- return QBluetoothUuid();
+ return d_ptr->deviceUuid;
}
/*!
diff --git a/src/bluetooth/qlowenergycontroller.h b/src/bluetooth/qlowenergycontroller.h
index 9fe46fe5..5498d4a5 100644
--- a/src/bluetooth/qlowenergycontroller.h
+++ b/src/bluetooth/qlowenergycontroller.h
@@ -93,13 +93,16 @@ public:
explicit QLowEnergyController(const QBluetoothAddress &remoteDevice,
QObject *parent = nullptr); // TODO Qt 6 remove ctor
explicit QLowEnergyController(const QBluetoothDeviceInfo &remoteDevice,
- QObject *parent = nullptr);
+ QObject *parent = nullptr); // TODO Qt 6 make private
explicit QLowEnergyController(const QBluetoothAddress &remoteDevice,
const QBluetoothAddress &localDevice,
QObject *parent = nullptr); // TODO Qt 6 remove ctor
static QLowEnergyController *createCentral(const QBluetoothDeviceInfo &remoteDevice,
QObject *parent = nullptr);
+ static QLowEnergyController *createCentral(const QBluetoothAddress &remoteDevice,
+ const QBluetoothAddress &localDevice,
+ QObject *parent = nullptr);
static QLowEnergyController *createPeripheral(QObject *parent = nullptr);
// TODO: Allow to set connection timeout (disconnect when no data has been exchanged for n seconds).
diff --git a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
index f019d9c2..4e5f3430 100644
--- a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp
@@ -268,9 +268,13 @@ void QLowEnergyControllerPrivateBluezDBus::connectToDeviceHelper()
const QVariantMap &ifaceValues = jt.value();
if (iface == QStringLiteral("org.bluez.Device1")) {
- if (remoteDevice.toString() == ifaceValues.value(QStringLiteral("Address")).toString()) {
- devicePath = it.key().path();
- break;
+ if (remoteDevice.toString() == ifaceValues.value(QStringLiteral("Address")).toString())
+ {
+ const QVariant adapterForCurrentDevice = ifaceValues.value(QStringLiteral("Adapter"));
+ if (qvariant_cast<QDBusObjectPath>(adapterForCurrentDevice).path() == hostAdapterPath) {
+ devicePath = it.key().path();
+ break;
+ }
}
}
}
diff --git a/src/bluetooth/qlowenergycontroller_osx.mm b/src/bluetooth/qlowenergycontroller_darwin.mm
index 8bcdc22e..253956e2 100644
--- a/src/bluetooth/qlowenergycontroller_osx.mm
+++ b/src/bluetooth/qlowenergycontroller_darwin.mm
@@ -38,13 +38,17 @@
**
****************************************************************************/
-#include "osx/osxbtnotifier_p.h"
#include "osx/osxbtutility_p.h"
#include "osx/uistrings_p.h"
+#ifndef Q_OS_TVOS
+#include "osx/osxbtperipheralmanager_p.h"
+#endif // Q_OS_TVOS
+#include "qlowenergycontroller_darwin_p.h"
#include "qlowenergyserviceprivate_p.h"
-#include "qlowenergycontroller_osx_p.h"
+#include "osx/osxbtcentralmanager_p.h"
+
#include "qlowenergyservicedata.h"
#include "qbluetoothlocaldevice.h"
#include "qbluetoothdeviceinfo.h"
@@ -58,30 +62,14 @@
#include <QtCore/qstring.h>
#include <QtCore/qlist.h>
-#define OSX_D_PTR QLowEnergyControllerPrivateOSX *osx_d_ptr = static_cast<QLowEnergyControllerPrivateOSX *>(d_ptr)
-
QT_BEGIN_NAMESPACE
namespace {
-static void registerQLowEnergyControllerMetaType()
-{
- static bool initDone = false;
- if (!initDone) {
- qRegisterMetaType<QLowEnergyController::ControllerState>();
- qRegisterMetaType<QLowEnergyController::Error>();
- qRegisterMetaType<QLowEnergyHandle>("QLowEnergyHandle");
- qRegisterMetaType<QSharedPointer<QLowEnergyServicePrivate> >();
- qRegisterMetaType<QLowEnergyCharacteristic>();
- qRegisterMetaType<QLowEnergyDescriptor>();
- initDone = true;
- }
-}
-
typedef QSharedPointer<QLowEnergyServicePrivate> ServicePrivate;
// Convenience function, can return a smart pointer that 'isNull'.
-ServicePrivate qt_createLEService(QLowEnergyControllerPrivateOSX *controller, CBService *cbService, bool included)
+ServicePrivate qt_createLEService(QLowEnergyControllerPrivateDarwin *controller, CBService *cbService, bool included)
{
Q_ASSERT_X(controller, Q_FUNC_INFO, "invalid controller (null)");
Q_ASSERT_X(cbService, Q_FUNC_INFO, "invalid service (nil)");
@@ -131,110 +119,276 @@ UUIDList qt_servicesUuids(NSArray *services)
return uuids;
}
-}
+} // unnamed namespace
+
+#ifndef Q_OS_TVOS
+using ObjCPeripheralManager = QT_MANGLE_NAMESPACE(OSXBTPeripheralManager);
+#endif // Q_OS_TVOS
+
+using ObjCCentralManager = QT_MANGLE_NAMESPACE(OSXBTCentralManager);
-QLowEnergyControllerPrivateOSX::QLowEnergyControllerPrivateOSX(QLowEnergyController::Role r,
- QLowEnergyController *q,
- const QBluetoothDeviceInfo &deviceInfo)
- : q_ptr(q),
- deviceUuid(deviceInfo.deviceUuid()),
- deviceName(deviceInfo.name()),
- lastError(QLowEnergyController::NoError),
- controllerState(QLowEnergyController::UnconnectedState),
- addressType(QLowEnergyController::PublicAddress)
+QLowEnergyControllerPrivateDarwin::QLowEnergyControllerPrivateDarwin()
{
+ void registerQLowEnergyControllerMetaType();
registerQLowEnergyControllerMetaType();
+ qRegisterMetaType<QLowEnergyHandle>("QLowEnergyHandle");
+ qRegisterMetaType<QSharedPointer<QLowEnergyServicePrivate>>();
+}
- Q_ASSERT_X(q, Q_FUNC_INFO, "invalid q_ptr (null)");
+QLowEnergyControllerPrivateDarwin::~QLowEnergyControllerPrivateDarwin()
+{
+ if (const auto leQueue = OSXBluetooth::qt_LE_queue()) {
+ if (role == QLowEnergyController::CentralRole) {
+ const auto manager = centralManager.getAs<ObjCCentralManager>();
+ dispatch_sync(leQueue, ^{
+ [manager detach];
+ });
+ } else {
+#ifndef Q_OS_TVOS
+ const auto manager = peripheralManager.getAs<ObjCPeripheralManager>();
+ dispatch_sync(leQueue, ^{
+ [manager detach];
+ });
+#endif
+ }
+ }
+}
- using OSXBluetooth::LECBManagerNotifier;
+bool QLowEnergyControllerPrivateDarwin::isValid() const
+{
+#ifdef Q_OS_TVOS
+ return centralManager;
+#else
+ return centralManager || peripheralManager;
+#endif
+}
- role = r;
+void QLowEnergyControllerPrivateDarwin::init()
+{
+ using OSXBluetooth::LECBManagerNotifier;
QScopedPointer<LECBManagerNotifier> notifier(new LECBManagerNotifier);
if (role == QLowEnergyController::PeripheralRole) {
#ifndef Q_OS_TVOS
- peripheralManager.reset([[ObjCPeripheralManager alloc] initWith:notifier.data()]);
+ peripheralManager.reset([[ObjCPeripheralManager alloc] initWith:notifier.data()],
+ DarwinBluetooth::RetainPolicy::noInitialRetain);
if (!peripheralManager) {
- qCWarning(QT_BT_OSX) << "failed to initialize peripheral manager";
+ qCWarning(QT_BT_OSX) << "failed to create a peripheral manager";
return;
}
#else
- qCWarning(QT_BT_OSX) << "peripheral role is not supported on your platform";
+ qCWarning(QT_BT_OSX) << "the peripheral role is not supported on your platform";
return;
-#endif
+#endif // Q_OS_TVOS
} else {
- centralManager.reset([[ObjCCentralManager alloc] initWith:notifier.data()]);
+ centralManager.reset([[ObjCCentralManager alloc] initWith:notifier.data()],
+ DarwinBluetooth::RetainPolicy::noInitialRetain);
if (!centralManager) {
- qCWarning(QT_BT_OSX) << "failed to initialize central manager";
+ qCWarning(QT_BT_OSX) << "failed to initialize a central manager";
return;
}
}
- if (!connectSlots(notifier.data())) {
+ if (!connectSlots(notifier.data()))
qCWarning(QT_BT_OSX) << "failed to connect to notifier's signal(s)";
- }
+
// Ownership was taken by central manager.
notifier.take();
}
-QLowEnergyControllerPrivateOSX::~QLowEnergyControllerPrivateOSX()
+void QLowEnergyControllerPrivateDarwin::connectToDevice()
{
- if (const auto leQueue = OSXBluetooth::qt_LE_queue()) {
- if (role == QLowEnergyController::CentralRole) {
- const auto manager = centralManager.data();
- dispatch_sync(leQueue, ^{
- [manager detach];
+ Q_ASSERT_X(state == QLowEnergyController::UnconnectedState,
+ Q_FUNC_INFO, "invalid state");
+
+ if (!isValid()) {
+ // init() had failed for was never called.
+ return _q_CBManagerError(QLowEnergyController::UnknownError);
+ }
+
+ if (deviceUuid.isNull()) {
+ // Wrong constructor was used or invalid UUID was provided.
+ return _q_CBManagerError(QLowEnergyController::UnknownRemoteDeviceError);
+ }
+
+ // The logic enforcing the role is in the public class.
+ Q_ASSERT_X(role != QLowEnergyController::PeripheralRole,
+ Q_FUNC_INFO, "invalid role (peripheral)");
+
+ dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
+ if (!leQueue) {
+ qCWarning(QT_BT_OSX) << "no LE queue found";
+ setErrorDescription(QLowEnergyController::UnknownError);
+ return;
+ }
+
+ setErrorDescription(QLowEnergyController::NoError);
+ setState(QLowEnergyController::ConnectingState);
+
+ const QBluetoothUuid deviceUuidCopy(deviceUuid);
+ ObjCCentralManager *manager = centralManager.getAs<ObjCCentralManager>();
+ dispatch_async(leQueue, ^{
+ [manager connectToDevice:deviceUuidCopy];
+ });
+}
+
+void QLowEnergyControllerPrivateDarwin::disconnectFromDevice()
+{
+ if (role == QLowEnergyController::PeripheralRole) {
+ // CoreBluetooth API intentionally does not provide any way of closing
+ // a connection. All we can do here is to stop the advertisement.
+ stopAdvertising();
+ return;
+ }
+
+ if (isValid()) {
+ const auto oldState = state;
+
+ if (dispatch_queue_t leQueue = OSXBluetooth::qt_LE_queue()) {
+ setState(QLowEnergyController::ClosingState);
+ invalidateServices();
+
+ auto manager = centralManager.getAs<ObjCCentralManager>();
+ dispatch_async(leQueue, ^{
+ [manager disconnectFromDevice];
});
+
+ if (oldState == QLowEnergyController::ConnectingState) {
+ // With a pending connect attempt there is no
+ // guarantee we'll ever have didDisconnect callback,
+ // set the state here and now to make sure we still
+ // can connect.
+ setState(QLowEnergyController::UnconnectedState);
+ }
} else {
-#ifndef Q_OS_TVOS
- const auto manager = peripheralManager.data();
- dispatch_sync(leQueue, ^{
- [manager detach];
- });
-#endif
+ qCCritical(QT_BT_OSX) << "qt LE queue is nil, "
+ "can not dispatch 'disconnect'";
}
}
}
-bool QLowEnergyControllerPrivateOSX::isValid() const
+void QLowEnergyControllerPrivateDarwin::discoverServices()
+{
+ Q_ASSERT_X(state != QLowEnergyController::UnconnectedState,
+ Q_FUNC_INFO, "not connected to peripheral");
+ Q_ASSERT_X(role != QLowEnergyController::PeripheralRole,
+ Q_FUNC_INFO, "invalid role (peripheral)");
+
+ dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
+ Q_ASSERT_X(leQueue, Q_FUNC_INFO, "LE queue not found");
+
+ setState(QLowEnergyController::DiscoveringState);
+
+ ObjCCentralManager *manager = centralManager.getAs<ObjCCentralManager>();
+ dispatch_async(leQueue, ^{
+ [manager discoverServices];
+ });
+}
+
+void QLowEnergyControllerPrivateDarwin::discoverServiceDetails(const QBluetoothUuid &serviceUuid)
+{
+ if (state != QLowEnergyController::DiscoveredState) {
+ qCWarning(QT_BT_OSX) << "can not discover service details in the current state, "
+ "QLowEnergyController::DiscoveredState is expected";
+ return;
+ }
+
+ if (!serviceList.contains(serviceUuid)) {
+ qCWarning(QT_BT_OSX) << "unknown service: " << serviceUuid;
+ return;
+ }
+
+ dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
+ Q_ASSERT(leQueue);
+
+ ServicePrivate qtService(serviceList.value(serviceUuid));
+ qtService->setState(QLowEnergyService::DiscoveringServices);
+ // Copy objects ...
+ ObjCCentralManager *manager = centralManager.getAs<ObjCCentralManager>();
+ const QBluetoothUuid serviceUuidCopy(serviceUuid);
+ dispatch_async(leQueue, ^{
+ [manager discoverServiceDetails:serviceUuidCopy];
+ });
+}
+
+void QLowEnergyControllerPrivateDarwin::requestConnectionUpdate(const QLowEnergyConnectionParameters &params)
+{
+ Q_UNUSED(params);
+ // TODO: implement this, if possible.
+ qCWarning(QT_BT_OSX) << "Connection update not implemented on your platform";
+}
+
+void QLowEnergyControllerPrivateDarwin::addToGenericAttributeList(const QLowEnergyServiceData &service,
+ QLowEnergyHandle startHandle)
+{
+ Q_UNUSED(service);
+ Q_UNUSED(startHandle);
+ // TODO: check why I don't need this (apparently it is used in addServiceHelper
+ // of the base class).
+}
+
+QLowEnergyService * QLowEnergyControllerPrivateDarwin::addServiceHelper(const QLowEnergyServiceData &service)
{
+ // Three checks below should be removed, they are done in the q_ptr's class.
#ifdef Q_OS_TVOS
- return centralManager;
+ Q_UNUSED(service);
+ qCDebug(QT_BT_OSX, "peripheral role is not supported on tvOS");
#else
- return centralManager || peripheralManager;
-#endif
+ if (role != QLowEnergyController::PeripheralRole) {
+ qCWarning(QT_BT_OSX) << "not in peripheral role";
+ return nullptr;
+ }
+
+ if (state != QLowEnergyController::UnconnectedState) {
+ qCWarning(QT_BT_OSX) << "invalid state";
+ return nullptr;
+ }
+
+ if (!service.isValid()) {
+ qCWarning(QT_BT_OSX) << "invalid service";
+ return nullptr;
+ }
+
+ for (auto includedService : service.includedServices())
+ includedService->d_ptr->type |= QLowEnergyService::IncludedService;
+
+ const auto manager = peripheralManager.getAs<ObjCPeripheralManager>();
+ Q_ASSERT(manager);
+ if (const auto servicePrivate = [manager addService:service]) {
+ servicePrivate->setController(this);
+ servicePrivate->state = QLowEnergyService::LocalService;
+ localServices.insert(servicePrivate->uuid, servicePrivate);
+ return new QLowEnergyService(servicePrivate);
+ }
+#endif // Q_OS_TVOS
+ return nullptr;
}
-void QLowEnergyControllerPrivateOSX::_q_connected()
+void QLowEnergyControllerPrivateDarwin::_q_connected()
{
- controllerState = QLowEnergyController::ConnectedState;
-
- emit q_ptr->stateChanged(QLowEnergyController::ConnectedState);
+ setState(QLowEnergyController::ConnectedState);
emit q_ptr->connected();
}
-void QLowEnergyControllerPrivateOSX::_q_disconnected()
+void QLowEnergyControllerPrivateDarwin::_q_disconnected()
{
- controllerState = QLowEnergyController::UnconnectedState;
-
if (role == QLowEnergyController::CentralRole)
invalidateServices();
- emit q_ptr->stateChanged(QLowEnergyController::UnconnectedState);
+ setState(QLowEnergyController::UnconnectedState);
emit q_ptr->disconnected();
}
-void QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished()
+void QLowEnergyControllerPrivateDarwin::_q_serviceDiscoveryFinished()
{
- Q_ASSERT_X(controllerState == QLowEnergyController::DiscoveringState,
+ Q_ASSERT_X(state == QLowEnergyController::DiscoveringState,
Q_FUNC_INFO, "invalid state");
using namespace OSXBluetooth;
QT_BT_MAC_AUTORELEASEPOOL;
- NSArray *const services = [centralManager.data() peripheral].services;
+ NSArray *const services = [centralManager.getAs<ObjCCentralManager>() peripheral].services;
// Now we have to traverse the discovered services tree.
// Essentially it's an iterative version of more complicated code from the
// OSXBTCentralManager's code.
@@ -249,13 +403,13 @@ void QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished()
const ServicePrivate newService(qt_createLEService(this, cbService, false));
if (!newService.data())
continue;
- if (discoveredServices.contains(newService->uuid)) {
+ if (serviceList.contains(newService->uuid)) {
// It's a bit stupid we first created it ...
qCDebug(QT_BT_OSX) << "discovered service with a duplicated UUID"
<< newService->uuid;
continue;
}
- discoveredServices.insert(newService->uuid, newService);
+ serviceList.insert(newService->uuid, newService);
discoveredCBServices.insert(newService->uuid, cbService);
}
@@ -273,8 +427,8 @@ void QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished()
}
const QBluetoothUuid uuid(qt_uuid(s.UUID));
- if (discoveredServices.contains(uuid) && discoveredCBServices.value(uuid) == s) {
- ServicePrivate qtService(discoveredServices.value(uuid));
+ if (serviceList.contains(uuid) && discoveredCBServices.value(uuid) == s) {
+ ServicePrivate qtService(serviceList.value(uuid));
// Add included UUIDs:
qtService->includedServices.append(qt_servicesUuids(s.includedServices));
}// Else - we ignored this CBService object.
@@ -286,15 +440,15 @@ void QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished()
for (NSUInteger i = 0, e = [toVisitNext count]; i < e; ++i) {
CBService *const s = [toVisitNext objectAtIndex:i];
const QBluetoothUuid uuid(qt_uuid(s.UUID));
- if (discoveredServices.contains(uuid)) {
+ if (serviceList.contains(uuid)) {
if (discoveredCBServices.value(uuid) == s) {
- ServicePrivate qtService(discoveredServices.value(uuid));
+ ServicePrivate qtService(serviceList.value(uuid));
qtService->type |= QLowEnergyService::IncludedService;
} // Else this is the duplicate we ignored already.
} else {
// Oh, we do not even have it yet???
ServicePrivate newService(qt_createLEService(this, s, true));
- discoveredServices.insert(newService->uuid, newService);
+ serviceList.insert(newService->uuid, newService);
discoveredCBServices.insert(newService->uuid, s);
}
}
@@ -306,31 +460,26 @@ void QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished()
qCDebug(QT_BT_OSX) << "no services found";
}
- for (ServiceMap::const_iterator it = discoveredServices.constBegin(); it != discoveredServices.constEnd(); ++it) {
- const QBluetoothUuid &uuid = it.key();
- QMetaObject::invokeMethod(q_ptr, "serviceDiscovered", Qt::QueuedConnection,
- Q_ARG(QBluetoothUuid, uuid));
- }
+ for (ServiceMap::const_iterator it = serviceList.constBegin(); it != serviceList.constEnd(); ++it)
+ emit q_ptr->serviceDiscovered(it.key());
- controllerState = QLowEnergyController::DiscoveredState;
- QMetaObject::invokeMethod(q_ptr, "stateChanged", Qt::QueuedConnection,
- Q_ARG(QLowEnergyController::ControllerState, controllerState));
- QMetaObject::invokeMethod(q_ptr, "discoveryFinished", Qt::QueuedConnection);
+ setState(QLowEnergyController::DiscoveredState);
+ emit q_ptr->discoveryFinished();
}
-void QLowEnergyControllerPrivateOSX::_q_serviceDetailsDiscoveryFinished(QSharedPointer<QLowEnergyServicePrivate> service)
+void QLowEnergyControllerPrivateDarwin::_q_serviceDetailsDiscoveryFinished(QSharedPointer<QLowEnergyServicePrivate> service)
{
QT_BT_MAC_AUTORELEASEPOOL;
Q_ASSERT(service);
- if (!discoveredServices.contains(service->uuid)) {
+ if (!serviceList.contains(service->uuid)) {
qCDebug(QT_BT_OSX) << "unknown service uuid:"
<< service->uuid;
return;
}
- ServicePrivate qtService(discoveredServices.value(service->uuid));
+ ServicePrivate qtService(serviceList.value(service->uuid));
// Assert on handles?
qtService->startHandle = service->startHandle;
qtService->endHandle = service->endHandle;
@@ -339,23 +488,23 @@ void QLowEnergyControllerPrivateOSX::_q_serviceDetailsDiscoveryFinished(QSharedP
qtService->setState(QLowEnergyService::ServiceDiscovered);
}
-void QLowEnergyControllerPrivateOSX::_q_servicesWereModified()
+void QLowEnergyControllerPrivateDarwin::_q_servicesWereModified()
{
- if (!(controllerState == QLowEnergyController::DiscoveringState
- || controllerState == QLowEnergyController::DiscoveredState)) {
+ if (!(state == QLowEnergyController::DiscoveringState
+ || state == QLowEnergyController::DiscoveredState)) {
qCWarning(QT_BT_OSX) << "services were modified while controller is not in Discovered/Discovering state";
return;
}
- if (controllerState == QLowEnergyController::DiscoveredState)
+ if (state == QLowEnergyController::DiscoveredState)
invalidateServices();
- controllerState = QLowEnergyController::ConnectedState;
+ setState(QLowEnergyController::ConnectedState);
q_ptr->discoverServices();
}
-void QLowEnergyControllerPrivateOSX::_q_characteristicRead(QLowEnergyHandle charHandle,
- const QByteArray &value)
+void QLowEnergyControllerPrivateDarwin::_q_characteristicRead(QLowEnergyHandle charHandle,
+ const QByteArray &value)
{
Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle(0)");
@@ -375,8 +524,8 @@ void QLowEnergyControllerPrivateOSX::_q_characteristicRead(QLowEnergyHandle char
emit service->characteristicRead(characteristic, value);
}
-void QLowEnergyControllerPrivateOSX::_q_characteristicWritten(QLowEnergyHandle charHandle,
- const QByteArray &value)
+void QLowEnergyControllerPrivateDarwin::_q_characteristicWritten(QLowEnergyHandle charHandle,
+ const QByteArray &value)
{
Q_ASSERT_X(charHandle, Q_FUNC_INFO, "invalid characteristic handle(0)");
@@ -399,8 +548,8 @@ void QLowEnergyControllerPrivateOSX::_q_characteristicWritten(QLowEnergyHandle c
emit service->characteristicWritten(characteristic, value);
}
-void QLowEnergyControllerPrivateOSX::_q_characteristicUpdated(QLowEnergyHandle charHandle,
- const QByteArray &value)
+void QLowEnergyControllerPrivateDarwin::_q_characteristicUpdated(QLowEnergyHandle charHandle,
+ const QByteArray &value)
{
// TODO: write/update notifications are quite similar (except asserts/warnings messages
// and different signals emitted). Merge them into one function?
@@ -428,8 +577,8 @@ void QLowEnergyControllerPrivateOSX::_q_characteristicUpdated(QLowEnergyHandle c
emit service->characteristicChanged(characteristic, value);
}
-void QLowEnergyControllerPrivateOSX::_q_descriptorRead(QLowEnergyHandle dHandle,
- const QByteArray &value)
+void QLowEnergyControllerPrivateDarwin::_q_descriptorRead(QLowEnergyHandle dHandle,
+ const QByteArray &value)
{
Q_ASSERT_X(dHandle, Q_FUNC_INFO, "invalid descriptor handle (0)");
@@ -444,8 +593,8 @@ void QLowEnergyControllerPrivateOSX::_q_descriptorRead(QLowEnergyHandle dHandle,
emit service->descriptorRead(qtDescriptor, value);
}
-void QLowEnergyControllerPrivateOSX::_q_descriptorWritten(QLowEnergyHandle dHandle,
- const QByteArray &value)
+void QLowEnergyControllerPrivateDarwin::_q_descriptorWritten(QLowEnergyHandle dHandle,
+ const QByteArray &value)
{
Q_ASSERT_X(dHandle, Q_FUNC_INFO, "invalid descriptor handle (0)");
@@ -461,8 +610,8 @@ void QLowEnergyControllerPrivateOSX::_q_descriptorWritten(QLowEnergyHandle dHand
emit service->descriptorWritten(qtDescriptor, value);
}
-void QLowEnergyControllerPrivateOSX::_q_notificationEnabled(QLowEnergyHandle charHandle,
- bool enabled)
+void QLowEnergyControllerPrivateDarwin::_q_notificationEnabled(QLowEnergyHandle charHandle,
+ bool enabled)
{
// CoreBluetooth in peripheral role does not allow mutable descriptors,
// in central we can only call setNotification:enabled/disabled.
@@ -504,7 +653,7 @@ void QLowEnergyControllerPrivateOSX::_q_notificationEnabled(QLowEnergyHandle cha
}
}
-void QLowEnergyControllerPrivateOSX::_q_LEnotSupported()
+void QLowEnergyControllerPrivateDarwin::_q_LEnotSupported()
{
// Report as an error. But this should not be possible
// actually: before connecting to any device, we have
@@ -512,32 +661,30 @@ void QLowEnergyControllerPrivateOSX::_q_LEnotSupported()
// be supported.
}
-void QLowEnergyControllerPrivateOSX::_q_CBManagerError(QLowEnergyController::Error errorCode)
+void QLowEnergyControllerPrivateDarwin::_q_CBManagerError(QLowEnergyController::Error errorCode)
{
- // Errors reported during connect and general errors.
-
- setErrorDescription(errorCode);
- emit q_ptr->error(lastError);
-
- if (controllerState == QLowEnergyController::ConnectingState) {
- controllerState = QLowEnergyController::UnconnectedState;
- emit q_ptr->stateChanged(controllerState);
- } else if (controllerState == QLowEnergyController::DiscoveringState) {
- controllerState = QLowEnergyController::ConnectedState;
- emit q_ptr->stateChanged(controllerState);
- } // In any other case we stay in Discovered, it's
- // a service/characteristic - related error.
+ // This function handles errors reported while connecting to a remote device
+ // and also other errors in general.
+ setError(errorCode);
+
+ if (state == QLowEnergyController::ConnectingState)
+ setState(QLowEnergyController::UnconnectedState);
+ else if (state == QLowEnergyController::DiscoveringState)
+ setState(QLowEnergyController::ConnectedState);
+
+ // In any other case we stay in Discovered, it's
+ // a service/characteristic - related error.
}
-void QLowEnergyControllerPrivateOSX::_q_CBManagerError(const QBluetoothUuid &serviceUuid,
- QLowEnergyController::Error errorCode)
+void QLowEnergyControllerPrivateDarwin::_q_CBManagerError(const QBluetoothUuid &serviceUuid,
+ QLowEnergyController::Error errorCode)
{
// Errors reported while discovering service details etc.
Q_UNUSED(errorCode) // TODO: setError?
// We failed to discover any characteristics/descriptors.
- if (discoveredServices.contains(serviceUuid)) {
- ServicePrivate qtService(discoveredServices.value(serviceUuid));
+ if (serviceList.contains(serviceUuid)) {
+ ServicePrivate qtService(serviceList.value(serviceUuid));
qtService->setState(QLowEnergyService::InvalidService);
} else {
qCDebug(QT_BT_OSX) << "error reported for unknown service"
@@ -545,109 +692,24 @@ void QLowEnergyControllerPrivateOSX::_q_CBManagerError(const QBluetoothUuid &ser
}
}
-void QLowEnergyControllerPrivateOSX::_q_CBManagerError(const QBluetoothUuid &serviceUuid,
- QLowEnergyService::ServiceError errorCode)
+void QLowEnergyControllerPrivateDarwin::_q_CBManagerError(const QBluetoothUuid &serviceUuid,
+ QLowEnergyService::ServiceError errorCode)
{
- if (!discoveredServices.contains(serviceUuid)) {
+ if (!serviceList.contains(serviceUuid)) {
qCDebug(QT_BT_OSX) << "unknown service uuid:"
<< serviceUuid;
return;
}
- ServicePrivate service(discoveredServices.value(serviceUuid));
+ ServicePrivate service(serviceList.value(serviceUuid));
service->setError(errorCode);
}
-void QLowEnergyControllerPrivateOSX::connectToDevice()
-{
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid private controller");
- Q_ASSERT_X(controllerState == QLowEnergyController::UnconnectedState,
- Q_FUNC_INFO, "invalid state");
- Q_ASSERT_X(!deviceUuid.isNull(), Q_FUNC_INFO,
- "invalid private controller (no device uuid)");
- Q_ASSERT_X(role != QLowEnergyController::PeripheralRole,
- Q_FUNC_INFO, "invalid role (peripheral)");
-
- dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- setErrorDescription(QLowEnergyController::UnknownError);
- return;
- }
-
- setErrorDescription(QLowEnergyController::NoError);
- controllerState = QLowEnergyController::ConnectingState;
-
- const QBluetoothUuid deviceUuidCopy(deviceUuid);
- ObjCCentralManager *manager = centralManager.data();
- dispatch_async(leQueue, ^{
- [manager connectToDevice:deviceUuidCopy];
- });
-}
-
-void QLowEnergyControllerPrivateOSX::discoverServices()
-{
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid private controller");
- Q_ASSERT_X(controllerState != QLowEnergyController::UnconnectedState,
- Q_FUNC_INFO, "not connected to peripheral");
- Q_ASSERT_X(role != QLowEnergyController::PeripheralRole,
- Q_FUNC_INFO, "invalid role (peripheral)");
-
- dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- setErrorDescription(QLowEnergyController::UnknownError);
- return;
- }
-
- controllerState = QLowEnergyController::DiscoveringState;
- emit q_ptr->stateChanged(QLowEnergyController::DiscoveringState);
-
- ObjCCentralManager *manager = centralManager.data();
- dispatch_async(leQueue, ^{
- [manager discoverServices];
- });
-}
-
-void QLowEnergyControllerPrivateOSX::discoverServiceDetails(const QBluetoothUuid &serviceUuid)
-{
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid private controller");
-
- if (controllerState != QLowEnergyController::DiscoveredState) {
- // This will also exclude peripheral role, since controller
- // can never be in discovered state ...
- qCWarning(QT_BT_OSX) << "can not discover service details in the current state, "
- "QLowEnergyController::DiscoveredState is expected";
- return;
- }
-
- if (!discoveredServices.contains(serviceUuid)) {
- qCWarning(QT_BT_OSX) << "unknown service: " << serviceUuid;
- return;
- }
-
- dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- return;
- }
-
- ServicePrivate qtService(discoveredServices.value(serviceUuid));
- qtService->setState(QLowEnergyService::DiscoveringServices);
- // Copy objects ...
- ObjCCentralManager *manager = centralManager.data();
- const QBluetoothUuid serviceUuidCopy(serviceUuid);
- dispatch_async(leQueue, ^{
- [manager discoverServiceDetails:serviceUuidCopy];
- });
-}
-
-void QLowEnergyControllerPrivateOSX::setNotifyValue(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle charHandle,
- const QByteArray &newValue)
+void QLowEnergyControllerPrivateDarwin::setNotifyValue(QSharedPointer<QLowEnergyServicePrivate> service,
+ QLowEnergyHandle charHandle,
+ const QByteArray &newValue)
{
Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)");
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid controller");
if (role == QLowEnergyController::PeripheralRole) {
qCWarning(QT_BT_OSX) << "invalid role (peripheral)";
@@ -666,7 +728,7 @@ void QLowEnergyControllerPrivateOSX::setNotifyValue(QSharedPointer<QLowEnergySer
return;
}
- if (!discoveredServices.contains(service->uuid)) {
+ if (!serviceList.contains(service->uuid)) {
qCWarning(QT_BT_OSX) << "no service with uuid:" << service->uuid << "found";
return;
}
@@ -678,11 +740,9 @@ void QLowEnergyControllerPrivateOSX::setNotifyValue(QSharedPointer<QLowEnergySer
}
dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- return;
- }
- ObjCCentralManager *manager = centralManager.data();
+ Q_ASSERT_X(leQueue, Q_FUNC_INFO, "no LE queue found");
+
+ ObjCCentralManager *manager = centralManager.getAs<ObjCCentralManager>();
const QBluetoothUuid serviceUuid(service->uuid);
const QByteArray newValueCopy(newValue);
dispatch_async(leQueue, ^{
@@ -692,18 +752,17 @@ void QLowEnergyControllerPrivateOSX::setNotifyValue(QSharedPointer<QLowEnergySer
});
}
-void QLowEnergyControllerPrivateOSX::readCharacteristic(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle charHandle)
+void QLowEnergyControllerPrivateDarwin::readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle)
{
Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)");
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid controller");
if (role == QLowEnergyController::PeripheralRole) {
qCWarning(QT_BT_OSX) << "invalid role (peripheral)";
return;
}
- if (!discoveredServices.contains(service->uuid)) {
+ if (!serviceList.contains(service->uuid)) {
qCWarning(QT_BT_OSX) << "no service with uuid:"
<< service->uuid << "found";
return;
@@ -716,29 +775,26 @@ void QLowEnergyControllerPrivateOSX::readCharacteristic(QSharedPointer<QLowEnerg
}
dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- return;
- }
+ Q_ASSERT_X(leQueue, Q_FUNC_INFO, "no LE queue found");
+
// Attention! We have to copy UUID.
- ObjCCentralManager *manager = centralManager.data();
+ ObjCCentralManager *manager = centralManager.getAs<ObjCCentralManager>();
const QBluetoothUuid serviceUuid(service->uuid);
dispatch_async(leQueue, ^{
[manager readCharacteristic:charHandle onService:serviceUuid];
});
}
-void QLowEnergyControllerPrivateOSX::writeCharacteristic(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle charHandle, const QByteArray &newValue,
- QLowEnergyService::WriteMode mode)
+void QLowEnergyControllerPrivateDarwin::writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle, const QByteArray &newValue,
+ QLowEnergyService::WriteMode mode)
{
Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)");
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid controller");
// We can work only with services found on a given peripheral
// (== created by the given LE controller).
- if (!discoveredServices.contains(service->uuid)) {
+ if (!serviceList.contains(service->uuid) && !localServices.contains(service->uuid)) {
qCWarning(QT_BT_OSX) << "no service with uuid:"
<< service->uuid << " found";
return;
@@ -751,15 +807,12 @@ void QLowEnergyControllerPrivateOSX::writeCharacteristic(QSharedPointer<QLowEner
}
dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- return;
- }
+ Q_ASSERT_X(leQueue, Q_FUNC_INFO, "no LE queue found");
// Attention! We have to copy objects!
const QByteArray newValueCopy(newValue);
if (role == QLowEnergyController::CentralRole) {
const QBluetoothUuid serviceUuid(service->uuid);
- const auto manager = centralManager.data();
+ const auto manager = centralManager.getAs<ObjCCentralManager>();
dispatch_async(leQueue, ^{
[manager write:newValueCopy
charHandle:charHandle
@@ -768,7 +821,7 @@ void QLowEnergyControllerPrivateOSX::writeCharacteristic(QSharedPointer<QLowEner
});
} else {
#ifndef Q_OS_TVOS
- const auto manager = peripheralManager.data();
+ const auto manager = peripheralManager.getAs<ObjCPeripheralManager>();
dispatch_async(leQueue, ^{
[manager write:newValueCopy charHandle:charHandle];
});
@@ -778,9 +831,9 @@ void QLowEnergyControllerPrivateOSX::writeCharacteristic(QSharedPointer<QLowEner
}
}
-quint16 QLowEnergyControllerPrivateOSX::updateValueOfCharacteristic(QLowEnergyHandle charHandle,
- const QByteArray &value,
- bool appendValue)
+quint16 QLowEnergyControllerPrivateDarwin::updateValueOfCharacteristic(QLowEnergyHandle charHandle,
+ const QByteArray &value,
+ bool appendValue)
{
QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);
if (!service.isNull()) {
@@ -799,18 +852,20 @@ quint16 QLowEnergyControllerPrivateOSX::updateValueOfCharacteristic(QLowEnergyHa
return 0;
}
-void QLowEnergyControllerPrivateOSX::readDescriptor(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle descriptorHandle)
+void QLowEnergyControllerPrivateDarwin::readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle)
{
+ Q_UNUSED(charHandle) // Hehe, yes!
+
Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)");
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid controller");
if (role == QLowEnergyController::PeripheralRole) {
qCWarning(QT_BT_OSX) << "invalid role (peripheral)";
return;
}
- if (!discoveredServices.contains(service->uuid)) {
+ if (!serviceList.contains(service->uuid)) {
qCWarning(QT_BT_OSX) << "no service with uuid:"
<< service->uuid << "found";
return;
@@ -823,19 +878,21 @@ void QLowEnergyControllerPrivateOSX::readDescriptor(QSharedPointer<QLowEnergySer
}
// Attention! Copy objects!
const QBluetoothUuid serviceUuid(service->uuid);
- ObjCCentralManager * const manager = centralManager.data();
+ ObjCCentralManager * const manager = centralManager.getAs<ObjCCentralManager>();
dispatch_async(leQueue, ^{
[manager readDescriptor:descriptorHandle
onService:serviceUuid];
});
}
-void QLowEnergyControllerPrivateOSX::writeDescriptor(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle descriptorHandle,
- const QByteArray &newValue)
+void QLowEnergyControllerPrivateDarwin::writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle,
+ const QByteArray &newValue)
{
+ Q_UNUSED(charHandle)
+
Q_ASSERT_X(!service.isNull(), Q_FUNC_INFO, "invalid service (null)");
- Q_ASSERT_X(isValid(), Q_FUNC_INFO, "invalid controller");
if (role == QLowEnergyController::PeripheralRole) {
qCWarning(QT_BT_OSX) << "invalid role (peripheral)";
@@ -845,20 +902,17 @@ void QLowEnergyControllerPrivateOSX::writeDescriptor(QSharedPointer<QLowEnergySe
// We can work only with services found on a given peripheral
// (== created by the given LE controller),
// otherwise we can not write anything at all.
- if (!discoveredServices.contains(service->uuid)) {
+ if (!serviceList.contains(service->uuid)) {
qCWarning(QT_BT_OSX) << "no service with uuid:"
<< service->uuid << " found";
return;
}
dispatch_queue_t leQueue(OSXBluetooth::qt_LE_queue());
- if (!leQueue) {
- qCWarning(QT_BT_OSX) << "no LE queue found";
- return;
- }
+ Q_ASSERT_X(leQueue, Q_FUNC_INFO, "no LE queue found");
// Attention! Copy objects!
const QBluetoothUuid serviceUuid(service->uuid);
- ObjCCentralManager * const manager = centralManager.data();
+ ObjCCentralManager * const manager = centralManager.getAs<ObjCCentralManager>();
const QByteArray newValueCopy(newValue);
dispatch_async(leQueue, ^{
[manager write:newValueCopy
@@ -867,8 +921,8 @@ void QLowEnergyControllerPrivateOSX::writeDescriptor(QSharedPointer<QLowEnergySe
});
}
-quint16 QLowEnergyControllerPrivateOSX::updateValueOfDescriptor(QLowEnergyHandle charHandle, QLowEnergyHandle descHandle,
- const QByteArray &value, bool appendValue)
+quint16 QLowEnergyControllerPrivateDarwin::updateValueOfDescriptor(QLowEnergyHandle charHandle, QLowEnergyHandle descHandle,
+ const QByteArray &value, bool appendValue)
{
QSharedPointer<QLowEnergyServicePrivate> service = serviceForHandle(charHandle);
if (!service.isNull()) {
@@ -893,66 +947,15 @@ quint16 QLowEnergyControllerPrivateOSX::updateValueOfDescriptor(QLowEnergyHandle
return 0;
}
-QSharedPointer<QLowEnergyServicePrivate> QLowEnergyControllerPrivateOSX::serviceForHandle(QLowEnergyHandle handle)
-{
- const QList<QSharedPointer<QLowEnergyServicePrivate>> services
- = discoveredServices.values();
- for (QSharedPointer<QLowEnergyServicePrivate> service : services) {
- if (service->startHandle <= handle && handle <= service->endHandle)
- return service;
- }
-
- return QSharedPointer<QLowEnergyServicePrivate>();
-}
-
-QLowEnergyCharacteristic QLowEnergyControllerPrivateOSX::characteristicForHandle(QLowEnergyHandle charHandle)
-{
- QSharedPointer<QLowEnergyServicePrivate> service(serviceForHandle(charHandle));
- if (service.isNull())
- return QLowEnergyCharacteristic();
-
- if (service->characteristicList.isEmpty())
- return QLowEnergyCharacteristic();
-
- // Check whether it is the handle of a characteristic header
- if (service->characteristicList.contains(charHandle))
- return QLowEnergyCharacteristic(service, charHandle);
-
- // Check whether it is the handle of the characteristic value or its descriptors
- QList<QLowEnergyHandle> charHandles(service->characteristicList.keys());
- std::sort(charHandles.begin(), charHandles.end());
-
- for (int i = charHandles.size() - 1; i >= 0; --i) {
- if (charHandles.at(i) > charHandle)
- continue;
-
- return QLowEnergyCharacteristic(service, charHandles.at(i));
- }
-
- return QLowEnergyCharacteristic();
-}
-
-QLowEnergyDescriptor QLowEnergyControllerPrivateOSX::descriptorForHandle(QLowEnergyHandle descriptorHandle)
-{
- const QLowEnergyCharacteristic ch(characteristicForHandle(descriptorHandle));
- if (!ch.isValid())
- return QLowEnergyDescriptor();
-
- const QLowEnergyServicePrivate::CharData charData = ch.d_ptr->characteristicList[ch.attributeHandle()];
-
- if (charData.descriptorList.contains(descriptorHandle))
- return QLowEnergyDescriptor(ch.d_ptr, ch.attributeHandle(), descriptorHandle);
-
- return QLowEnergyDescriptor();
-}
-
-void QLowEnergyControllerPrivateOSX::setErrorDescription(QLowEnergyController::Error errorCode)
+void QLowEnergyControllerPrivateDarwin::setErrorDescription(QLowEnergyController::Error errorCode)
{
// This function does not emit!
+ // TODO: well, it is not a reason to duplicate a significant part of
+ // setError though!
- lastError = errorCode;
+ error = errorCode;
- switch (lastError) {
+ switch (error) {
case QLowEnergyController::NoError:
errorString.clear();
break;
@@ -978,48 +981,36 @@ void QLowEnergyControllerPrivateOSX::setErrorDescription(QLowEnergyController::E
}
}
-void QLowEnergyControllerPrivateOSX::invalidateServices()
-{
- const QList<QSharedPointer<QLowEnergyServicePrivate>> services
- = discoveredServices.values();
- for (const QSharedPointer<QLowEnergyServicePrivate> service : services) {
- service->setController(nullptr);
- service->setState(QLowEnergyService::InvalidService);
- }
-
- discoveredServices.clear();
-}
-
-bool QLowEnergyControllerPrivateOSX::connectSlots(OSXBluetooth::LECBManagerNotifier *notifier)
+bool QLowEnergyControllerPrivateDarwin::connectSlots(OSXBluetooth::LECBManagerNotifier *notifier)
{
using OSXBluetooth::LECBManagerNotifier;
Q_ASSERT_X(notifier, Q_FUNC_INFO, "invalid notifier object (null)");
bool ok = connect(notifier, &LECBManagerNotifier::connected,
- this, &QLowEnergyControllerPrivateOSX::_q_connected);
+ this, &QLowEnergyControllerPrivateDarwin::_q_connected);
ok = ok && connect(notifier, &LECBManagerNotifier::disconnected,
- this, &QLowEnergyControllerPrivateOSX::_q_disconnected);
+ this, &QLowEnergyControllerPrivateDarwin::_q_disconnected);
ok = ok && connect(notifier, &LECBManagerNotifier::serviceDiscoveryFinished,
- this, &QLowEnergyControllerPrivateOSX::_q_serviceDiscoveryFinished);
- ok = ok && connect(notifier, &LECBManagerNotifier::serviceDetailsDiscoveryFinished,
- this, &QLowEnergyControllerPrivateOSX::_q_serviceDetailsDiscoveryFinished);
+ this, &QLowEnergyControllerPrivateDarwin::_q_serviceDiscoveryFinished);
ok = ok && connect(notifier, &LECBManagerNotifier::servicesWereModified,
- this, &QLowEnergyControllerPrivateOSX::_q_servicesWereModified);
+ this, &QLowEnergyControllerPrivateDarwin::_q_servicesWereModified);
+ ok = ok && connect(notifier, &LECBManagerNotifier::serviceDetailsDiscoveryFinished,
+ this, &QLowEnergyControllerPrivateDarwin::_q_serviceDetailsDiscoveryFinished);
ok = ok && connect(notifier, &LECBManagerNotifier::characteristicRead,
- this, &QLowEnergyControllerPrivateOSX::_q_characteristicRead);
+ this, &QLowEnergyControllerPrivateDarwin::_q_characteristicRead);
ok = ok && connect(notifier, &LECBManagerNotifier::characteristicWritten,
- this, &QLowEnergyControllerPrivateOSX::_q_characteristicWritten);
+ this, &QLowEnergyControllerPrivateDarwin::_q_characteristicWritten);
ok = ok && connect(notifier, &LECBManagerNotifier::characteristicUpdated,
- this, &QLowEnergyControllerPrivateOSX::_q_characteristicUpdated);
+ this, &QLowEnergyControllerPrivateDarwin::_q_characteristicUpdated);
ok = ok && connect(notifier, &LECBManagerNotifier::descriptorRead,
- this, &QLowEnergyControllerPrivateOSX::_q_descriptorRead);
+ this, &QLowEnergyControllerPrivateDarwin::_q_descriptorRead);
ok = ok && connect(notifier, &LECBManagerNotifier::descriptorWritten,
- this, &QLowEnergyControllerPrivateOSX::_q_descriptorWritten);
+ this, &QLowEnergyControllerPrivateDarwin::_q_descriptorWritten);
ok = ok && connect(notifier, &LECBManagerNotifier::notificationEnabled,
- this, &QLowEnergyControllerPrivateOSX::_q_notificationEnabled);
+ this, &QLowEnergyControllerPrivateDarwin::_q_notificationEnabled);
ok = ok && connect(notifier, &LECBManagerNotifier::LEnotSupported,
- this, &QLowEnergyControllerPrivateOSX::_q_LEnotSupported);
+ this, &QLowEnergyControllerPrivateDarwin::_q_LEnotSupported);
ok = ok && connect(notifier, SIGNAL(CBManagerError(QLowEnergyController::Error)),
this, SLOT(_q_CBManagerError(QLowEnergyController::Error)));
ok = ok && connect(notifier, SIGNAL(CBManagerError(const QBluetoothUuid &, QLowEnergyController::Error)),
@@ -1033,253 +1024,9 @@ bool QLowEnergyControllerPrivateOSX::connectSlots(OSXBluetooth::LECBManagerNotif
return ok;
}
-QLowEnergyController::QLowEnergyController(const QBluetoothAddress &remoteAddress,
- QObject *parent)
- : QObject(parent),
- d_ptr(new QLowEnergyControllerPrivateOSX(CentralRole, this))
-{
- OSX_D_PTR;
-
- osx_d_ptr->remoteAddress = remoteAddress;
- osx_d_ptr->localAddress = QBluetoothLocalDevice().address();
-
- qCWarning(QT_BT_OSX) << "construction with remote address "
- "is not supported!";
-}
-
-QLowEnergyController::QLowEnergyController(const QBluetoothDeviceInfo &remoteDevice,
- QObject *parent)
- : QObject(parent),
- d_ptr(new QLowEnergyControllerPrivateOSX(CentralRole, this, remoteDevice))
-{
- OSX_D_PTR;
-
- osx_d_ptr->localAddress = QBluetoothLocalDevice().address();
- // That's the only "real" ctor - with Core Bluetooth we need a _valid_ deviceUuid
- // from 'remoteDevice'.
-}
-
-QLowEnergyController::QLowEnergyController(const QBluetoothAddress &remoteAddress,
- const QBluetoothAddress &localAddress,
- QObject *parent)
- : QObject(parent),
- d_ptr(new QLowEnergyControllerPrivateOSX(CentralRole, this))
-{
- OSX_D_PTR;
-
- osx_d_ptr->remoteAddress = remoteAddress;
- osx_d_ptr->localAddress = localAddress;
-
- qCWarning(QT_BT_OSX) << "construction with remote/local "
- "addresses is not supported!";
-}
-
-QLowEnergyController::QLowEnergyController(QObject *parent)
- : QObject(parent),
- d_ptr(new QLowEnergyControllerPrivateOSX(PeripheralRole, this))
-{
- OSX_D_PTR;
-
- osx_d_ptr->localAddress = QBluetoothLocalDevice().address();
-}
-
-QLowEnergyController *QLowEnergyController::createCentral(const QBluetoothDeviceInfo &remoteDevice,
- QObject *parent)
-{
- return new QLowEnergyController(remoteDevice, parent);
-}
-
-QLowEnergyController *QLowEnergyController::createPeripheral(QObject *parent)
-{
- return new QLowEnergyController(parent);
-}
-
-QLowEnergyController::~QLowEnergyController()
-{
- // Deleting a peripheral will also disconnect.
- delete d_ptr;
-}
-
-QLowEnergyController::Role QLowEnergyController::role() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->role;
-}
-
-QBluetoothAddress QLowEnergyController::localAddress() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->localAddress;
-}
-
-QBluetoothAddress QLowEnergyController::remoteAddress() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->remoteAddress;
-}
-
-QBluetoothUuid QLowEnergyController::remoteDeviceUuid() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->deviceUuid;
-}
-
-QString QLowEnergyController::remoteName() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->deviceName;
-}
-
-QLowEnergyController::ControllerState QLowEnergyController::state() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->controllerState;
-}
-
-QLowEnergyController::RemoteAddressType QLowEnergyController::remoteAddressType() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->addressType;
-}
-
-void QLowEnergyController::setRemoteAddressType(RemoteAddressType type)
-{
- Q_UNUSED(type)
-
- OSX_D_PTR;
-
- osx_d_ptr->addressType = type;
-}
-
-void QLowEnergyController::connectToDevice()
-{
- OSX_D_PTR;
-
- // A memory allocation problem.
- if (!osx_d_ptr->isValid())
- return osx_d_ptr->_q_CBManagerError(UnknownError);
-
- if (role() == PeripheralRole) {
- qCWarning(QT_BT_OSX) << "can not connect in peripheral role";
- return osx_d_ptr->_q_CBManagerError(ConnectionError);
- }
-
- // No QBluetoothDeviceInfo provided during construction.
- if (osx_d_ptr->deviceUuid.isNull())
- return osx_d_ptr->_q_CBManagerError(UnknownRemoteDeviceError);
-
- if (osx_d_ptr->controllerState != UnconnectedState)
- return;
-
- osx_d_ptr->connectToDevice();
-}
-
-void QLowEnergyController::disconnectFromDevice()
-{
- if (state() == UnconnectedState || state() == ClosingState)
- return;
-
- OSX_D_PTR;
-
- if (role() == PeripheralRole) {
- // CoreBluetooth API intentionally does not provide any way of closing
- // a connection. All we can do here is to stop the advertisement.
- stopAdvertising();
- return;
- }
-
- if (osx_d_ptr->isValid()) {
- const ControllerState oldState = osx_d_ptr->controllerState;
-
- if (dispatch_queue_t leQueue = OSXBluetooth::qt_LE_queue()) {
- osx_d_ptr->controllerState = ClosingState;
- emit stateChanged(ClosingState);
- osx_d_ptr->invalidateServices();
-
- QT_MANGLE_NAMESPACE(OSXBTCentralManager) *manager
- = osx_d_ptr->centralManager.data();
- dispatch_async(leQueue, ^{
- [manager disconnectFromDevice];
- });
-
- if (oldState == ConnectingState) {
- // With a pending connect attempt there is no
- // guarantee we'll ever have didDisconnect callback,
- // set the state here and now to make sure we still
- // can connect.
- osx_d_ptr->controllerState = UnconnectedState;
- emit stateChanged(UnconnectedState);
- }
- } else {
- qCCritical(QT_BT_OSX) << "qt LE queue is nil, "
- "can not dispatch 'disconnect'";
- }
- }
-}
-
-void QLowEnergyController::discoverServices()
-{
- if (role() == PeripheralRole) {
- qCWarning(QT_BT_OSX) << "invalid role (peripheral)";
- return;
- }
-
- if (state() != ConnectedState)
- return;
-
- OSX_D_PTR;
-
- osx_d_ptr->discoverServices();
-}
-
-QList<QBluetoothUuid> QLowEnergyController::services() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->discoveredServices.keys();
-}
-
-QLowEnergyService *QLowEnergyController::createServiceObject(const QBluetoothUuid &serviceUuid,
- QObject *parent)
-{
- OSX_D_PTR;
-
- QLowEnergyService *service = nullptr;
-
- QLowEnergyControllerPrivateOSX::ServiceMap::const_iterator it = osx_d_ptr->discoveredServices.constFind(serviceUuid);
- if (it != osx_d_ptr->discoveredServices.constEnd()) {
- const QSharedPointer<QLowEnergyServicePrivate> &serviceData = it.value();
-
- service = new QLowEnergyService(serviceData, parent);
- }
-
- return service;
-}
-
-QLowEnergyController::Error QLowEnergyController::error() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->lastError;
-}
-
-QString QLowEnergyController::errorString() const
-{
- OSX_D_PTR;
-
- return osx_d_ptr->errorString;
-}
-
-void QLowEnergyController::startAdvertising(const QLowEnergyAdvertisingParameters &params,
- const QLowEnergyAdvertisingData &advertisingData,
- const QLowEnergyAdvertisingData &scanResponseData)
+void QLowEnergyControllerPrivateDarwin::startAdvertising(const QLowEnergyAdvertisingParameters &params,
+ const QLowEnergyAdvertisingData &advertisingData,
+ const QLowEnergyAdvertisingData &scanResponseData)
{
#ifdef Q_OS_TVOS
Q_UNUSED(params)
@@ -1287,123 +1034,65 @@ void QLowEnergyController::startAdvertising(const QLowEnergyAdvertisingParameter
Q_UNUSED(scanResponseData)
qCWarning(QT_BT_OSX) << "advertising is not supported on your platform";
#else
- OSX_D_PTR;
- if (!osx_d_ptr->isValid())
- return osx_d_ptr->_q_CBManagerError(UnknownError);
+ if (!isValid())
+ return _q_CBManagerError(QLowEnergyController::UnknownError);
- if (role() != PeripheralRole) {
- qCWarning(QT_BT_OSX) << "invalid role";
+ if (role != QLowEnergyController::PeripheralRole) {
+ qCWarning(QT_BT_OSX) << "controller is not a peripheral, cannot start advertising";
return;
}
- if (state() != UnconnectedState) {
- qCWarning(QT_BT_OSX) << "invalid state" << state();
+ if (state != QLowEnergyController::UnconnectedState) {
+ qCWarning(QT_BT_OSX) << "invalid state" << state;
return;
}
auto leQueue(OSXBluetooth::qt_LE_queue());
if (!leQueue) {
qCWarning(QT_BT_OSX) << "no LE queue found";
- osx_d_ptr->setErrorDescription(QLowEnergyController::UnknownError);
+ setErrorDescription(QLowEnergyController::UnknownError);
return;
}
- [osx_d_ptr->peripheralManager setParameters:params
- data:advertisingData
- scanResponse:scanResponseData];
+ const auto manager = peripheralManager.getAs<ObjCPeripheralManager>();
+ [manager setParameters:params data:advertisingData scanResponse:scanResponseData];
- osx_d_ptr->controllerState = AdvertisingState;
- emit stateChanged(AdvertisingState);
+ setState(QLowEnergyController::AdvertisingState);
- const auto manager = osx_d_ptr->peripheralManager.data();
dispatch_async(leQueue, ^{
[manager startAdvertising];
});
#endif
}
-void QLowEnergyController::stopAdvertising()
+void QLowEnergyControllerPrivateDarwin::stopAdvertising()
{
#ifdef Q_OS_TVOS
qCWarning(QT_BT_OSX) << "advertising is not supported on your platform";
#else
- OSX_D_PTR;
-
- if (!osx_d_ptr->isValid())
- return osx_d_ptr->_q_CBManagerError(UnknownError);
+ if (!isValid())
+ return _q_CBManagerError(QLowEnergyController::UnknownError);
- if (state() != AdvertisingState) {
- qCDebug(QT_BT_OSX) << "cannot stop advertising, called in state" << state();
+ if (state != QLowEnergyController::AdvertisingState) {
+ qCDebug(QT_BT_OSX) << "cannot stop advertising, called in state" << state;
return;
}
if (const auto leQueue = OSXBluetooth::qt_LE_queue()) {
- const auto manager = osx_d_ptr->peripheralManager.data();
+ const auto manager = peripheralManager.getAs<ObjCPeripheralManager>();
dispatch_sync(leQueue, ^{
[manager stopAdvertising];
});
- osx_d_ptr->controllerState = UnconnectedState;
- emit stateChanged(UnconnectedState);
+ setState(QLowEnergyController::UnconnectedState);
} else {
qCWarning(QT_BT_OSX) << "no LE queue found";
- osx_d_ptr->setErrorDescription(QLowEnergyController::UnknownError);
+ setErrorDescription(QLowEnergyController::UnknownError);
return;
}
#endif
}
-QLowEnergyService *QLowEnergyController::addService(const QLowEnergyServiceData &data,
- QObject *parent)
-{
-#ifdef Q_OS_TVOS
- Q_UNUSED(data)
- Q_UNUSED(parent)
- qCWarning(QT_BT_OSX) << "peripheral role is not supported on your platform";
-#else
- OSX_D_PTR;
-
- if (!osx_d_ptr->isValid()) {
- osx_d_ptr->_q_CBManagerError(UnknownError);
- return nullptr;
- }
-
- if (role() != PeripheralRole) {
- qCWarning(QT_BT_OSX) << "not in peripheral role";
- return nullptr;
- }
-
- if (state() != UnconnectedState) {
- qCWarning(QT_BT_OSX) << "invalid state";
- return nullptr;
- }
-
- if (!data.isValid()) {
- qCWarning(QT_BT_OSX) << "invalid service";
- return nullptr;
- }
-
- for (auto includedService : data.includedServices())
- includedService->d_ptr->type |= QLowEnergyService::IncludedService;
-
- if (const auto servicePrivate = [osx_d_ptr->peripheralManager addService:data]) {
- servicePrivate->setController(osx_d_ptr);
- servicePrivate->state = QLowEnergyService::LocalService;
- osx_d_ptr->discoveredServices.insert(servicePrivate->uuid, servicePrivate);
- return new QLowEnergyService(servicePrivate, parent);
- }
-#endif
-
- return nullptr;
-}
-
-void QLowEnergyController::requestConnectionUpdate(const QLowEnergyConnectionParameters &params)
-{
- Q_UNUSED(params);
- qCWarning(QT_BT_OSX) << "Connection update not implemented on your platform";
-}
-
QT_END_NAMESPACE
-#include "moc_qlowenergycontroller_osx_p.cpp"
diff --git a/src/bluetooth/qlowenergycontroller_osx_p.h b/src/bluetooth/qlowenergycontroller_darwin_p.h
index da959895..960d7fbc 100644
--- a/src/bluetooth/qlowenergycontroller_osx_p.h
+++ b/src/bluetooth/qlowenergycontroller_darwin_p.h
@@ -37,8 +37,8 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QLOWENERGYCONTROLLER_OSX_P_H
-#define QLOWENERGYCONTROLLER_OSX_P_H
+#ifndef QLOWENERGYCONTROLLER_DARWIN_P_H
+#define QLOWENERGYCONTROLLER_DARWIN_P_H
//
// W A R N I N G
@@ -51,46 +51,64 @@
// We mean it.
//
-#include "osx/osxbtperipheralmanager_p.h"
#include "qlowenergyserviceprivate_p.h"
-#include "osx/osxbtcentralmanager_p.h"
#include "qlowenergycontrollerbase_p.h"
#include "qlowenergycontroller.h"
#include "osx/osxbtnotifier_p.h"
-#include "osx/osxbtutility_p.h"
#include "qbluetoothaddress.h"
#include "qbluetoothuuid.h"
+#include "osx/btraii_p.h"
#include <QtCore/qsharedpointer.h>
-#include <QtCore/qsysinfo.h>
#include <QtCore/qglobal.h>
#include <QtCore/qstring.h>
#include <QtCore/qmap.h>
QT_BEGIN_NAMESPACE
-namespace OSXBluetooth
-{
-
-class LECBManagerNotifier;
-
-}
-
class QByteArray;
-// Suffix 'OSX' is a legacy, it's also iOS.
-class QLowEnergyControllerPrivateOSX : public QLowEnergyControllerPrivate
+class QLowEnergyControllerPrivateDarwin : public QLowEnergyControllerPrivate
{
friend class QLowEnergyController;
friend class QLowEnergyService;
Q_OBJECT
public:
- QLowEnergyControllerPrivateOSX(QLowEnergyController::Role role, QLowEnergyController *q,
- const QBluetoothDeviceInfo &info = QBluetoothDeviceInfo());
- ~QLowEnergyControllerPrivateOSX();
-
- bool isValid() const;
+ QLowEnergyControllerPrivateDarwin();
+ ~QLowEnergyControllerPrivateDarwin();
+
+ void init() override;
+ void connectToDevice() override;
+ void disconnectFromDevice() override;
+ void discoverServices() override;
+ void discoverServiceDetails(const QBluetoothUuid &serviceUuid) override;
+
+ void readCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle) override;
+ void readDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle) override;
+
+ void writeCharacteristic(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle, const QByteArray &newValue,
+ QLowEnergyService::WriteMode mode) override;
+ void writeDescriptor(const QSharedPointer<QLowEnergyServicePrivate> service,
+ const QLowEnergyHandle charHandle,
+ const QLowEnergyHandle descriptorHandle,
+ const QByteArray &newValue) override;
+
+
+ void requestConnectionUpdate(const QLowEnergyConnectionParameters &params) override;
+ void addToGenericAttributeList(const QLowEnergyServiceData &service,
+ QLowEnergyHandle startHandle) override;
+
+ void startAdvertising(const QLowEnergyAdvertisingParameters &params,
+ const QLowEnergyAdvertisingData &advertisingData,
+ const QLowEnergyAdvertisingData &scanResponseData) override;
+ void stopAdvertising()override;
+ QLowEnergyService *addServiceHelper(const QLowEnergyServiceData &service) override;
+ bool isValid() const; // QT6 - delete this logic.
private Q_SLOTS:
void _q_connected();
@@ -113,75 +131,30 @@ private Q_SLOTS:
void _q_CBManagerError(const QBluetoothUuid &serviceUuid, QLowEnergyService::ServiceError error);
private:
- void connectToDevice();
- void discoverServices();
- void discoverServiceDetails(const QBluetoothUuid &serviceUuid);
-
void setNotifyValue(QSharedPointer<QLowEnergyServicePrivate> service,
QLowEnergyHandle charHandle, const QByteArray &newValue);
- void readCharacteristic(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle charHandle);
- void writeCharacteristic(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle charHandle, const QByteArray &newValue,
- QLowEnergyService::WriteMode mode);
-
quint16 updateValueOfCharacteristic(QLowEnergyHandle charHandle,
const QByteArray &value,
bool appendValue);
- void readDescriptor(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle charHandle);
- void writeDescriptor(QSharedPointer<QLowEnergyServicePrivate> service,
- QLowEnergyHandle descriptorHandle,
- const QByteArray &newValue);
-
-
quint16 updateValueOfDescriptor(QLowEnergyHandle charHandle,
QLowEnergyHandle descHandle,
const QByteArray &value,
bool appendValue);
- // 'Lookup' functions:
- QSharedPointer<QLowEnergyServicePrivate> serviceForHandle(QLowEnergyHandle serviceHandle);
- QLowEnergyCharacteristic characteristicForHandle(QLowEnergyHandle charHandle);
- QLowEnergyDescriptor descriptorForHandle(QLowEnergyHandle descriptorHandle);
-
void setErrorDescription(QLowEnergyController::Error errorCode);
- void invalidateServices();
bool connectSlots(OSXBluetooth::LECBManagerNotifier *notifier);
- QLowEnergyController *q_ptr;
- QBluetoothUuid deviceUuid;
- QString deviceName;
-
- QString errorString;
- QLowEnergyController::Error lastError;
-
- QBluetoothAddress localAddress;
- QBluetoothAddress remoteAddress;
-
- QLowEnergyController::Role role;
-
- QLowEnergyController::ControllerState controllerState;
- QLowEnergyController::RemoteAddressType addressType;
-
- typedef QT_MANGLE_NAMESPACE(OSXBTCentralManager) ObjCCentralManager;
- typedef OSXBluetooth::ObjCScopedPointer<ObjCCentralManager> CentralManager;
- CentralManager centralManager;
+ DarwinBluetooth::ScopedPointer centralManager;
#ifndef Q_OS_TVOS
- typedef QT_MANGLE_NAMESPACE(OSXBTPeripheralManager) ObjCPeripheralManager;
- typedef OSXBluetooth::ObjCScopedPointer<ObjCPeripheralManager> PeripheralManager;
- PeripheralManager peripheralManager;
+ DarwinBluetooth::ScopedPointer peripheralManager;
#endif
- typedef QMap<QBluetoothUuid, QSharedPointer<QLowEnergyServicePrivate> > ServiceMap;
- typedef ServiceMap::const_iterator ConstServiceIterator;
- typedef ServiceMap::iterator ServiceIterator;
- ServiceMap discoveredServices;
+ using ServiceMap = QMap<QBluetoothUuid, QSharedPointer<QLowEnergyServicePrivate>>;
};
QT_END_NAMESPACE
-#endif
+#endif // QLOWENERGYCONTROLLER_DARWIN_P_H
diff --git a/src/bluetooth/qlowenergycontrollerbase.cpp b/src/bluetooth/qlowenergycontrollerbase.cpp
index 86108648..de72808e 100644
--- a/src/bluetooth/qlowenergycontrollerbase.cpp
+++ b/src/bluetooth/qlowenergycontrollerbase.cpp
@@ -61,7 +61,7 @@ QLowEnergyControllerPrivate::~QLowEnergyControllerPrivate()
bool QLowEnergyControllerPrivate::isValidLocalAdapter()
{
-#ifdef QT_WINRT_BLUETOOTH
+#if defined(QT_WINRT_BLUETOOTH) || defined(Q_OS_DARWIN)
return true;
#endif
if (localAdapter.isNull())
diff --git a/src/bluetooth/qlowenergycontrollerbase_p.h b/src/bluetooth/qlowenergycontrollerbase_p.h
index a8d1c676..169ba07b 100644
--- a/src/bluetooth/qlowenergycontrollerbase_p.h
+++ b/src/bluetooth/qlowenergycontrollerbase_p.h
@@ -51,24 +51,6 @@
// We mean it.
//
-#if defined(QT_OSX_BLUETOOTH) || defined(QT_IOS_BLUETOOTH)
-
-#include <QtCore/qglobal.h>
-#include <QtCore/qobject.h>
-
-QT_BEGIN_NAMESPACE
-
-class QLowEnergyControllerPrivate : public QObject
-{
-public:
- // This class is required to make shared pointer machinery and
- // moc (== Obj-C syntax) happy on both OS X and iOS.
-};
-
-QT_END_NAMESPACE
-
-#else
-
#include <qglobal.h>
#include <QtCore/qobject.h>
@@ -135,7 +117,6 @@ public:
virtual QLowEnergyService *addServiceHelper(
const QLowEnergyServiceData &service);
-
// common backend methods
bool isValidLocalAdapter();
void setError(QLowEnergyController::Error newError);
@@ -174,6 +155,7 @@ protected:
QLowEnergyHandle lastLocalHandle{};
QString remoteName; // device name of the remote
+ QBluetoothUuid deviceUuid; // quite useless anywhere but Darwin (CoreBluetooth).
Q_DECLARE_PUBLIC(QLowEnergyController)
QLowEnergyController *q_ptr;
@@ -181,6 +163,4 @@ protected:
QT_END_NAMESPACE
-#endif //defined(QT_OSX_BLUETOOTH) || defined(QT_IOS_BLUETOOTH)
-
#endif // QLOWENERGYCONTROLLERPRIVATEBASE_P_H
diff --git a/src/bluetooth/qlowenergydescriptor.h b/src/bluetooth/qlowenergydescriptor.h
index 62ca5fd3..84f48fbc 100644
--- a/src/bluetooth/qlowenergydescriptor.h
+++ b/src/bluetooth/qlowenergydescriptor.h
@@ -83,7 +83,7 @@ protected:
friend class QLowEnergyControllerPrivateBluez;
friend class QLowEnergyControllerPrivateBluezDBus;
friend class QLowEnergyControllerPrivateCommon;
- friend class QLowEnergyControllerPrivateOSX;
+ friend class QLowEnergyControllerPrivateDarwin;
friend class QLowEnergyControllerPrivateWinRT;
friend class QLowEnergyControllerPrivateWinRTNew;
QLowEnergyDescriptorPrivate *data = nullptr;
diff --git a/src/bluetooth/qlowenergyservice.cpp b/src/bluetooth/qlowenergyservice.cpp
index 1529d3c2..2e6d1f9b 100644
--- a/src/bluetooth/qlowenergyservice.cpp
+++ b/src/bluetooth/qlowenergyservice.cpp
@@ -47,6 +47,10 @@
#include "qlowenergycontrollerbase_p.h"
#include "qlowenergyserviceprivate_p.h"
+#ifdef Q_OS_DARWIN
+#include "qlowenergycontroller_darwin_p.h"
+#endif // Q_OS_DARWIN
+
QT_BEGIN_NAMESPACE
/*!
@@ -809,6 +813,21 @@ void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor,
d->setError(QLowEnergyService::OperationError);
return;
}
+#ifdef Q_OS_DARWIN
+ if (descriptor.uuid() == QBluetoothUuid::ClientCharacteristicConfiguration) {
+ // We have to identify a special case - ClientCharacteristicConfiguration
+ // since with CoreBluetooth:
+ //
+ // "You cannot use this method to write the value of a client configuration descriptor
+ // (represented by the CBUUIDClientCharacteristicConfigurationString constant),
+ // which describes how notification or indications are configured for a
+ // characteristic’s value with respect to a client. If you want to manage
+ // notifications or indications for a characteristic’s value, you must
+ // use the setNotifyValue:forCharacteristic: method instead."
+ auto controller = static_cast<QLowEnergyControllerPrivateDarwin *>(d->controller.data());
+ return controller->setNotifyValue(descriptor.d_ptr, descriptor.characteristicHandle(), newValue);
+ }
+#endif // Q_OS_DARWIN
d->controller->writeDescriptor(descriptor.d_ptr,
descriptor.characteristicHandle(),
diff --git a/src/bluetooth/qlowenergyservice.h b/src/bluetooth/qlowenergyservice.h
index 9de65a84..a2715471 100644
--- a/src/bluetooth/qlowenergyservice.h
+++ b/src/bluetooth/qlowenergyservice.h
@@ -136,6 +136,7 @@ private:
friend class QLowEnergyControllerPrivate;
friend class QLowEnergyControllerPrivateBluez;
friend class QLowEnergyControllerPrivateAndroid;
+ friend class QLowEnergyControllerPrivateDarwin;
QLowEnergyService(QSharedPointer<QLowEnergyServicePrivate> p,
QObject *parent = nullptr);
};
diff --git a/src/bluetooth/qlowenergyservice_osx.mm b/src/bluetooth/qlowenergyservice_osx.mm
deleted file mode 100644
index c294b693..00000000
--- a/src/bluetooth/qlowenergyservice_osx.mm
+++ /dev/null
@@ -1,277 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Javier S. Pedro <maemo@javispedro.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtBluetooth module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qlowenergycontroller_osx_p.h"
-#include "qlowenergyserviceprivate_p.h"
-#include "qlowenergycharacteristic.h"
-#include "qlowenergydescriptor.h"
-#include "qlowenergyservice.h"
-#include "qbluetoothuuid.h"
-
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qstring.h>
-#include <QtCore/qlist.h>
-
-#include <algorithm>
-
-QT_BEGIN_NAMESPACE
-
-namespace {
-
-QLowEnergyControllerPrivateOSX *qt_mac_le_controller(QSharedPointer<QLowEnergyServicePrivate> d_ptr)
-{
- if (d_ptr.isNull())
- return nullptr;
-
- return static_cast<QLowEnergyControllerPrivateOSX *>(d_ptr->controller.data());
-}
-
-}
-
-QLowEnergyService::QLowEnergyService(QSharedPointer<QLowEnergyServicePrivate> d, QObject *parent)
- : QObject(parent),
- d_ptr(d)
-{
- qRegisterMetaType<QLowEnergyService::ServiceState>();
- qRegisterMetaType<QLowEnergyService::ServiceError>();
-
- connect(d.data(), SIGNAL(error(QLowEnergyService::ServiceError)),
- this, SIGNAL(error(QLowEnergyService::ServiceError)));
- connect(d.data(), SIGNAL(stateChanged(QLowEnergyService::ServiceState)),
- this, SIGNAL(stateChanged(QLowEnergyService::ServiceState)));
- connect(d.data(), SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)),
- this, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)));
- connect(d.data(), SIGNAL(characteristicWritten(QLowEnergyCharacteristic, QByteArray)),
- this, SIGNAL(characteristicWritten(QLowEnergyCharacteristic, QByteArray)));
- connect(d.data(), SIGNAL(descriptorWritten(QLowEnergyDescriptor, QByteArray)),
- this, SIGNAL(descriptorWritten(QLowEnergyDescriptor, QByteArray)));
- connect(d.data(), SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)),
- this, SIGNAL(characteristicRead(QLowEnergyCharacteristic,QByteArray)));
- connect(d.data(), SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray)),
- this, SIGNAL(descriptorRead(QLowEnergyDescriptor,QByteArray)));
-
-}
-
-QLowEnergyService::~QLowEnergyService()
-{
-}
-
-QList<QBluetoothUuid> QLowEnergyService::includedServices() const
-{
- return d_ptr->includedServices;
-}
-
-QLowEnergyService::ServiceTypes QLowEnergyService::type() const
-{
- return d_ptr->type;
-}
-
-QLowEnergyService::ServiceState QLowEnergyService::state() const
-{
- return d_ptr->state;
-}
-
-QLowEnergyCharacteristic QLowEnergyService::characteristic(const QBluetoothUuid &uuid) const
-{
- CharacteristicDataMap::const_iterator charIt = d_ptr->characteristicList.constBegin();
- for ( ; charIt != d_ptr->characteristicList.constEnd(); ++charIt) {
- const QLowEnergyHandle charHandle = charIt.key();
- const QLowEnergyServicePrivate::CharData &charDetails = charIt.value();
-
- if (charDetails.uuid == uuid)
- return QLowEnergyCharacteristic(d_ptr, charHandle);
- }
-
- return QLowEnergyCharacteristic();
-}
-
-QList<QLowEnergyCharacteristic> QLowEnergyService::characteristics() const
-{
- QList<QLowEnergyCharacteristic> result;
- QList<QLowEnergyHandle> handles(d_ptr->characteristicList.keys());
-
- std::sort(handles.begin(), handles.end());
-
- for (const QLowEnergyHandle &handle : qAsConst(handles)) {
- QLowEnergyCharacteristic characteristic(d_ptr, handle);
- result.append(characteristic);
- }
-
- return result;
-}
-
-QBluetoothUuid QLowEnergyService::serviceUuid() const
-{
- return d_ptr->uuid;
-}
-
-QString QLowEnergyService::serviceName() const
-{
- bool ok = false;
- const quint16 clsId = d_ptr->uuid.toUInt16(&ok);
- if (ok) {
- QBluetoothUuid::ServiceClassUuid uuid
- = static_cast<QBluetoothUuid::ServiceClassUuid>(clsId);
- const QString name = QBluetoothUuid::serviceClassToString(uuid);
- if (!name.isEmpty())
- return name;
- }
-
- return qApp ? qApp->translate("QBluetoothServiceDiscoveryAgent", "Unknown Service") :
- QStringLiteral("Unknown Service");
-}
-
-void QLowEnergyService::discoverDetails()
-{
- QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
-
- if (!controller || d_ptr->state == InvalidService) {
- d_ptr->setError(OperationError);
- return;
- }
-
- if (d_ptr->state != DiscoveryRequired)
- return;
-
- d_ptr->setState(QLowEnergyService::DiscoveringServices);
- controller->discoverServiceDetails(d_ptr->uuid);
-}
-
-QLowEnergyService::ServiceError QLowEnergyService::error() const
-{
- return d_ptr->lastError;
-}
-
-bool QLowEnergyService::contains(const QLowEnergyCharacteristic &characteristic) const
-{
- if (characteristic.d_ptr.isNull() || !characteristic.data)
- return false;
-
- if (d_ptr == characteristic.d_ptr
- && d_ptr->characteristicList.contains(characteristic.attributeHandle())) {
- return true;
- }
-
- return false;
-}
-
-void QLowEnergyService::readCharacteristic(const QLowEnergyCharacteristic &characteristic)
-{
- QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
- if (controller == nullptr || state() != ServiceDiscovered || !contains(characteristic)) {
- d_ptr->setError(OperationError);
- return;
- }
-
- controller->readCharacteristic(characteristic.d_ptr, characteristic.attributeHandle());
-}
-
-
-void QLowEnergyService::writeCharacteristic(const QLowEnergyCharacteristic &ch, const QByteArray &newValue,
- WriteMode mode)
-{
- QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
- if (controller == nullptr ||
- (controller->role == QLowEnergyController::CentralRole && state() != ServiceDiscovered) ||
- !contains(ch)) {
- d_ptr->setError(QLowEnergyService::OperationError);
- return;
- }
-
- controller->writeCharacteristic(ch.d_ptr, ch.attributeHandle(), newValue, mode);
-}
-
-bool QLowEnergyService::contains(const QLowEnergyDescriptor &descriptor) const
-{
- if (descriptor.d_ptr.isNull() || !descriptor.data)
- return false;
-
- const QLowEnergyHandle charHandle = descriptor.characteristicHandle();
- if (!charHandle)
- return false;
-
- if (d_ptr == descriptor.d_ptr && d_ptr->characteristicList.contains(charHandle)
- && d_ptr->characteristicList[charHandle].descriptorList.contains(descriptor.handle()))
- {
- return true;
- }
-
- return false;
-}
-
-void QLowEnergyService::readDescriptor(const QLowEnergyDescriptor &descriptor)
-{
- QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
- if (controller == nullptr || state() != ServiceDiscovered || !contains(descriptor)) {
- d_ptr->setError(OperationError);
- return;
- }
-
- controller->readDescriptor(descriptor.d_ptr, descriptor.handle());
-}
-
-void QLowEnergyService::writeDescriptor(const QLowEnergyDescriptor &descriptor,
- const QByteArray &newValue)
-{
- QLowEnergyControllerPrivateOSX *const controller = qt_mac_le_controller(d_ptr);
- if (controller == nullptr || state() != ServiceDiscovered || !contains(descriptor)) {
- // This operation error also includes LE controller in the peripheral role:
- // on iOS/OS X - descriptors are immutable.
- d_ptr->setError(OperationError);
- return;
- }
-
- if (descriptor.uuid() == QBluetoothUuid::ClientCharacteristicConfiguration) {
- // We have to identify a special case - ClientCharacteristicConfiguration
- // since with Core Bluetooth:
- //
- // "You cannot use this method to write the value of a client configuration descriptor
- // (represented by the CBUUIDClientCharacteristicConfigurationString constant),
- // which describes how notification or indications are configured for a
- // characteristic’s value with respect to a client. If you want to manage
- // notifications or indications for a characteristic’s value, you must
- // use the setNotifyValue:forCharacteristic: method instead."
- controller->setNotifyValue(descriptor.d_ptr, descriptor.characteristicHandle(), newValue);
- } else {
- controller->writeDescriptor(descriptor.d_ptr, descriptor.handle(), newValue);
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/nfc/qnearfieldtagtype2.cpp b/src/nfc/qnearfieldtagtype2.cpp
index 24ff8280..492dc5e3 100644
--- a/src/nfc/qnearfieldtagtype2.cpp
+++ b/src/nfc/qnearfieldtagtype2.cpp
@@ -307,9 +307,7 @@ void QNearFieldTagType2::timerEvent(QTimerEvent *event)
killTimer(event->timerId());
- QMutableMapIterator<QNearFieldTarget::RequestId, SectorSelectState> i(d->m_pendingSectorSelectCommands);
- while (i.hasNext()) {
- i.next();
+ for (auto i = d->m_pendingSectorSelectCommands.begin(), end = d->m_pendingSectorSelectCommands.end(); i != end; ++i) {
SectorSelectState &state = i.value();
@@ -318,8 +316,7 @@ void QNearFieldTagType2::timerEvent(QTimerEvent *event)
setResponseForRequest(i.key(), true);
- i.remove();
-
+ d->m_pendingSectorSelectCommands.erase(i);
break;
}
}
diff --git a/src/nfc/qnearfieldtarget.cpp b/src/nfc/qnearfieldtarget.cpp
index e9a6fa11..7d83db78 100644
--- a/src/nfc/qnearfieldtarget.cpp
+++ b/src/nfc/qnearfieldtarget.cpp
@@ -47,7 +47,7 @@
#include <QtCore/QDebug>
-#include <QTime>
+#include <QElapsedTimer>
#include <QCoreApplication>
QT_BEGIN_NAMESPACE
@@ -462,7 +462,7 @@ bool QNearFieldTarget::waitForRequestCompleted(const RequestId &id, int msecs)
{
Q_D(QNearFieldTarget);
- QTime timer;
+ QElapsedTimer timer;
timer.start();
do {
@@ -497,13 +497,12 @@ void QNearFieldTarget::setResponseForRequest(const QNearFieldTarget::RequestId &
{
Q_D(QNearFieldTarget);
- QMutableMapIterator<RequestId, QVariant> i(d->m_decodedResponses);
- while (i.hasNext()) {
- i.next();
-
+ for (auto i = d->m_decodedResponses.begin(), end = d->m_decodedResponses.end(); i != end; /* erasing */) {
// no more external references
if (i.key().refCount() == 1)
- i.remove();
+ i = d->m_decodedResponses.erase(i);
+ else
+ ++i;
}
d->m_decodedResponses.insert(id, response);
diff --git a/src/nfc/qqmlndefrecord.cpp b/src/nfc/qqmlndefrecord.cpp
index bc3667fe..5a96bec8 100644
--- a/src/nfc/qqmlndefrecord.cpp
+++ b/src/nfc/qqmlndefrecord.cpp
@@ -215,10 +215,9 @@ QQmlNdefRecord *qNewDeclarativeNdefRecordForNdefRecord(const QNdefRecord &record
{
const QString urn = urnForRecordType(record.typeNameFormat(), record.type());
- QMapIterator<QString, const QMetaObject *> i(*registeredNdefRecordTypes());
- while (i.hasNext()) {
- i.next();
+ const auto *rt = registeredNdefRecordTypes();
+ for (auto i = rt->cbegin(), end = rt->cend(); i != end; ++i) {
QRegularExpression rx(QRegularExpression::anchoredPattern(i.key()));
if (!rx.match(urn).hasMatch())
continue;
diff --git a/tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp b/tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp
index 6636f0cd..d8c80291 100644
--- a/tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp
+++ b/tests/auto/qbluetoothdeviceinfo/tst_qbluetoothdeviceinfo.cpp
@@ -447,21 +447,15 @@ void tst_QBluetoothDeviceInfo::tst_serviceUuids()
QBluetoothDeviceInfo deviceInfo;
QBluetoothDeviceInfo copyInfo = deviceInfo;
- QList<QBluetoothUuid> servicesList;
+ QVector<QBluetoothUuid> servicesList;
servicesList.append(QBluetoothUuid::L2cap);
servicesList.append(QBluetoothUuid::Rfcomm);
QVERIFY(servicesList.count() > 0);
- deviceInfo.setServiceUuids(servicesList.toVector());
+ deviceInfo.setServiceUuids(servicesList);
QVERIFY(deviceInfo.serviceUuids().count() > 0);
deviceInfo.setServiceUuids(QVector<QBluetoothUuid>());
QCOMPARE(deviceInfo.serviceUuids().count(), 0);
-
- deviceInfo.setServiceUuids(servicesList, QBluetoothDeviceInfo::DataComplete);
- QVERIFY(deviceInfo.serviceUuids().count() > 0);
- QVERIFY(deviceInfo != copyInfo);
-
- QVERIFY(deviceInfo.serviceUuidsCompleteness() == QBluetoothDeviceInfo::DataComplete);
}
void tst_QBluetoothDeviceInfo::tst_cached()
diff --git a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
index 8ffc0480..ab393210 100644
--- a/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
+++ b/tests/auto/qlowenergycontroller/tst_qlowenergycontroller.cpp
@@ -451,14 +451,18 @@ void tst_QLowEnergyController::tst_concurrentDiscovery()
// 2. new controller to same device fails
{
+#ifdef Q_OS_DARWIN
+ QLowEnergyController control2(remoteDeviceInfo);
+#else
QLowEnergyController control2(remoteDevice);
+#endif
control2.connectToDevice();
{
QTRY_IMPL(control2.state() != QLowEnergyController::ConnectingState,
30000);
}
-#if defined(Q_OS_ANDROID) || QT_CONFIG(winrt_bt)
+#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || QT_CONFIG(winrt_bt)
QCOMPARE(control.state(), QLowEnergyController::ConnectedState);
QCOMPARE(control2.state(), QLowEnergyController::ConnectedState);
control2.disconnectFromDevice();