10#include <QtCore/qoperatingsystemversion.h>
11#include <QtCore/qvariant.h>
12#include <QtCore/qstring.h>
13#include <QtCore/qtimer.h>
23const int basebandConnectTimeoutMS = 20000;
25QBluetoothUuid sdp_element_to_uuid(IOBluetoothSDPDataElement *element)
29 if (!element || [element getTypeDescriptor] != kBluetoothSDPDataElementTypeUUID)
32 return qt_uuid([[element getUUIDValue] getUUIDWithLength:16]);
41 return sdp_element_to_uuid([
record getAttributeDataElement:kBluetoothSDPAttributeIdentifierServiceID]);
50 IOBluetoothSDPDataElement *
const idList = [
record getAttributeDataElement:kBluetoothSDPAttributeIdentifierServiceClassIDList];
57 if ([idList getTypeDescriptor] == kBluetoothSDPDataElementTypeDataElementSequence)
58 arr = [idList getArrayValue];
59 else if ([idList getTypeDescriptor] == kBluetoothSDPDataElementTypeUUID)
65 for (IOBluetoothSDPDataElement *dataElement
in arr) {
66 const auto qtUuid = sdp_element_to_uuid(dataElement);
80 for (
const auto &uuid : uuids) {
99 const BluetoothSDPDataElementTypeDescriptor typeDescriptor = [dataElement getTypeDescriptor];
101 switch (typeDescriptor) {
102 case kBluetoothSDPDataElementTypeNil:
104 case kBluetoothSDPDataElementTypeUnsignedInt:
105 return [[dataElement getNumberValue] unsignedIntValue];
106 case kBluetoothSDPDataElementTypeSignedInt:
107 return [[dataElement getNumberValue] intValue];
108 case kBluetoothSDPDataElementTypeUUID:
110 case kBluetoothSDPDataElementTypeString:
111 case kBluetoothSDPDataElementTypeURL:
112 return QString::fromNSString([dataElement getStringValue]);
113 case kBluetoothSDPDataElementTypeBoolean:
114 return [[dataElement getNumberValue] boolValue];
115 case kBluetoothSDPDataElementTypeDataElementSequence:
116 case kBluetoothSDPDataElementTypeDataElementAlternative:
119 NSArray *
const arr = [dataElement getArrayValue];
120 for (IOBluetoothSDPDataElement *element
in arr)
139 NSDictionary *
const attributes =
record.attributes;
140 NSEnumerator *
const keys = attributes.keyEnumerator;
142 const quint16 attributeID = [
key unsignedShortValue];
143 IOBluetoothSDPDataElement *
const element = [attributes objectForKey:
key];
149 if (!serviceUuid.
isNull())
153 const auto sequence = service_class_ID_list_to_sequence(uuids);
168 NSArray *
const records =
device.services;
169 for (IOBluetoothSDPServiceRecord *
record in records) {
205 delegate = aDelegate;
223 return [
self performSDPQueryWithDevice:address filters:emptyFilter];
226- (
void)interruptSDPQuery
234 qCDebug(QT_BT_DARWIN) <<
"couldn't connect to device" << [device nameOrAddress]
235 <<
", ending SDP inquiry.";
240 [device closeConnection];
242 delegate->SDPInquiryError(
device, kIOReturnTimeout);
252 qCDebug(QT_BT_DARWIN) <<
"Starting and SDP inquiry for address:" <<
address;
259 && qtFilters.size()) {
260 array.reset([[NSMutableArray alloc]
init], RetainPolicy::noInitialRetain);
262 qCCritical(QT_BT_DARWIN) <<
"failed to allocate an uuid filter";
263 return kIOReturnError;
269 [array addObject:uuid];
273 qCCritical(QT_BT_DARWIN) <<
"failed to create an uuid filter";
274 return kIOReturnError;
281 qCCritical(QT_BT_DARWIN) <<
"failed to create an IOBluetoothDevice object";
282 return kIOReturnError;
284 qCDebug(QT_BT_DARWIN) <<
"Device" << [device nameOrAddress] <<
"connected:"
285 << bool([
device isConnected]) <<
"paired:" << bool([
device isPaired]);
287 IOReturn
result = kIOReturnSuccess;
298 if (![
device isConnected]) {
299 qCDebug(QT_BT_DARWIN) <<
"Device" << [device nameOrAddress]
300 <<
"is not connected, connecting it first";
301 result = [device openConnection:self];
307 if (![
device isConnected]) {
308 qCDebug(QT_BT_DARWIN) <<
"Starting connection monitor for device"
309 << [device nameOrAddress] <<
"with timeout limit of"
310 << basebandConnectTimeoutMS/1000 <<
"seconds.";
316 qCDebug(QT_BT_DARWIN) <<
"Connection monitor timeout for device:"
317 << [device nameOrAddress]
318 <<
", connected:" << bool([device isConnected]);
321 if ([device isConnected])
322 [self connectionComplete:device status:kIOReturnSuccess];
324 [self interruptSDPQuery];
331 result = [device performSDPQuery:self];
333 if (
result != kIOReturnSuccess) {
334 qCCritical(QT_BT_DARWIN,
"failed to start an SDP query");
343 if (qtFilters.size())
344 result = [device performSDPQuery:self uuids:array];
346 result = [device performSDPQuery:self];
348 if (
result != kIOReturnSuccess) {
349 qCCritical(QT_BT_DARWIN) <<
"failed to start an SDP query";
358- (
void)connectionComplete:(IOBluetoothDevice *)aDevice status:(IOReturn)status
360 qCDebug(QT_BT_DARWIN) <<
"connectionComplete for device" << [aDevice nameOrAddress]
361 <<
"with status:" << status;
372 if (status == kIOReturnSuccess)
373 status = [aDevice performSDPQuery:self];
375 if (status != kIOReturnSuccess) {
377 qCWarning(QT_BT_DARWIN,
"failed to open connection or start an SDP query");
379 delegate->SDPInquiryError(aDevice, status);
393- (
void)sdpQueryComplete:(IOBluetoothDevice *)aDevice status:(IOReturn)status
395 qCDebug(QT_BT_DARWIN) <<
"sdpQueryComplete for device:" << [aDevice nameOrAddress]
396 <<
"with status:" << status;
411 qCDebug(QT_BT_DARWIN) <<
"Closing the connection established for SDP inquiry.";
413 [device closeConnection];
416 if (status != kIOReturnSuccess)
417 delegate->SDPInquiryError(aDevice, status);
419 delegate->SDPInquiryFinished(aDevice);
IOBluetoothDevice * device
std::unique_ptr< QTimer > connectionWatchdog
ObjCScopedPointer< IOBluetoothDevice > device
#define QT_BT_MAC_AUTORELEASEPOOL
void setServiceUuid(const QBluetoothUuid &uuid)
This is a convenience function.
void setAttribute(quint16 attributeId, const QVariant &value)
Sets the attribute identified by attributeId to value.
qsizetype size() const noexcept
bool isEmpty() const noexcept
void push_back(parameter_type t)
void append(parameter_type t)
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static QOperatingSystemVersion current()
[0]
static constexpr QOperatingSystemVersionBase MacOSBigSur
\variable QOperatingSystemVersion::MacOSBigSur
void timeout(QPrivateSignal)
This signal is emitted when the timer times out.
bool isNull() const noexcept
Returns true if this is the null UUID {00000000-0000-0000-0000-000000000000}; otherwise returns false...
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
QList< QBluetoothUuid > extract_services_uuids(IOBluetoothDevice *device)
void extract_service_record(IOBluetoothSDPServiceRecord *record, QBluetoothServiceInfo &serviceInfo)
BluetoothDeviceAddress iobluetooth_address(const QBluetoothAddress &qAddress)
QBluetoothUuid qt_uuid(NSUUID *nsUuid)
ObjCStrongReference< IOBluetoothSDPUUID > iobluetooth_uuid(const QBluetoothUuid &uuid)
QVariant extract_attribute_value(IOBluetoothSDPDataElement *dataElement)
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
#define qCCritical(category,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
GLenum GLenum GLsizei count
GLuint GLuint64EXT address
#define Q_ASSERT_X(cond, x, msg)
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
QT_END_NAMESPACE typedef QT_PREPEND_NAMESPACE(quintptr) WId