8#include "darwin/btsdpinquiry_p.h"
10#include "darwin/btutility_p.h"
11#include "darwin/uistrings_p.h"
13#include <QtCore/qoperatingsystemversion.h>
14#include <QtCore/qcoreapplication.h>
15#include <QtCore/qloggingcategory.h>
16#include <QtCore/qstring.h>
17#include <QtCore/qglobal.h>
18#include <QtCore/qdebug.h>
19#include <QtCore/qlist.h>
21#include <Foundation/Foundation.h>
23#include <IOBluetooth/IOBluetooth.h>
34 QBluetoothServiceDiscoveryAgent *qp,
const QBluetoothAddress &localAddress) :
45 serviceInquiry.reset([[DarwinBTSDPInquiry alloc] initWithDelegate:
this], RetainPolicy::noInitialRetain);
56 if (deviceAddress.isNull()) {
64 IOBluetoothHostController *
const hc = [IOBluetoothHostController defaultController];
65 if (![hc powerState]) {
66 discoveredDevices.clear();
68 error = QBluetoothServiceDiscoveryAgent::PoweredOffError;
69 errorString = QCoreApplication::translate(SERVICE_DISCOVERY, SD_LOCAL_DEV_OFF);
70 emit q_ptr->errorOccurred(error);
76 if (DiscoveryMode() == QBluetoothServiceDiscoveryAgent::MinimalDiscovery) {
77 performMinimalServiceDiscovery(deviceAddress);
79 IOReturn result = kIOReturnSuccess;
80 auto nativeInquiry = serviceInquiry.getAs<DarwinBTSDPInquiry>();
81 if (uuidFilter.size())
82 result = [nativeInquiry performSDPQueryWithDevice:deviceAddress filters:uuidFilter];
84 result = [nativeInquiry performSDPQueryWithDevice:deviceAddress];
86 if (result != kIOReturnSuccess) {
88 SDPInquiryError(nil, result);
95 Q_ASSERT_X(q_ptr, Q_FUNC_INFO,
"invalid q_ptr (null)");
97 discoveredDevices.clear();
100 [serviceInquiry.getAs<DarwinBTSDPInquiry>() stopSDPQuery];
102 emit q_ptr->canceled();
107 auto device =
static_cast<IOBluetoothDevice *>(generic);
108 Q_ASSERT_X(device, Q_FUNC_INFO,
"invalid IOBluetoothDevice (nil)");
110 if (state == Inactive)
115 NSArray *
const records = device.services;
116 qCDebug(QT_BT_DARWIN) <<
"SDP finished for device" << [device nameOrAddress]
117 <<
", services found:" << [records count];
118 for (IOBluetoothSDPServiceRecord *record in records) {
119 QBluetoothServiceInfo serviceInfo;
120 Q_ASSERT_X(discoveredDevices.size() >= 1, Q_FUNC_INFO,
"invalid number of devices");
122 qCDebug(QT_BT_DARWIN) <<
"Processing service" << [record getServiceName];
123 serviceInfo.setDevice(discoveredDevices.at(0));
124 DarwinBluetooth::extract_service_record(record, serviceInfo);
126 if (!serviceInfo.isValid()) {
127 qCDebug(QT_BT_DARWIN) <<
"Discarding invalid service";
131 if (QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSBigSur
132 && uuidFilter.size()) {
133 const auto &serviceId = serviceInfo.serviceUuid();
134 bool match = !serviceId.isNull() && uuidFilter.contains(serviceId);
136 const auto &classUuids = serviceInfo.serviceClassUuids();
137 for (
const auto &uuid : classUuids) {
138 if (uuidFilter.contains(uuid)) {
149 if (!isDuplicatedService(serviceInfo)) {
150 discoveredServices.append(serviceInfo);
151 emit q_ptr->serviceDiscovered(serviceInfo);
154 if (state == Inactive)
166 qCWarning(QT_BT_DARWIN) <<
"inquiry failed with IOKit code:" <<
int(errorCode);
168 discoveredDevices.clear();
171 error = QBluetoothServiceDiscoveryAgent::UnknownError;
172 errorString = QCoreApplication::translate(DEV_DISCOVERY, DD_UNKNOWN_ERROR);
173 emit q_ptr->errorOccurred(error);
181 Q_ASSERT_X(!deviceAddress.isNull(), Q_FUNC_INFO,
"invalid device address");
185 const BluetoothDeviceAddress iobtAddress = DarwinBluetooth::iobluetooth_address(deviceAddress);
186 IOBluetoothDevice *
const device = [IOBluetoothDevice deviceWithAddress:&iobtAddress];
187 if (!device || !device.services) {
189 error = QBluetoothServiceDiscoveryAgent::UnknownError;
190 errorString = QCoreApplication::translate(SERVICE_DISCOVERY, SD_MINIMAL_FAILED);
191 emit q_ptr->errorOccurred(error);
195 NSArray *
const records = device.services;
196 for (IOBluetoothSDPServiceRecord *record in records) {
197 QBluetoothServiceInfo serviceInfo;
198 Q_ASSERT_X(discoveredDevices.size() >= 1, Q_FUNC_INFO,
199 "invalid number of devices");
201 serviceInfo.setDevice(discoveredDevices.at(0));
202 DarwinBluetooth::extract_service_record(record, serviceInfo);
204 if (!serviceInfo.isValid())
207 if (!uuidFilter.isEmpty() && !serviceHasMatchingUuid(serviceInfo))
210 if (!isDuplicatedService(serviceInfo)) {
211 discoveredServices.append(serviceInfo);
212 emit q_ptr->serviceDiscovered(serviceInfo);
222 for (
const auto &requestedUuid : uuidFilter) {
223 if (serviceInfo.serviceUuid() == requestedUuid)
225 if (serviceInfo.serviceClassUuids().contains(requestedUuid))
#define QT_BT_MAC_AUTORELEASEPOOL
~QBluetoothServiceDiscoveryAgentPrivate()
void _q_serviceDiscoveryFinished()
QBluetoothServiceDiscoveryAgentPrivate(QBluetoothServiceDiscoveryAgent *qp, const QBluetoothAddress &deviceAdapter)