diff options
author | Timur Pocheptsov <Timur.Pocheptsov@digia.com> | 2014-09-30 17:29:15 +0200 |
---|---|---|
committer | Timur Pocheptsov <Timur.Pocheptsov@digia.com> | 2014-10-16 09:46:15 +0200 |
commit | e417b7036e35744daa1978cd236798e3ee1693c0 (patch) | |
tree | 3e86b6ce833e70efa75f8151302973a030338fb2 /src/bluetooth/qbluetoothserviceinfo_osx.mm | |
parent | 552bdb884b44fffde3075ee2016a8a5c04108b3c (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.mm | 79 |
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; } |