summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/qbluetoothserviceinfo_osx.mm
diff options
context:
space:
mode:
authorTimur Pocheptsov <Timur.Pocheptsov@digia.com>2014-09-30 17:29:15 +0200
committerTimur Pocheptsov <Timur.Pocheptsov@digia.com>2014-10-16 09:46:15 +0200
commite417b7036e35744daa1978cd236798e3ee1693c0 (patch)
tree3e86b6ce833e70efa75f8151302973a030338fb2 /src/bluetooth/qbluetoothserviceinfo_osx.mm
parent552bdb884b44fffde3075ee2016a8a5c04108b3c (diff)
QtBluetooth - device discovery test on OS X.
- Enable this auto test on OS X, requires a modification: 'stop' is synchronous and so cancelSpy.isEmpty() == false (the last QVERIFY fails. - Fix several problems with SDK versions (workarounds for non-existing methods in SDK < 10.9). - Change error handling: we set an error in a ctor _only_ if QBluetoothAddress parameter was not null (!isNull()) and we failed to find a local device with such an address. This is the only case documented/expected, all others _do_ _not_ set an error, even if a local adapter is off or does not exits. This fixes a failing (to integrate) auto-test. Change-Id: I9902211078330f296775f1c3249da166c19001a4 Reviewed-by: Alex Blasche <alexander.blasche@digia.com>
Diffstat (limited to 'src/bluetooth/qbluetoothserviceinfo_osx.mm')
-rw-r--r--src/bluetooth/qbluetoothserviceinfo_osx.mm79
1 files changed, 53 insertions, 26 deletions
diff --git a/src/bluetooth/qbluetoothserviceinfo_osx.mm b/src/bluetooth/qbluetoothserviceinfo_osx.mm
index 2ab2c9f1..ae88b4e7 100644
--- a/src/bluetooth/qbluetoothserviceinfo_osx.mm
+++ b/src/bluetooth/qbluetoothserviceinfo_osx.mm
@@ -62,20 +62,23 @@ namespace {
// This is not in osxbtutility_p, since it's not required
// in general and just fixes the problem with SDK < 10.9,
// where we have to care about about IOBluetoothSDPServiceRecordRef.
-class ServiceRecordDeleter
+class ServiceRecordRefGuard
{
public:
- ServiceRecordDeleter(IOBluetoothSDPServiceRecordRef r)
+ ServiceRecordRefGuard(IOBluetoothSDPServiceRecordRef r)
: recordRef(r)
{
}
- ~ServiceRecordDeleter()
+ ~ServiceRecordRefGuard()
{
if (recordRef) // Requires non-NULL pointers.
CFRelease(recordRef);
}
+private:
IOBluetoothSDPServiceRecordRef recordRef;
+
+ Q_DISABLE_COPY(ServiceRecordRefGuard)
};
}
@@ -85,7 +88,6 @@ class QBluetoothServiceInfoPrivate
public:
typedef QBluetoothServiceInfo QSInfo;
QBluetoothServiceInfoPrivate(QBluetoothServiceInfo *q);
- ~QBluetoothServiceInfoPrivate();
bool registerService(const QBluetoothAddress &localAdapter = QBluetoothAddress());
@@ -105,20 +107,17 @@ private:
typedef OSXBluetooth::ObjCScopedPointer<IOBluetoothSDPServiceRecord> SDPRecord;
SDPRecord serviceRecord;
+ BluetoothSDPServiceRecordHandle serviceRecordHandle;
};
QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate(QBluetoothServiceInfo *q)
: q_ptr(q),
- registered(false)
+ registered(false),
+ serviceRecordHandle(0)
{
Q_ASSERT_X(q, "QBluetoothServiceInfoPrivate()", "invalid q_ptr (null)");
}
-QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate()
-{
- // TODO: should it unregister?
-}
-
bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &localAdapter)
{
Q_UNUSED(localAdapter)
@@ -129,8 +128,6 @@ bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &loca
Q_ASSERT_X(!serviceRecord, "QBluetoothServiceInfoPrivate::registerService()",
"not registered, but serviceRecord is not nil");
- // TODO: create a service description (as NSDictionary) and add to the
- // local SDP server via IOBluetoothSDPServiceRecord and its methods.
using namespace OSXBluetooth;
ObjCStrongReference<NSMutableDictionary>
@@ -143,56 +140,79 @@ bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &loca
}
SDPRecord newRecord;
-
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_NA)
newRecord.reset([[IOBluetoothSDPServiceRecord
publishedServiceRecordWithDictionary:serviceDict] retain]);
-
#else
IOBluetoothSDPServiceRecordRef recordRef = Q_NULLPTR;
// With ARC this will require a different cast?
const IOReturn status = IOBluetoothAddServiceDict((CFDictionaryRef)serviceDict.data(), &recordRef);
if (status != kIOReturnSuccess) {
qCWarning(QT_BT_OSX) << "QBluetoothServiceInfoPrivate::registerService(), "
- "failed to create register a service record";
+ "failed to register a service record";
return false;
}
- const ServiceRecordDeleter refGuard(recordRef);
+ const ServiceRecordRefGuard refGuard(recordRef);
newRecord.reset([[IOBluetoothSDPServiceRecord withSDPServiceRecordRef:recordRef] retain]);
- // It's weird, but ... it's not possible to release a record ref yet!
+ // It's weird, but ... it's not possible to release a record ref yet.
#endif
if (!newRecord) {
qCWarning(QT_BT_OSX) << "QBluetoothServiceInfoPrivate::registerService(), "
- "failed to create register a service record";
+ "failed to register a service record";
+ // In case of SDK < 10.9 it's not possible to remove a service record ...
+ // no way to obtain record handle yet.
+ return false;
+ }
+
+ BluetoothSDPServiceRecordHandle newRecordHandle = 0;
+ if ([newRecord getServiceRecordHandle:&newRecordHandle] != kIOReturnSuccess) {
+ qCWarning(QT_BT_OSX) << "QBluetoothServiceInfoPrivate::registerService(), "
+ "failed to register a service record";
+#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_NA)
+ [newRecord removeServiceRecord];
+#endif
+ // With SDK < 10.9 there is no way to unregister at this point ...
return false;
}
const QSInfo::Protocol type = q_ptr->socketProtocol();
quint16 realPort = 0;
QBluetoothServerPrivate *server = Q_NULLPTR;
+ bool configured = false;
if (type == QBluetoothServiceInfo::L2capProtocol) {
BluetoothL2CAPPSM psm = 0;
server = QBluetoothServerPrivate::registeredServer(q_ptr->protocolServiceMultiplexer(), type);
- if ([newRecord getL2CAPPSM:&psm] != kIOReturnSuccess) {
- [newRecord removeServiceRecord];
- return false;
+ if ([newRecord getL2CAPPSM:&psm] == kIOReturnSuccess) {
+ configured = true;
+ realPort = psm;
}
- realPort = psm;
} else if (type == QBluetoothServiceInfo::RfcommProtocol) {
BluetoothRFCOMMChannelID channelID = 0;
server = QBluetoothServerPrivate::registeredServer(q_ptr->serverChannel(), type);
- if ([newRecord getRFCOMMChannelID:&channelID] != kIOReturnSuccess) {
- [newRecord removeServiceRecord];
- return false;
+ if ([newRecord getRFCOMMChannelID:&channelID] == kIOReturnSuccess) {
+ configured = true;
+ realPort = channelID;
}
- realPort = channelID;
+ }
+
+ if (!configured) {
+#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_NA)
+ [newRecord removeServiceRecord];
+#else
+ IOBluetoothRemoveServiceWithRecordHandle(newRecordHandle);
+#endif
+ qCWarning(QT_BT_OSX) << "QBluetoothServiceInfoPrivate::registerService(), "
+ "failed to register a service record";
+ return false;
}
registered = true;
serviceRecord.reset(newRecord.take());
+ serviceRecordHandle = newRecordHandle;
+
if (server)
server->startListener(realPort);
@@ -212,7 +232,13 @@ bool QBluetoothServiceInfoPrivate::unregisterService()
Q_ASSERT_X(serviceRecord, "QBluetoothServiceInfoPrivate::unregisterService()",
"service registered, but serviceRecord is nil");
+#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_NA)
[serviceRecord removeServiceRecord];
+#else
+ // Assert on newRecordHandle? Is 0 a valid/invalid handle?
+ IOBluetoothRemoveServiceWithRecordHandle(serviceRecordHandle);
+#endif
+
serviceRecord.reset(nil);
const QSInfo::Protocol type = q_ptr->socketProtocol();
@@ -228,6 +254,7 @@ bool QBluetoothServiceInfoPrivate::unregisterService()
server->stopListener();
registered = false;
+ serviceRecordHandle = 0;
return true;
}