summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/bluetooth/qbluetoothservicediscoveryagent_osx.mm')
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_osx.mm416
1 files changed, 31 insertions, 385 deletions
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm b/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm
index bd9cc7f3..d8decae1 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_osx.mm
@@ -37,6 +37,7 @@
**
****************************************************************************/
+#include "qbluetoothservicediscoveryagent_p.h"
#include "qbluetoothservicediscoveryagent.h"
#include "qbluetoothdevicediscoveryagent.h"
#include "qbluetoothlocaldevice.h"
@@ -57,132 +58,41 @@
QT_BEGIN_NAMESPACE
-class QBluetoothServiceDiscoveryAgentPrivate : public QObject, public OSXBluetooth::SDPInquiryDelegate
-{
- friend class QBluetoothServiceDiscoveryAgent;
-public:
- enum DiscoveryState {
- Inactive,
- DeviceDiscovery,
- ServiceDiscovery,
- };
-
- QBluetoothServiceDiscoveryAgentPrivate(QBluetoothServiceDiscoveryAgent *qp,
- const QBluetoothAddress &localAddress);
-
- void startDeviceDiscovery();
- void stopDeviceDiscovery();
-
- void startServiceDiscovery();
- void stopServiceDiscovery();
-
- DiscoveryState discoveryState();
- void setDiscoveryMode(QBluetoothServiceDiscoveryAgent::DiscoveryMode m);
- QBluetoothServiceDiscoveryAgent::DiscoveryMode DiscoveryMode();
-
- void _q_deviceDiscovered(const QBluetoothDeviceInfo &info);
- void _q_deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error);
- void _q_deviceDiscoveryFinished();
-
-private:
- // SDPInquiryDelegate:
- void SDPInquiryFinished(IOBluetoothDevice *device) override;
- void SDPInquiryError(IOBluetoothDevice *device, IOReturn errorCode) override;
-
- void performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress);
- void setupDeviceDiscoveryAgent();
- bool isDuplicatedService(const QBluetoothServiceInfo &serviceInfo) const;
- void serviceDiscoveryFinished();
-
- bool serviceHasMathingUuid(const QBluetoothServiceInfo &serviceInfo) const;
-
- QBluetoothServiceDiscoveryAgent *q_ptr;
+namespace {
- QBluetoothServiceDiscoveryAgent::Error error;
- QString errorString;
+using DarwinBluetooth::RetainPolicy;
+using ObjCServiceInquiry = QT_MANGLE_NAMESPACE(OSXBTSDPInquiry);
- QList<QBluetoothDeviceInfo> discoveredDevices;
- QList<QBluetoothServiceInfo> discoveredServices;
- QList<QBluetoothUuid> uuidFilter;
-
- bool singleDevice;
- QBluetoothAddress deviceAddress;
- QBluetoothAddress localAdapterAddress;
-
- DiscoveryState state;
- QBluetoothServiceDiscoveryAgent::DiscoveryMode discoveryMode;
-
- QScopedPointer<QBluetoothDeviceDiscoveryAgent> deviceDiscoveryAgent;
- OSXBluetooth::ObjCScopedPointer<ObjCServiceInquiry> serviceInquiry;
-};
+}
QBluetoothServiceDiscoveryAgentPrivate::QBluetoothServiceDiscoveryAgentPrivate(
QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &localAddress) :
- q_ptr(qp),
+
error(QBluetoothServiceDiscoveryAgent::NoError),
- singleDevice(false),
- localAdapterAddress(localAddress),
+ m_deviceAdapterAddress(localAddress),
state(Inactive),
- discoveryMode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery)
-{
- serviceInquiry.reset([[ObjCServiceInquiry alloc] initWithDelegate:this]);
-}
+ mode(QBluetoothServiceDiscoveryAgent::MinimalDiscovery),
+ singleDevice(false),
+ q_ptr(qp)
-void QBluetoothServiceDiscoveryAgentPrivate::startDeviceDiscovery()
{
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- Q_ASSERT_X(state == Inactive, Q_FUNC_INFO, "invalid state");
- Q_ASSERT_X(error != QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError,
- Q_FUNC_INFO, "invalid bluetooth adapter");
-
- Q_ASSERT_X(deviceDiscoveryAgent.isNull(), "startDeviceDiscovery()",
- "discovery agent already exists");
-
- state = DeviceDiscovery;
-
- setupDeviceDiscoveryAgent();
- deviceDiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::ClassicMethod);
+ Q_ASSERT(q_ptr);
+ serviceInquiry.reset([[ObjCServiceInquiry alloc] initWithDelegate:this], RetainPolicy::noInitialRetain);
}
-void QBluetoothServiceDiscoveryAgentPrivate::stopDeviceDiscovery()
+QBluetoothServiceDiscoveryAgentPrivate::~QBluetoothServiceDiscoveryAgentPrivate()
{
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- Q_ASSERT_X(!deviceDiscoveryAgent.isNull(), Q_FUNC_INFO,
- "invalid device discovery agent (null)");
- Q_ASSERT_X(state == DeviceDiscovery, Q_FUNC_INFO, "invalid state");
-
- deviceDiscoveryAgent->stop();
- deviceDiscoveryAgent.reset(nullptr);
- state = Inactive;
-
- emit q_ptr->canceled();
}
-void QBluetoothServiceDiscoveryAgentPrivate::startServiceDiscovery()
+void QBluetoothServiceDiscoveryAgentPrivate::start(const QBluetoothAddress &deviceAddress)
{
- // Any of 'Inactive'/'DeviceDiscovery'/'ServiceDiscovery' states
- // are possible.
-
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- Q_ASSERT_X(error != QBluetoothServiceDiscoveryAgent::InvalidBluetoothAdapterError,
- Q_FUNC_INFO, "invalid bluetooth adapter");
-
- if (discoveredDevices.isEmpty()) {
- state = Inactive;
- emit q_ptr->finished();
- return;
- }
-
QT_BT_MAC_AUTORELEASEPOOL;
- state = ServiceDiscovery;
- const QBluetoothAddress &address(discoveredDevices.at(0).address());
-
- if (address.isNull()) {
+ if (deviceAddress.isNull()) {
// This can happen: LE scan works with CoreBluetooth, but CBPeripherals
// do not expose hardware addresses.
// Pop the current QBluetoothDeviceInfo and decide what to do next.
- return serviceDiscoveryFinished();
+ return _q_serviceDiscoveryFinished();
}
// Autoreleased object.
@@ -195,17 +105,18 @@ void QBluetoothServiceDiscoveryAgentPrivate::startServiceDiscovery()
emit q_ptr->error(error);
}
- return serviceDiscoveryFinished();
+ return _q_serviceDiscoveryFinished();
}
if (DiscoveryMode() == QBluetoothServiceDiscoveryAgent::MinimalDiscovery) {
- performMinimalServiceDiscovery(address);
+ performMinimalServiceDiscovery(deviceAddress);
} else {
IOReturn result = kIOReturnSuccess;
+ auto nativeInquiry = serviceInquiry.getAs<ObjCServiceInquiry>();
if (uuidFilter.size())
- result = [serviceInquiry performSDPQueryWithDevice:address filters:uuidFilter];
+ result = [nativeInquiry performSDPQueryWithDevice:deviceAddress filters:uuidFilter];
else
- result = [serviceInquiry performSDPQueryWithDevice:address];
+ result = [nativeInquiry performSDPQueryWithDevice:deviceAddress];
if (result != kIOReturnSuccess) {
// Failed immediately to perform an SDP inquiry on IOBluetoothDevice:
@@ -214,87 +125,21 @@ void QBluetoothServiceDiscoveryAgentPrivate::startServiceDiscovery()
}
}
-void QBluetoothServiceDiscoveryAgentPrivate::stopServiceDiscovery()
+void QBluetoothServiceDiscoveryAgentPrivate::stop()
{
- Q_ASSERT_X(state != Inactive, Q_FUNC_INFO, "invalid state");
Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
discoveredDevices.clear();
- state = Inactive;
// "Stops" immediately.
- [serviceInquiry stopSDPQuery];
+ [serviceInquiry.getAs<ObjCServiceInquiry>() stopSDPQuery];
emit q_ptr->canceled();
}
-QBluetoothServiceDiscoveryAgentPrivate::DiscoveryState
- QBluetoothServiceDiscoveryAgentPrivate::discoveryState()
-{
- return state;
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::setDiscoveryMode(
- QBluetoothServiceDiscoveryAgent::DiscoveryMode m)
-{
- discoveryMode = m;
-
-}
-
-QBluetoothServiceDiscoveryAgent::DiscoveryMode
- QBluetoothServiceDiscoveryAgentPrivate::DiscoveryMode()
-{
- return discoveryMode;
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscovered(const QBluetoothDeviceInfo &info)
-{
- // Look for duplicates, and cached entries
- for (int i = 0; i < discoveredDevices.count(); i++) {
- if (discoveredDevices.at(i).address() == info.address()) {
- discoveredDevices.removeAt(i);
- break;
- }
- }
-
- discoveredDevices.prepend(info);
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error)
-{
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
-
- error = QBluetoothServiceDiscoveryAgent::UnknownError;
- errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_UNKNOWN_ERROR);
-
- deviceDiscoveryAgent->stop();
- deviceDiscoveryAgent.reset(nullptr);
-
- state = QBluetoothServiceDiscoveryAgentPrivate::Inactive;
- emit q_ptr->error(error);
- emit q_ptr->finished();
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryFinished()
-{
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
-
- if (deviceDiscoveryAgent->error() != QBluetoothDeviceDiscoveryAgent::NoError) {
- //Forward the device discovery error
- error = static_cast<QBluetoothServiceDiscoveryAgent::Error>(deviceDiscoveryAgent->error());
- errorString = deviceDiscoveryAgent->errorString();
- deviceDiscoveryAgent.reset(nullptr);
- state = Inactive;
- emit q_ptr->error(error);
- emit q_ptr->finished();
- } else {
- deviceDiscoveryAgent.reset(nullptr);
- startServiceDiscovery();
- }
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryFinished(IOBluetoothDevice *device)
+void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryFinished(void *generic)
{
+ auto device = static_cast<IOBluetoothDevice *>(generic);
Q_ASSERT_X(device, Q_FUNC_INFO, "invalid IOBluetoothDevice (nil)");
if (state == Inactive)
@@ -323,10 +168,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryFinished(IOBluetoothDevic
}
}
- serviceDiscoveryFinished();
+ _q_serviceDiscoveryFinished();
}
-void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryError(IOBluetoothDevice *device, IOReturn errorCode)
+void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryError(void *device, IOReturn errorCode)
{
Q_UNUSED(device)
@@ -340,7 +185,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::SDPInquiryError(IOBluetoothDevice *
emit q_ptr->error(error);
}
- serviceDiscoveryFinished();
+ _q_serviceDiscoveryFinished();
}
void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(const QBluetoothAddress &deviceAddress)
@@ -371,7 +216,7 @@ void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(cons
if (!serviceInfo.isValid())
continue;
- if (!uuidFilter.isEmpty() && !serviceHasMathingUuid(serviceInfo))
+ if (!uuidFilter.isEmpty() && !serviceHasMatchingUuid(serviceInfo))
continue;
if (!isDuplicatedService(serviceInfo)) {
@@ -381,52 +226,10 @@ void QBluetoothServiceDiscoveryAgentPrivate::performMinimalServiceDiscovery(cons
}
}
- serviceDiscoveryFinished();
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::setupDeviceDiscoveryAgent()
-{
- Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
- Q_ASSERT_X(deviceDiscoveryAgent.isNull() || !deviceDiscoveryAgent->isActive(),
- Q_FUNC_INFO, "device discovery agent is active");
-
- deviceDiscoveryAgent.reset(new QBluetoothDeviceDiscoveryAgent(localAdapterAddress, q_ptr));
-
- QObject::connect(deviceDiscoveryAgent.data(), &QBluetoothDeviceDiscoveryAgent::deviceDiscovered,
- this, &QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscovered);
- QObject::connect(deviceDiscoveryAgent.data(), &QBluetoothDeviceDiscoveryAgent::finished,
- this, &QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryFinished);
- QObject::connect(deviceDiscoveryAgent.data(),
- QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error),
- this,
- &QBluetoothServiceDiscoveryAgentPrivate::_q_deviceDiscoveryError);
-}
-
-bool QBluetoothServiceDiscoveryAgentPrivate::isDuplicatedService(const QBluetoothServiceInfo &serviceInfo) const
-{
- //check the service is not already part of our known list
- for (int j = 0; j < discoveredServices.count(); j++) {
- const QBluetoothServiceInfo &info = discoveredServices.at(j);
- if (info.device() == serviceInfo.device()
- && info.serviceClassUuids() == serviceInfo.serviceClassUuids()
- && info.serviceUuid() == serviceInfo.serviceUuid()) {
- return true;
- }
- }
-
- return false;
-}
-
-void QBluetoothServiceDiscoveryAgentPrivate::serviceDiscoveryFinished()
-{
- if (!discoveredDevices.isEmpty())
- discoveredDevices.removeFirst();
-
- if (state == ServiceDiscovery)
- startServiceDiscovery();
+ _q_serviceDiscoveryFinished();
}
-bool QBluetoothServiceDiscoveryAgentPrivate::serviceHasMathingUuid(const QBluetoothServiceInfo &serviceInfo) const
+bool QBluetoothServiceDiscoveryAgentPrivate::serviceHasMatchingUuid(const QBluetoothServiceInfo &serviceInfo) const
{
for (const auto &requestedUuid : uuidFilter) {
if (serviceInfo.serviceUuid() == requestedUuid)
@@ -437,161 +240,4 @@ bool QBluetoothServiceDiscoveryAgentPrivate::serviceHasMathingUuid(const QBlueto
return false;
}
-QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(QObject *parent)
-: QObject(parent),
- d_ptr(new QBluetoothServiceDiscoveryAgentPrivate(this, QBluetoothAddress()))
-{
-}
-
-QBluetoothServiceDiscoveryAgent::QBluetoothServiceDiscoveryAgent(const QBluetoothAddress &deviceAdapter, QObject *parent)
-: QObject(parent),
- d_ptr(new QBluetoothServiceDiscoveryAgentPrivate(this, deviceAdapter))
-{
- if (!deviceAdapter.isNull()) {
- const QList<QBluetoothHostInfo> localDevices = QBluetoothLocalDevice::allDevices();
- for (const QBluetoothHostInfo &hostInfo : localDevices) {
- if (hostInfo.address() == deviceAdapter)
- return;
- }
- d_ptr->error = InvalidBluetoothAdapterError;
- d_ptr->errorString = QCoreApplication::translate(SERVICE_DISCOVERY, SD_INVALID_ADDRESS);
- }
-}
-
-QBluetoothServiceDiscoveryAgent::~QBluetoothServiceDiscoveryAgent()
-{
- delete d_ptr;
-}
-
-QList<QBluetoothServiceInfo> QBluetoothServiceDiscoveryAgent::discoveredServices() const
-{
- return d_ptr->discoveredServices;
-}
-
-/*
- Sets the UUID filter to \a uuids. Only services matching the UUIDs in \a uuids will be
- returned.
-
- An empty UUID list is equivalent to a list containing only QBluetoothUuid::PublicBrowseGroup.
-
- \sa uuidFilter()
-*/
-void QBluetoothServiceDiscoveryAgent::setUuidFilter(const QList<QBluetoothUuid> &uuids)
-{
- d_ptr->uuidFilter = uuids;
-}
-
-/*
- This is an overloaded member function, provided for convenience.
-
- Sets the UUID filter to a list containing the single element \a uuid.
-
- \sa uuidFilter()
-*/
-void QBluetoothServiceDiscoveryAgent::setUuidFilter(const QBluetoothUuid &uuid)
-{
- d_ptr->uuidFilter.clear();
- d_ptr->uuidFilter.append(uuid);
-}
-
-/*
- Returns the UUID filter.
-
- \sa setUuidFilter()
-*/
-QList<QBluetoothUuid> QBluetoothServiceDiscoveryAgent::uuidFilter() const
-{
- return d_ptr->uuidFilter;
-}
-
-/*
- Sets the remote device address to \a address. If \a address is default constructed,
- services will be discovered on all contactable Bluetooth devices. A new remote
- address can only be set while there is no service discovery in progress; otherwise
- this function returns false.
-
- \sa remoteAddress()
-*/
-bool QBluetoothServiceDiscoveryAgent::setRemoteAddress(const QBluetoothAddress &address)
-{
- if (isActive())
- return false;
-
- if (!address.isNull())
- d_ptr->singleDevice = true;
-
- d_ptr->deviceAddress = address;
- return true;
-}
-
-QBluetoothAddress QBluetoothServiceDiscoveryAgent::remoteAddress() const
-{
- if (d_ptr->singleDevice)
- return d_ptr->deviceAddress;
-
- return QBluetoothAddress();
-}
-
-void QBluetoothServiceDiscoveryAgent::start(DiscoveryMode mode)
-{
- OSXBluetooth::qt_test_iobluetooth_runloop();
-
- if (d_ptr->discoveryState() == QBluetoothServiceDiscoveryAgentPrivate::Inactive
- && d_ptr->error != InvalidBluetoothAdapterError)
- {
- d_ptr->setDiscoveryMode(mode);
- if (d_ptr->deviceAddress.isNull()) {
- d_ptr->startDeviceDiscovery();
- } else {
- d_ptr->discoveredDevices.append(QBluetoothDeviceInfo(d_ptr->deviceAddress, QString(), 0));
- d_ptr->startServiceDiscovery();
- }
- }
-}
-
-void QBluetoothServiceDiscoveryAgent::stop()
-{
- if (d_ptr->error == InvalidBluetoothAdapterError || !isActive())
- return;
-
- switch (d_ptr->discoveryState()) {
- case QBluetoothServiceDiscoveryAgentPrivate::DeviceDiscovery:
- d_ptr->stopDeviceDiscovery();
- break;
- case QBluetoothServiceDiscoveryAgentPrivate::ServiceDiscovery:
- d_ptr->stopServiceDiscovery();
- default:;
- }
-
- d_ptr->discoveredDevices.clear();
-}
-
-void QBluetoothServiceDiscoveryAgent::clear()
-{
- // Don't clear the list while the search is ongoing
- if (isActive())
- return;
-
- d_ptr->discoveredDevices.clear();
- d_ptr->discoveredServices.clear();
- d_ptr->uuidFilter.clear();
-}
-
-bool QBluetoothServiceDiscoveryAgent::isActive() const
-{
- return d_ptr->state != QBluetoothServiceDiscoveryAgentPrivate::Inactive;
-}
-
-QBluetoothServiceDiscoveryAgent::Error QBluetoothServiceDiscoveryAgent::error() const
-{
- return d_ptr->error;
-}
-
-QString QBluetoothServiceDiscoveryAgent::errorString() const
-{
- return d_ptr->errorString;
-}
-
-#include "moc_qbluetoothservicediscoveryagent.cpp"
-
QT_END_NAMESPACE