9#include <QtCore/qoperatingsystemversion.h>
10#include <QtCore/qendian.h>
11#include <QtCore/qstring.h>
13#ifndef QT_IOS_BLUETOOTH
15#import <IOBluetooth/objc/IOBluetoothSDPUUID.h>
16#import <CoreFoundation/CoreFoundation.h>
17#import <CoreBluetooth/CBUUID.h>
38 if (address && address.length) {
39 NSString *
const fixed = [address stringByReplacingOccurrencesOfString:@
"-" withString:@
":"];
40 return QString::fromNSString(fixed);
46#ifndef QT_IOS_BLUETOOTH
49QBluetoothAddress
qt_address(
const BluetoothDeviceAddress *a)
53 const quint64 qAddress = a->data[5] |
54 qint64(a->data[4]) << 8 |
55 qint64(a->data[3]) << 16 |
56 qint64(a->data[2]) << 24 |
57 qint64(a->data[1]) << 32 |
58 qint64(a->data[0]) << 40;
59 return QBluetoothAddress(qAddress);
62 return QBluetoothAddress();
67 BluetoothDeviceAddress a = {};
68 if (!qAddress.isNull()) {
69 const quint64 val = qAddress.toUInt64();
70 a.data[0] = (val >> 40) & 0xff;
71 a.data[1] = (val >> 32) & 0xff;
72 a.data[2] = (val >> 24) & 0xff;
73 a.data[3] = (val >> 16) & 0xff;
74 a.data[4] = (val >> 8) & 0xff;
75 a.data[5] = val & 0xff;
83 const unsigned nBytes = 128 /
std::numeric_limits<
unsigned char>::digits;
84 const QUuid::Id128Bytes intVal(uuid.toBytes());
86 const ObjCStrongReference<IOBluetoothSDPUUID> iobtUUID([IOBluetoothSDPUUID uuidWithBytes:intVal.data
87 length:nBytes], RetainPolicy::doInitialRetain);
91QBluetoothUuid
qt_uuid(IOBluetoothSDPUUID *uuid)
93 QBluetoothUuid qtUuid;
94 if (!uuid || [uuid length] != 16)
98 QUuid::Id128Bytes uuidVal = {};
99 const quint8 *
const source =
static_cast<
const quint8 *>([uuid bytes]);
100 std::copy(source, source + 16, uuidVal.data);
101 return QBluetoothUuid(uuidVal);
107 case kIOReturnSuccess:
110 case kIOReturnNoMemory:
111 return QString::fromLatin1(
"memory allocation failed");
112 case kIOReturnNoResources:
113 return QString::fromLatin1(
"failed to obtain a resource");
115 return QString::fromLatin1(
"device is busy");
116 case kIOReturnStillOpen:
117 return QString::fromLatin1(
"device(s) still open");
121 return QString::fromLatin1(
"unknown error");
131 if (CFRunLoopGetMain() != CFRunLoopGetCurrent()) {
132 qCWarning(QT_BT_DARWIN) <<
"IOBluetooth works only on the main thread or a"
133 <<
"thread with a running CFRunLoop";
149 return QBluetoothUuid();
153 if (uuid.data.length == 2) {
156 const uchar *
const src =
static_cast<
const uchar *>(uuid.data.bytes);
157 return QBluetoothUuid(qFromBigEndian<quint16>(src));
158 }
else if (uuid.data.length == 4) {
159 const uchar *
const src =
static_cast<
const uchar *>(uuid.data.bytes);
160 return QBluetoothUuid(qFromBigEndian<quint32>(src));
161 }
else if (uuid.data.length == 16) {
162 QUuid::Id128Bytes qtUuidData = {};
163 const quint8 *
const source =
static_cast<
const quint8 *>(uuid.data.bytes);
164 std::copy(source, source + 16, qtUuidData.data);
166 return QBluetoothUuid(qtUuidData);
169 qCDebug(QT_BT_DARWIN) <<
"qt_uuid, invalid CBUUID, 2, 4, or 16 bytes expected, but got "
170 << uuid.data.length <<
" bytes length";
171 return QBluetoothUuid();
177 const auto asUInt16 = qToBigEndian(qtUuid.toUInt16(&ok));
178 const auto asUInt128 = qtUuid.toBytes();
180 const NSUInteger length = ok ?
sizeof asUInt16 :
sizeof asUInt128;
181 const void *bytes = &asUInt128;
185 NSData *uuidData = [NSData dataWithBytes:bytes length:length];
186 ObjCStrongReference<CBUUID> cbUuid([CBUUID UUIDWithData:uuidData], RetainPolicy::doInitialRetain);
192 const QBluetoothUuid qtUuid2(qt_uuid(cbUuid));
193 return qtUuid == qtUuid2;
198 return equal_uuids(qtUuid, cbUuid);
204 if (!data || !data.length)
207 value.resize(data.length);
208 const char *
const src =
static_cast<
const char *>(data.bytes);
209 std::copy(src, src + data.length, value.data());
214template<
class Integer>
218 value.resize(
sizeof n);
219 const char *
const src =
reinterpret_cast<
char *>(&n);
220 std::copy(src, src +
sizeof n, value.data());
231 NSData *
const utf8Data = [string dataUsingEncoding:NSUTF8StringEncoding];
233 return qt_bytearray(utf8Data);
258 if ([obj isKindOfClass:[NSData
class]]) {
259 return qt_bytearray(
static_cast<NSData *>(obj));
272ObjCStrongReference<NSData> data_from_bytearray(
const QByteArray & qtData)
275 return ObjCStrongReference<NSData>([[NSData alloc] init], RetainPolicy::noInitialRetain);
277 ObjCStrongReference<NSData> result([NSData dataWithBytes:qtData.constData() length:qtData.size()], RetainPolicy::doInitialRetain);
281ObjCStrongReference<NSMutableData> mutable_data_from_bytearray(
const QByteArray &qtData)
283 using MutableData = ObjCStrongReference<NSMutableData>;
286 return MutableData([[NSMutableData alloc] init], RetainPolicy::noInitialRetain);
288 MutableData result([[NSMutableData alloc] initWithLength:qtData.size()], RetainPolicy::noInitialRetain);
289 [result replaceBytesInRange:NSMakeRange(0, qtData.size())
290 withBytes:qtData.constData()];
302 queue = dispatch_queue_create(label, DISPATCH_QUEUE_SERIAL);
304 qCCritical(QT_BT_DARWIN) <<
"failed to create dispatch queue with label"
311 dispatch_release(queue);
319 dispatch_queue_t queue;
324dispatch_queue_t qt_LE_queue()
327 return leQueue.data();
#define QT_BT_MAC_AUTORELEASEPOOL
SerialDispatchQueue(const char *label)
dispatch_queue_t data() const
ObjCStrongReference< CBUUID > cb_uuid(const QBluetoothUuid &qtUuid)
const int defaultLEScanTimeoutMS
bool equal_uuids(const QBluetoothUuid &qtUuid, CBUUID *cbUuid)
QByteArray qt_bytearray(NSData *data)
QString qt_address(NSString *address)
QByteArray qt_bytearray(Integer n)
void qt_test_iobluetooth_runloop()
BluetoothDeviceAddress iobluetooth_address(const QBluetoothAddress &address)
QString qt_error_string(IOReturn errorCode)
QBluetoothAddress qt_address(const BluetoothDeviceAddress *address)
ObjCStrongReference< IOBluetoothSDPUUID > iobluetooth_uuid(const QBluetoothUuid &uuid)
QBluetoothUuid qt_uuid(IOBluetoothSDPUUID *uuid)
bool equal_uuids(CBUUID *cbUuid, const QBluetoothUuid &qtUuid)
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")