summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimur Pocheptsov <timur.pocheptsov@qt.io>2019-04-26 14:18:26 +0200
committerTimur Pocheptsov <timur.pocheptsov@qt.io>2019-06-14 14:21:53 +0200
commit722fde4664b8b3f5f661e37d212c32ba0fb2bbad (patch)
treebc00af5f01f15ed0b74c2d8a9cf2c93405eef6f7
parent50b589b85f1caa68846316e8b3dbe4f8c416775b (diff)
De-duplicate device discovery code (Darwin)
- use the shared *._p.h file/class declaration for the private class - use the shared *.cpp with the public class implementation - get rid of *_ios.mm - iOS/tvOS/watchOS specific implementation and use the shared (by macOS, iOS, tvOS, watchOS) *_darwin.mm source. - get rid of somewhat weird 'isValid' in the private class, it is is not taken care of in the public API anyway and today its whole concept/usage looks (quite) buggy to me. I only have to check that the default controller is not nil and has the state 'ON'. Task-number: QTBUG-75348 Change-Id: I5383e4f8df02ac12f069c2f59e252cb8a200800b Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
-rw-r--r--src/bluetooth/bluetooth.pro6
-rw-r--r--src/bluetooth/osx/btdelegates.cpp4
-rw-r--r--src/bluetooth/osx/btdelegates_p.h16
-rw-r--r--src/bluetooth/osx/btraii_p.h5
-rw-r--r--src/bluetooth/osx/osxbt.pri21
-rw-r--r--src/bluetooth/osx/osxbtdeviceinquiry.mm24
-rw-r--r--src/bluetooth/osx/osxbtdeviceinquiry_p.h24
-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
10 files changed, 184 insertions, 764 deletions
diff --git a/src/bluetooth/bluetooth.pro b/src/bluetooth/bluetooth.pro
index 2bcdee12..71c8e6ed 100644
--- a/src/bluetooth/bluetooth.pro
+++ b/src/bluetooth/bluetooth.pro
@@ -162,7 +162,7 @@ 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 \
@@ -177,7 +177,6 @@ qtConfig(bluez) {
qbluetoothtransferreply_osx_p.h \
qlowenergycontroller_osx_p.h
- SOURCES -= qbluetoothdevicediscoveryagent.cpp
SOURCES -= qbluetoothserviceinfo.cpp
SOURCES -= qbluetoothservicediscoveryagent.cpp
SOURCES -= qbluetoothsocket.cpp
@@ -192,7 +191,7 @@ qtConfig(bluez) {
LIBS_PRIVATE += -framework Foundation -framework CoreBluetooth
OBJECTIVE_SOURCES += \
- qbluetoothdevicediscoveryagent_ios.mm \
+ qbluetoothdevicediscoveryagent_darwin.mm \
qlowenergycontroller_osx.mm \
qlowenergyservice_osx.mm
@@ -208,7 +207,6 @@ qtConfig(bluez) {
qbluetoothsocket_dummy.cpp \
qbluetoothserver_p.cpp
- SOURCES -= qbluetoothdevicediscoveryagent.cpp
SOURCES -= qlowenergyservice.cpp
SOURCES -= qlowenergycontroller.cpp
SOURCES -= qlowenergycontrollerbase.cpp
diff --git a/src/bluetooth/osx/btdelegates.cpp b/src/bluetooth/osx/btdelegates.cpp
index c86516f9..531ca1df 100644
--- a/src/bluetooth/osx/btdelegates.cpp
+++ b/src/bluetooth/osx/btdelegates.cpp
@@ -39,6 +39,8 @@
#include "btdelegates_p.h"
+#if defined(Q_OS_MACOS)
+
QT_BEGIN_NAMESPACE
namespace DarwinBluetooth {
@@ -70,3 +72,5 @@ SocketListener::~SocketListener()
} // namespace DarwinBluetooth
QT_END_NAMESPACE
+
+#endif
diff --git a/src/bluetooth/osx/btdelegates_p.h b/src/bluetooth/osx/btdelegates_p.h
index cb29b87e..11fbcc28 100644
--- a/src/bluetooth/osx/btdelegates_p.h
+++ b/src/bluetooth/osx/btdelegates_p.h
@@ -58,9 +58,9 @@
#include <QtCore/qsharedpointer.h>
#include <QtCore/qglobal.h>
-#if defined(Q_OS_MACOS) || defined(Q_OS_IOS)
+#if defined(Q_OS_MACOS)
+
#include <IOKit/IOReturn.h>
-#endif
#include <cstdint>
@@ -72,8 +72,6 @@ class QByteArray;
namespace DarwinBluetooth {
-#if defined(Q_OS_MACOS)
-
class DeviceInquiryDelegate
{
public:
@@ -81,7 +79,7 @@ public:
virtual void inquiryFinished() = 0;
virtual void error(IOReturn error) = 0;
- virtual void deviceFound(void *ioBluetoothDevice) = 0;
+ virtual void classicDeviceFound(void *ioBluetoothDevice) = 0;
};
class PairingDelegate
@@ -141,15 +139,11 @@ public:
virtual void openNotifyL2CAP(void *l2capChannel) = 0;
};
-#else
-
-#error "This header is only for macOS (Bluetooth Classic only)"
-
-#endif // Q_OS_MACOS
-
} // namespace DarwinBluetooth
QT_END_NAMESPACE
+#endif // Q_OS_MACOS
+
#endif // DARWINBTDELEGATES_P_H
diff --git a/src/bluetooth/osx/btraii_p.h b/src/bluetooth/osx/btraii_p.h
index b64defb6..6053d63b 100644
--- a/src/bluetooth/osx/btraii_p.h
+++ b/src/bluetooth/osx/btraii_p.h
@@ -107,6 +107,11 @@ public:
return static_cast<ObjCType *>(objCInstance);
}
+ operator bool() const
+ {
+ return !!objCInstance;
+ }
+
private:
void *objCInstance = nullptr;
};
diff --git a/src/bluetooth/osx/osxbt.pri b/src/bluetooth/osx/osxbt.pri
index ae6111ee..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) {
@@ -21,9 +28,7 @@ CONFIG(osx) {
osx/osxbluetooth_p.h \
osx/osxbtcentralmanager_p.h \
osx/osxbtnotifier_p.h \
- osx/osxbtperipheralmanager_p.h \
- osx/btraii_p.h \
- osx/btdelegates_p.h
+ osx/osxbtperipheralmanager_p.h
OBJECTIVE_SOURCES += osx/osxbtutility.mm \
osx/osxbtdevicepair.mm \
@@ -38,9 +43,7 @@ CONFIG(osx) {
osx/osxbtobexsession.mm \
osx/osxbtledeviceinquiry.mm \
osx/osxbtcentralmanager.mm \
- osx/osxbtperipheralmanager.mm \
- osx/btraii.mm
- SOURCES += osx/btdelegates.cpp
+ osx/osxbtperipheralmanager.mm
} else {
PRIVATE_HEADERS += osx/osxbtutility_p.h \
osx/osxbtledeviceinquiry_p.h \
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/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;