diff options
author | Timur Pocheptsov <Timur.Pocheptsov@digia.com> | 2014-09-23 17:18:05 +0200 |
---|---|---|
committer | Timur Pocheptsov <Timur.Pocheptsov@digia.com> | 2014-09-26 18:19:54 +0200 |
commit | d66c466a135e4bebc293256f6ca361b287fd9bdb (patch) | |
tree | 503ba3d58787adfcc6dca6b3cab16b47bd0c32ae /src/bluetooth/qbluetoothserviceinfo_osx.mm | |
parent | d1d77c8210ecf7a89a81dad69d21b91e06bf129e (diff) |
Port QBluetoothServer to OS X.
Implement QBluetoothServer using IOBluetooth framework.
- Add empty (for now) implementation + modify .pro file.
- Add a 'socket listener'. Actually, there are no sockets,
no 'listen' but I still have to emulate this to make a server work.
- Implement (to some degree) QBluetoothServer::listen member functions:
on OS X QBluetoothServer::listen(address, port) does not really create
a listening socket, it just checks that this port is not busy yet
(IOBluetooth can either listen on a port you provide, or can
listen on any port, but it can not select some port and listen on it.
Only after service registered (with 'invalid' port first) - we have a real
channelID or PSM.
- Server port - either a "fake" port assigned by QBluetoothServer::listen,
or a real port as registered by IOBluetooth.
- Update a dependency.
- Implement nextPendingConnection.
- Implement fake server ports (something similar to Android version), but
on OS X these fake ports can later be replaced with real ports.
- Service info updates PSM/ChannelID with a real port and also starts a listener.
- Unregister a server (dtor, close, etc.)
- Do not update a 'fake' port with a real one: it can happen, that a real port
is already taken by some 'fake' port and this will break the whole idea of
fake ports. Let them be always fake, the real is required only when starting
a 'listener'.
- With 'fake' server ports '0' is not valid anymore (use serverPort() instead).
Change-Id: I44537a35891c6806e58ec874a18bd938d4b41c53
Reviewed-by: Alex Blasche <alexander.blasche@digia.com>
Diffstat (limited to 'src/bluetooth/qbluetoothserviceinfo_osx.mm')
-rw-r--r-- | src/bluetooth/qbluetoothserviceinfo_osx.mm | 72 |
1 files changed, 39 insertions, 33 deletions
diff --git a/src/bluetooth/qbluetoothserviceinfo_osx.mm b/src/bluetooth/qbluetoothserviceinfo_osx.mm index 621aab35..61f68f7f 100644 --- a/src/bluetooth/qbluetoothserviceinfo_osx.mm +++ b/src/bluetooth/qbluetoothserviceinfo_osx.mm @@ -40,6 +40,7 @@ ****************************************************************************/ #include "osx/osxbtservicerecord_p.h" +#include "qbluetoothserver_osx_p.h" #include "qbluetoothserviceinfo.h" #include "qbluetoothdeviceinfo.h" #include "osx/osxbtutility_p.h" @@ -47,6 +48,7 @@ #include <QtCore/qloggingcategory.h> #include <QtCore/qvariant.h> #include <QtCore/qglobal.h> +#include <QtCore/qmutex.h> #include <QtCore/qmap.h> #include <QtCore/qurl.h> @@ -58,6 +60,7 @@ QT_BEGIN_NAMESPACE class QBluetoothServiceInfoPrivate { public: + typedef QBluetoothServiceInfo QSInfo; QBluetoothServiceInfoPrivate(QBluetoothServiceInfo *q); ~QBluetoothServiceInfoPrivate(); @@ -116,54 +119,45 @@ bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &loca return false; } - serviceRecord.reset([[IOBluetoothSDPServiceRecord + SDPRecord newRecord([[IOBluetoothSDPServiceRecord publishedServiceRecordWithDictionary:serviceDict] retain]); - if (!serviceRecord) { + if (!newRecord) { qCWarning(QT_BT_OSX) << "QBluetoothServiceInfoPrivate::registerService(), " "failed to create register a service record"; return false; } - QBluetoothServiceInfo::Sequence protocolDescriptorList; - bool updatePDL = false; + const QSInfo::Protocol type = q_ptr->socketProtocol(); + quint16 realPort = 0; + QBluetoothServerPrivate *server = Q_NULLPTR; - if (q_ptr->socketProtocol() == QBluetoothServiceInfo::L2capProtocol) { - // + if (type == QBluetoothServiceInfo::L2capProtocol) { BluetoothL2CAPPSM psm = 0; - if ([serviceRecord getL2CAPPSM:&psm] == kIOReturnSuccess) { - if (psm != q_ptr->protocolServiceMultiplexer()) { - // Update with a real PSM assigned by IOBluetooth! - updatePDL = true; - QBluetoothServiceInfo::Sequence protocol; - protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap)); - protocol << QVariant::fromValue(qint16(psm)); - protocolDescriptorList.append(QVariant::fromValue(protocol)); - } + server = QBluetoothServerPrivate::registeredServer(q_ptr->protocolServiceMultiplexer(), type); + if ([newRecord getL2CAPPSM:&psm] != kIOReturnSuccess) { + [newRecord removeServiceRecord]; + return false; } - } else if (q_ptr->socketProtocol() == QBluetoothServiceInfo::RfcommProtocol) { - // + realPort = psm; + } else if (type == QBluetoothServiceInfo::RfcommProtocol) { BluetoothRFCOMMChannelID channelID = 0; - if ([serviceRecord getRFCOMMChannelID:&channelID] == kIOReturnSuccess) { - if (channelID != q_ptr->serverChannel()) { - updatePDL = true; - QBluetoothServiceInfo::Sequence protocol; - protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::L2cap)); - protocolDescriptorList.append(QVariant::fromValue(protocol)); - protocol.clear(); - protocol << QVariant::fromValue(QBluetoothUuid(QBluetoothUuid::Rfcomm)) - << QVariant::fromValue(quint8(channelID)); - protocolDescriptorList.append(QVariant::fromValue(protocol)); - } + server = QBluetoothServerPrivate::registeredServer(q_ptr->serverChannel(), type); + if ([newRecord getRFCOMMChannelID:&channelID] != kIOReturnSuccess) { + [newRecord removeServiceRecord]; + return false; } + realPort = channelID; } - if (updatePDL) - q_ptr->setAttribute(QBluetoothServiceInfo::ProtocolDescriptorList, protocolDescriptorList); - - // TODO - check ServiceRecordHandle + error handling - if we failed to obtain a port. + if (!server) { + [newRecord removeServiceRecord]; + return false; + } registered = true; + serviceRecord.reset(newRecord.take()); + server->startListener(realPort); return true; } @@ -184,7 +178,19 @@ bool QBluetoothServiceInfoPrivate::unregisterService() [serviceRecord removeServiceRecord]; serviceRecord.reset(nil); - return false; + const QSInfo::Protocol type = q_ptr->socketProtocol(); + QBluetoothServerPrivate *server = Q_NULLPTR; + + const QMutexLocker lock(&QBluetoothServerPrivate::channelMapMutex()); + if (type == QSInfo::RfcommProtocol) + server = QBluetoothServerPrivate::registeredServer(q_ptr->serverChannel(), type); + else if (type == QSInfo::L2capProtocol) + server = QBluetoothServerPrivate::registeredServer(q_ptr->protocolServiceMultiplexer(), type); + + if (server) + server->stopListener(); + + return true; } bool QBluetoothServiceInfo::isRegistered() const |