summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/qbluetoothsocket_osx.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/bluetooth/qbluetoothsocket_osx.mm')
-rw-r--r--src/bluetooth/qbluetoothsocket_osx.mm839
1 files changed, 292 insertions, 547 deletions
diff --git a/src/bluetooth/qbluetoothsocket_osx.mm b/src/bluetooth/qbluetoothsocket_osx.mm
index 7f630146..f74c14f8 100644
--- a/src/bluetooth/qbluetoothsocket_osx.mm
+++ b/src/bluetooth/qbluetoothsocket_osx.mm
@@ -43,6 +43,9 @@
// dependencies problem.
#include "qbluetoothsocketbase_p.h"
#include "qbluetoothsocket_osx_p.h"
+
+#include "osx/osxbtrfcommchannel_p.h"
+#include "osx/osxbtl2capchannel_p.h"
#include "qbluetoothlocaldevice.h"
#include "qbluetoothdeviceinfo.h"
#include "osx/osxbtutility_p.h"
@@ -57,30 +60,294 @@
QT_BEGIN_NAMESPACE
+namespace {
+
+using DarwinBluetooth::RetainPolicy;
+using ObjCL2CAPChannel = QT_MANGLE_NAMESPACE(OSXBTL2CAPChannel);
+using ObjCRFCOMMChannel = QT_MANGLE_NAMESPACE(OSXBTRFCOMMChannel);
+
+} // unnamed namespace
+
QBluetoothSocketPrivate::QBluetoothSocketPrivate()
- : writeChunk(std::numeric_limits<UInt16>::max()),
- openMode(QIODevice::NotOpen), // That's what is set in public class' ctors.
- state(QBluetoothSocket::UnconnectedState),
- socketType(QBluetoothServiceInfo::UnknownProtocol),
- socketError(QBluetoothSocket::NoSocketError),
- isConnecting(false)
+ : writeChunk(std::numeric_limits<UInt16>::max())
{
q_ptr = nullptr;
}
QBluetoothSocketPrivate::~QBluetoothSocketPrivate()
{
- // "Empty" dtor to make a shared pointer happy (parametrized with
- // incomplete type in the header file).
+}
+
+bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
+{
+ // For now - very simplistic, we don't call it in this file, public class
+ // only calls it in a ctor, setting the protocol RFCOMM (in case of Android)
+ // or, indeed, doing, socket-related initialization in BlueZ backend.
+ Q_ASSERT(socketType == QBluetoothServiceInfo::UnknownProtocol);
+ socketType = type;
+ return type != QBluetoothServiceInfo::UnknownProtocol;
+}
+
+QString QBluetoothSocketPrivate::localName() const
+{
+ const QBluetoothLocalDevice device;
+ return device.name();
+}
+
+QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
+{
+ const QBluetoothLocalDevice device;
+ return device.address();
+}
+
+quint16 QBluetoothSocketPrivate::localPort() const
+{
+ return 0;
+}
+
+QString QBluetoothSocketPrivate::peerName() const
+{
+ QT_BT_MAC_AUTORELEASEPOOL;
+
+ NSString *nsName = nil;
+ if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
+ if (rfcommChannel)
+ nsName = [rfcommChannel.getAs<ObjCRFCOMMChannel>() peerName];
+ } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
+ if (l2capChannel)
+ nsName = [l2capChannel.getAs<ObjCL2CAPChannel>() peerName];
+ }
+
+ if (nsName)
+ return QString::fromNSString(nsName);
+
+ return QString();
+}
+
+QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
+{
+ BluetoothDeviceAddress addr = {};
+ if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
+ if (rfcommChannel)
+ addr = [rfcommChannel.getAs<ObjCRFCOMMChannel>() peerAddress];
+ } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
+ if (l2capChannel)
+ addr = [l2capChannel.getAs<ObjCL2CAPChannel>() peerAddress];
+ }
+
+ return OSXBluetooth::qt_address(&addr);
+}
+
+quint16 QBluetoothSocketPrivate::peerPort() const
+{
+ if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
+ if (rfcommChannel)
+ return [rfcommChannel.getAs<ObjCRFCOMMChannel>() getChannelID];
+ } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
+ if (l2capChannel)
+ return [l2capChannel.getAs<ObjCL2CAPChannel>() getPSM];
+ }
+
+ return 0;
+}
+
+void QBluetoothSocketPrivate::abort()
+{
+ // Can never be called while we're in connectToService:
+ Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - "
+ "still in connectToService()");
+
+ if (socketType == QBluetoothServiceInfo::RfcommProtocol)
+ rfcommChannel.reset();
+ else if (socketType == QBluetoothServiceInfo::L2capProtocol)
+ l2capChannel.reset();
+
+ Q_ASSERT(q_ptr);
+
+ q_ptr->setSocketState(QBluetoothSocket::UnconnectedState);
+ emit q_ptr->readChannelFinished();
+ emit q_ptr->disconnected();
+
+}
+
+void QBluetoothSocketPrivate::close()
+{
+ // Can never be called while we're in connectToService:
+ Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - "
+ "still in connectToService()");
+
+ if (!txBuffer.size())
+ abort();
+}
+
+
+qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
+{
+ Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)");
+ Q_ASSERT_X(maxSize > 0, Q_FUNC_INFO, "invalid data size");
+
+ if (state != QBluetoothSocket::ConnectedState) {
+ errorString = QCoreApplication::translate(SOCKET, SOC_NOWRITE);
+ q_ptr->setSocketError(QBluetoothSocket::OperationError);
+ return -1;
+ }
+
+ // We do not have a real socket API under the hood,
+ // IOBluetoothL2CAPChannel is buffered (writeAsync).
+
+ if (!txBuffer.size())
+ QMetaObject::invokeMethod(this, "_q_writeNotify", Qt::QueuedConnection);
+
+ char *dst = txBuffer.reserve(int(maxSize));
+ std::copy(data, data + maxSize, dst);
+
+ return maxSize;
+}
+
+qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
+{
+ if (!data)
+ return 0;
+
+ if (state != QBluetoothSocket::ConnectedState) {
+ errorString = QCoreApplication::translate(SOCKET, SOC_NOREAD);
+ q_ptr->setSocketError(QBluetoothSocket::OperationError);
+ return -1;
+ }
+
+ if (!buffer.isEmpty())
+ return buffer.read(data, int(maxSize));
+
+ return 0;
+}
+
+qint64 QBluetoothSocketPrivate::bytesAvailable() const
+{
+ return buffer.size();
+}
+
+bool QBluetoothSocketPrivate::canReadLine() const
+{
+ return buffer.canReadLine();
+}
+
+qint64 QBluetoothSocketPrivate::bytesToWrite() const
+{
+ return txBuffer.size();
+}
+
+bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+ QBluetoothSocket::SocketState socketState, QIODevice::OpenMode openMode)
+{
+ Q_UNUSED(socketDescriptor)
+ Q_UNUSED(socketType)
+ Q_UNUSED(socketState)
+ Q_UNUSED(openMode)
+
+ qCWarning(QT_BT_OSX) << "setting a socket descriptor is not supported by IOBluetooth";
+ // Noop on macOS.
+ return true;
+}
+
+void QBluetoothSocketPrivate::connectToServiceHelper(const QBluetoothAddress &address, quint16 port,
+ QIODevice::OpenMode openMode)
+{
+ Q_UNUSED(address)
+ Q_UNUSED(port)
+ Q_UNUSED(openMode)
+}
+
+void QBluetoothSocketPrivate::connectToService(const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
+{
+ Q_ASSERT(q_ptr);
+
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
+ if (state!= QBluetoothSocket::UnconnectedState && state != QBluetoothSocket::ServiceLookupState) {
+ qCWarning(QT_BT_OSX) << "called on a busy socket";
+ errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS);
+ q_ptr->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ // Report this problem early, potentially avoid device discovery:
+ if (service.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) {
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
+ errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
+ q_ptr->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ socketType = service.socketProtocol();
+
+ if (service.protocolServiceMultiplexer() > 0) {
+ connectToService(service.device().address(),
+ quint16(service.protocolServiceMultiplexer()),
+ openMode);
+ } else if (service.serverChannel() > 0) {
+ connectToService(service.device().address(),
+ quint16(service.serverChannel()),
+ openMode);
+ } else {
+ // Try service discovery.
+ if (service.serviceUuid().isNull()) {
+ qCWarning(QT_BT_OSX) << "No port, no PSM, and no "
+ "UUID provided, unable to connect";
+ return;
+ }
+
+ q_ptr->doDeviceDiscovery(service, openMode);
+ }
+}
+
+void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
+ QIODevice::OpenMode openMode)
+{
+ Q_ASSERT(q_ptr);
+
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
+ // Report this problem early, avoid device discovery:
+ if (socketType == QBluetoothServiceInfo::UnknownProtocol) {
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
+ errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
+ q_ptr->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ if (state != QBluetoothSocket::UnconnectedState) {
+ qCWarning(QT_BT_OSX) << "called on a busy socket";
+ errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS);
+ q_ptr->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice);
+ QBluetoothServiceInfo service;
+ service.setDevice(device);
+ service.setServiceUuid(uuid);
+ q_ptr->doDeviceDiscovery(service, openMode);
}
void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, quint16 port,
QIODevice::OpenMode mode)
{
- Q_ASSERT_X(state == QBluetoothSocket::ServiceLookupState
- || state == QBluetoothSocket::UnconnectedState,
+ Q_ASSERT(q_ptr);
+
+ OSXBluetooth::qt_test_iobluetooth_runloop();
+
+ if (socketType == QBluetoothServiceInfo::UnknownProtocol) {
+ qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
+ errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
+ q_ptr->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ Q_ASSERT_X(state == QBluetoothSocket::ServiceLookupState || state == QBluetoothSocket::UnconnectedState,
Q_FUNC_INFO, "invalid state");
+ q_ptr->setOpenMode(mode);
+
socketError = QBluetoothSocket::NoSocketError;
errorString.clear();
buffer.clear();
@@ -100,15 +367,15 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
openMode = mode;
if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
- rfcommChannel.reset([[ObjCRFCOMMChannel alloc] initWithDelegate:this]);
+ rfcommChannel.reset([[ObjCRFCOMMChannel alloc] initWithDelegate:this], RetainPolicy::noInitialRetain);
if (rfcommChannel)
- status = [rfcommChannel connectAsyncToDevice:address withChannelID:port];
+ status = [rfcommChannel.getAs<ObjCRFCOMMChannel>() connectAsyncToDevice:address withChannelID:port];
else
status = kIOReturnNoMemory;
} else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
- l2capChannel.reset([[ObjCL2CAPChannel alloc] initWithDelegate:this]);
+ l2capChannel.reset([[ObjCL2CAPChannel alloc] initWithDelegate:this], RetainPolicy::noInitialRetain);
if (l2capChannel)
- status = [l2capChannel connectAsyncToDevice:address withPSM:port];
+ status = [l2capChannel.getAs<ObjCL2CAPChannel>() connectAsyncToDevice:address withPSM:port];
else
status = kIOReturnNoMemory;
}
@@ -148,84 +415,6 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
}
}
-void QBluetoothSocketPrivate::close()
-{
- // Can never be called while we're in connectToService:
- Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - "
- "still in connectToService()");
-
- if (!txBuffer.size())
- abort();
-}
-
-void QBluetoothSocketPrivate::abort()
-{
- // Can never be called while we're in connectToService:
- Q_ASSERT_X(!isConnecting, Q_FUNC_INFO, "internal inconsistency - "
- "still in connectToService()");
-
- if (socketType == QBluetoothServiceInfo::RfcommProtocol)
- rfcommChannel.reset(nil);
- else if (socketType == QBluetoothServiceInfo::L2capProtocol)
- l2capChannel.reset(nil);
-}
-
-quint64 QBluetoothSocketPrivate::bytesAvailable() const
-{
- return buffer.size();
-}
-
-QString QBluetoothSocketPrivate::peerName() const
-{
- QT_BT_MAC_AUTORELEASEPOOL;
-
- NSString *nsName = nil;
- if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
- if (rfcommChannel)
- nsName = [rfcommChannel peerName];
- } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
- if (l2capChannel)
- nsName = [l2capChannel peerName];
- }
-
- if (nsName)
- return QString::fromNSString(nsName);
-
- return QString();
-}
-
-QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
-{
- BluetoothDeviceAddress addr = {};
- if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
- if (rfcommChannel)
- addr = [rfcommChannel peerAddress];
- } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
- if (l2capChannel)
- addr = [l2capChannel peerAddress];
- }
-
- return OSXBluetooth::qt_address(&addr);
-}
-
-quint16 QBluetoothSocketPrivate::peerPort() const
-{
- if (socketType == QBluetoothServiceInfo::RfcommProtocol) {
- if (rfcommChannel)
- return [rfcommChannel getChannelID];
- } else if (socketType == QBluetoothServiceInfo::L2capProtocol) {
- if (l2capChannel)
- return [l2capChannel getPSM];
- }
-
- return 0;
-}
-
-void QBluetoothSocketPrivate::_q_readNotify()
-{
- // Noop.
-}
-
void QBluetoothSocketPrivate::_q_writeNotify()
{
Q_ASSERT_X(socketType == QBluetoothServiceInfo::L2capProtocol
@@ -238,14 +427,14 @@ void QBluetoothSocketPrivate::_q_writeNotify()
if (txBuffer.size()) {
const bool isL2CAP = socketType == QBluetoothServiceInfo::L2capProtocol;
writeChunk.resize(isL2CAP ? std::numeric_limits<UInt16>::max() :
- [rfcommChannel getMTU]);
+ [rfcommChannel.getAs<ObjCRFCOMMChannel>() getMTU]);
const int size = txBuffer.read(writeChunk.data(), writeChunk.size());
IOReturn status = kIOReturnError;
if (!isL2CAP)
- status = [rfcommChannel writeAsync:writeChunk.data() length:UInt16(size)];
+ status = [rfcommChannel.getAs<ObjCRFCOMMChannel>() writeAsync:writeChunk.data() length:UInt16(size)];
else
- status = [l2capChannel writeAsync:writeChunk.data() length:UInt16(size)];
+ status = [l2capChannel.getAs<ObjCL2CAPChannel>() writeAsync:writeChunk.data() length:UInt16(size)];
if (status != kIOReturnSuccess) {
errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
@@ -260,21 +449,22 @@ void QBluetoothSocketPrivate::_q_writeNotify()
close();
}
-bool QBluetoothSocketPrivate::setChannel(IOBluetoothRFCOMMChannel *channel)
+bool QBluetoothSocketPrivate::setRFCOMChannel(void *generic)
{
// A special case "constructor": on OS X we do not have a real listening socket,
// instead a bluetooth server "listens" for channel open notifications and
// creates (if asked by a user later) a "socket" object
// for this connection. This function initializes
// a "socket" from such an external channel (reported by a notification).
-
+ auto channel = static_cast<IOBluetoothRFCOMMChannel *>(generic);
// It must be a newborn socket!
Q_ASSERT_X(socketError == QBluetoothSocket::NoSocketError
&& state == QBluetoothSocket::UnconnectedState && !rfcommChannel && !l2capChannel,
Q_FUNC_INFO, "unexpected socket state");
openMode = QIODevice::ReadWrite;
- rfcommChannel.reset([[ObjCRFCOMMChannel alloc] initWithDelegate:this channel:channel]);
+ rfcommChannel.reset([[ObjCRFCOMMChannel alloc] initWithDelegate:this channel:channel],
+ RetainPolicy::noInitialRetain);
if (rfcommChannel) {// We do not handle errors, up to an external user.
q_ptr->setOpenMode(QIODevice::ReadWrite);
state = QBluetoothSocket::ConnectedState;
@@ -284,13 +474,14 @@ bool QBluetoothSocketPrivate::setChannel(IOBluetoothRFCOMMChannel *channel)
return rfcommChannel;
}
-bool QBluetoothSocketPrivate::setChannel(IOBluetoothL2CAPChannel *channel)
+bool QBluetoothSocketPrivate::setL2CAPChannel(void *generic)
{
// A special case "constructor": on OS X we do not have a real listening socket,
// instead a bluetooth server "listens" for channel open notifications and
// creates (if asked by a user later) a "socket" object
// for this connection. This function initializes
// a "socket" from such an external channel (reported by a notification).
+ auto channel = static_cast<IOBluetoothL2CAPChannel *>(generic);
// It must be a newborn socket!
Q_ASSERT_X(socketError == QBluetoothSocket::NoSocketError
@@ -298,7 +489,7 @@ bool QBluetoothSocketPrivate::setChannel(IOBluetoothL2CAPChannel *channel)
Q_FUNC_INFO, "unexpected socket state");
openMode = QIODevice::ReadWrite;
- l2capChannel.reset([[ObjCL2CAPChannel alloc] initWithDelegate:this channel:channel]);
+ l2capChannel.reset([[ObjCL2CAPChannel alloc] initWithDelegate:this channel:channel], RetainPolicy::noInitialRetain);
if (l2capChannel) {// We do not handle errors, up to an external user.
q_ptr->setOpenMode(QIODevice::ReadWrite);
state = QBluetoothSocket::ConnectedState;
@@ -308,7 +499,6 @@ bool QBluetoothSocketPrivate::setChannel(IOBluetoothL2CAPChannel *channel)
return l2capChannel;
}
-
void QBluetoothSocketPrivate::setChannelError(IOReturn errorCode)
{
Q_UNUSED(errorCode)
@@ -365,7 +555,7 @@ void QBluetoothSocketPrivate::readChannelData(void *data, std::size_t size)
Q_ASSERT_X(q_ptr, Q_FUNC_INFO, "invalid q_ptr (null)");
const char *src = static_cast<char *>(data);
- char *dst = buffer.reserve(size);
+ char *dst = buffer.reserve(int(size));
std::copy(src, src + size, dst);
if (!isConnecting) {
@@ -379,449 +569,4 @@ void QBluetoothSocketPrivate::writeComplete()
_q_writeNotify();
}
-qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
-{
- Q_ASSERT_X(data, Q_FUNC_INFO, "invalid data (null)");
- Q_ASSERT_X(maxSize > 0, Q_FUNC_INFO, "invalid data size");
-
- if (state != QBluetoothSocket::ConnectedState) {
- errorString = QCoreApplication::translate(SOCKET, SOC_NOWRITE);
- q_ptr->setSocketError(QBluetoothSocket::OperationError);
- return -1;
- }
-
- // We do not have a real socket API under the hood,
- // IOBluetoothL2CAPChannel buffered (writeAsync).
-
- if (!txBuffer.size())
- QMetaObject::invokeMethod(this, "_q_writeNotify", Qt::QueuedConnection);
-
- char *dst = txBuffer.reserve(maxSize);
- std::copy(data, data + maxSize, dst);
-
- return maxSize;
-}
-
-QBluetoothSocket::QBluetoothSocket(QBluetoothServiceInfo::Protocol socketType, QObject *parent)
- : QIODevice(parent),
- d_ptr(new QBluetoothSocketPrivate)
-{
- d_ptr->q_ptr = this;
- d_ptr->socketType = socketType;
-
- setOpenMode(NotOpen);
-}
-
-QBluetoothSocket::QBluetoothSocket(QObject *parent)
- : QIODevice(parent),
- d_ptr(new QBluetoothSocketPrivate)
-{
- d_ptr->q_ptr = this;
- setOpenMode(NotOpen);
-}
-
-QBluetoothSocket::~QBluetoothSocket()
-{
- delete d_ptr;
-}
-
-bool QBluetoothSocket::isSequential() const
-{
- return true;
-}
-
-qint64 QBluetoothSocket::bytesAvailable() const
-{
- return QIODevice::bytesAvailable() + d_ptr->bytesAvailable();
-}
-
-qint64 QBluetoothSocket::bytesToWrite() const
-{
- return d_ptr->txBuffer.size();
-}
-
-void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, OpenMode openMode)
-{
- OSXBluetooth::qt_test_iobluetooth_runloop();
-
- if (state() != UnconnectedState && state() != ServiceLookupState) {
- qCWarning(QT_BT_OSX) << "called on a busy socket";
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS);
- setSocketError(OperationError);
- return;
- }
-
- // Report this problem early, potentially avoid device discovery:
- if (service.socketProtocol() == QBluetoothServiceInfo::UnknownProtocol) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
-
- d_ptr->socketType = service.socketProtocol();
-
- if (service.protocolServiceMultiplexer() > 0) {
- d_ptr->connectToService(service.device().address(),
- service.protocolServiceMultiplexer(),
- openMode);
- } else if (service.serverChannel() > 0) {
- d_ptr->connectToService(service.device().address(),
- service.serverChannel(), openMode);
- } else {
- // Try service discovery.
- if (service.serviceUuid().isNull()) {
- qCWarning(QT_BT_OSX) << "No port, no PSM, and no "
- "UUID provided, unable to connect";
- return;
- }
-
- doDeviceDiscovery(service, openMode);
- }
-}
-
-void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid,
- OpenMode openMode)
-{
- OSXBluetooth::qt_test_iobluetooth_runloop();
-
- // Report this problem early, avoid device discovery:
- if (socketType() == QBluetoothServiceInfo::UnknownProtocol) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
-
- if (state() != QBluetoothSocket::UnconnectedState) {
- qCWarning(QT_BT_OSX) << "called on a busy socket";
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS);
- setSocketError(QBluetoothSocket::OperationError);
- return;
- }
-
- QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice);
- QBluetoothServiceInfo service;
- service.setDevice(device);
- service.setServiceUuid(uuid);
- doDeviceDiscovery(service, openMode);
-}
-
-void QBluetoothSocket::connectToService(const QBluetoothAddress &address, quint16 port,
- OpenMode openMode)
-{
- OSXBluetooth::qt_test_iobluetooth_runloop();
-
- if (socketType() == QBluetoothServiceInfo::UnknownProtocol) {
- qCWarning(QT_BT_OSX) << Q_FUNC_INFO << "cannot connect with 'UnknownProtocol' type";
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_NETWORK_ERROR);
- setSocketError(QBluetoothSocket::UnsupportedProtocolError);
- return;
- }
-
- if (state() != QBluetoothSocket::UnconnectedState) {
- qCWarning(QT_BT_OSX) << "called on a busy socket";
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_CONNECT_IN_PROGRESS);
- setSocketError(OperationError);
- return;
- }
-
- setOpenMode(openMode);
- d_ptr->connectToService(address, port, openMode);
-}
-
-QBluetoothServiceInfo::Protocol QBluetoothSocket::socketType() const
-{
- return d_ptr->socketType;
-}
-
-QBluetoothSocket::SocketState QBluetoothSocket::state() const
-{
- return d_ptr->state;
-}
-
-QBluetoothSocket::SocketError QBluetoothSocket::error() const
-{
- return d_ptr->socketError;
-}
-
-QString QBluetoothSocket::errorString() const
-{
- return d_ptr->errorString;
-}
-
-void QBluetoothSocket::setSocketState(QBluetoothSocket::SocketState state)
-{
- const SocketState oldState = d_ptr->state;
- d_ptr->state = state;
- if (oldState != d_ptr->state)
- emit stateChanged(state);
-
- if (state == ListeningState) {
- // We can register for L2CAP/RFCOMM open notifications,
- // that's different from 'listen' and is implemented
- // in QBluetoothServer.
- qCWarning(QT_BT_OSX) << "listening sockets are not supported";
- }
-}
-
-bool QBluetoothSocket::canReadLine() const
-{
- return d_ptr->buffer.canReadLine() || QIODevice::canReadLine();
-}
-
-void QBluetoothSocket::setSocketError(QBluetoothSocket::SocketError socketError)
-{
- d_ptr->socketError = socketError;
- emit error(socketError);
-}
-
-void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, OpenMode openMode)
-{
- OSXBluetooth::qt_test_iobluetooth_runloop();
-
- setSocketState(ServiceLookupState);
-
- if (d_ptr->discoveryAgent)
- d_ptr->discoveryAgent->stop();
-
- d_ptr->discoveryAgent.reset(new QBluetoothServiceDiscoveryAgent(this));
- d_ptr->discoveryAgent->setRemoteAddress(service.device().address());
-
- connect(d_ptr->discoveryAgent.data(), SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
- this, SLOT(serviceDiscovered(QBluetoothServiceInfo)));
- connect(d_ptr->discoveryAgent.data(), SIGNAL(finished()),
- this, SLOT(discoveryFinished()));
-
- d_ptr->openMode = openMode;
-
- if (!service.serviceUuid().isNull())
- d_ptr->discoveryAgent->setUuidFilter(service.serviceUuid());
-
- if (!service.serviceClassUuids().isEmpty())
- d_ptr->discoveryAgent->setUuidFilter(service.serviceClassUuids());
-
- Q_ASSERT_X(!d_ptr->discoveryAgent->uuidFilter().isEmpty(), Q_FUNC_INFO,
- "invalid service info");
-
- d_ptr->discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery);
-}
-
-void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service)
-{
- if (service.protocolServiceMultiplexer() != 0 || service.serverChannel() != 0) {
- d_ptr->discoveryAgent->stop();
- connectToService(service, d_ptr->openMode);
- }
-}
-
-void QBluetoothSocket::discoveryFinished()
-{
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_SERVICE_NOT_FOUND);
- setSocketState(UnconnectedState);
- setSocketError(ServiceNotFoundError);
-}
-
-void QBluetoothSocket::abort()
-{
- if (state() == UnconnectedState)
- return;
-
- setOpenMode(NotOpen);
-
- if (state() == ServiceLookupState && d_ptr->discoveryAgent) {
- d_ptr->discoveryAgent->disconnect();
- d_ptr->discoveryAgent->stop();
- d_ptr->discoveryAgent.reset();
- }
-
- setSocketState(QBluetoothSocket::ClosingState);
- d_ptr->abort();
-
- setSocketState(QBluetoothSocket::UnconnectedState);
- emit readChannelFinished();
- emit disconnected();
-}
-
-void QBluetoothSocket::disconnectFromService()
-{
- close();
-}
-
-QString QBluetoothSocket::localName() const
-{
- const QBluetoothLocalDevice device;
- return device.name();
-}
-
-QBluetoothAddress QBluetoothSocket::localAddress() const
-{
- const QBluetoothLocalDevice device;
- return device.address();
-}
-
-quint16 QBluetoothSocket::localPort() const
-{
- return 0;
-}
-
-QString QBluetoothSocket::peerName() const
-{
- return d_ptr->peerName();
-}
-
-QBluetoothAddress QBluetoothSocket::peerAddress() const
-{
- return d_ptr->peerAddress();
-}
-
-quint16 QBluetoothSocket::peerPort() const
-{
- return d_ptr->peerPort();
-}
-
-qint64 QBluetoothSocket::writeData(const char *data, qint64 maxSize)
-{
- if (!data || maxSize <= 0) {
- d_ptr->errorString = QCoreApplication::translate(SOCKET, SOC_INVAL_DATASIZE);
- setSocketError(QBluetoothSocket::OperationError);
- return -1;
- }
-
- return d_ptr->writeData(data, maxSize);
-}
-
-qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
-{
- if (state != QBluetoothSocket::ConnectedState) {
- errorString = QCoreApplication::translate(SOCKET, SOC_NOREAD);
- q_ptr->setSocketError(QBluetoothSocket::OperationError);
- return -1;
- }
-
- if (!buffer.isEmpty())
- return buffer.read(data, maxSize);
-
- return 0;
-}
-
-qint64 QBluetoothSocket::readData(char *data, qint64 maxSize)
-{
- return d_ptr->readData(data, maxSize);
-}
-
-void QBluetoothSocket::close()
-{
- if (state() == UnconnectedState)
- return;
-
- setOpenMode(NotOpen);
-
- if (state() == ServiceLookupState && d_ptr->discoveryAgent) {
- d_ptr->discoveryAgent->disconnect();
- d_ptr->discoveryAgent->stop();
- d_ptr->discoveryAgent.reset();
- }
-
- setSocketState(ClosingState);
-
- d_ptr->close();
-
- setSocketState(UnconnectedState);
- emit readChannelFinished();
- emit disconnected();
-}
-
-bool QBluetoothSocket::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
- SocketState socketState, OpenMode openMode)
-{
- Q_UNUSED(socketDescriptor)
- Q_UNUSED(socketType)
- Q_UNUSED(socketState)
- Q_UNUSED(openMode)
-
- // Noop on OS X.
- return true;
-}
-
-int QBluetoothSocket::socketDescriptor() const
-{
- return -1;
-}
-
-/* not supported on OS X */
-void QBluetoothSocket::setPreferredSecurityFlags(QBluetooth::SecurityFlags flags)
-{
- Q_UNUSED(flags)
-}
-
-/* not supported on OS X - platform always uses encryption */
-QBluetooth::SecurityFlags QBluetoothSocket::preferredSecurityFlags() const
-{
- return QBluetooth::Secure;
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-
-QDebug operator<<(QDebug debug, QBluetoothSocket::SocketError error)
-{
- switch (error) {
- case QBluetoothSocket::UnknownSocketError:
- debug << "QBluetoothSocket::UnknownSocketError";
- break;
- case QBluetoothSocket::HostNotFoundError:
- debug << "QBluetoothSocket::HostNotFoundError";
- break;
- case QBluetoothSocket::RemoteHostClosedError:
- debug << "QBluetoothSocket::RemoteHostClosedError";
- break;
- case QBluetoothSocket::ServiceNotFoundError:
- debug << "QBluetoothSocket::ServiceNotFoundError";
- break;
- case QBluetoothSocket::NetworkError:
- debug << "QBluetoothSocket::NetworkError";
- break;
- case QBluetoothSocket::UnsupportedProtocolError:
- debug << "QBluetoothSocket::UnsupportedProtocolError";
- break;
- default:
- debug << "QBluetoothSocket::SocketError(" << (int)error << ")";
- }
- return debug;
-}
-
-QDebug operator<<(QDebug debug, QBluetoothSocket::SocketState state)
-{
- switch (state) {
- case QBluetoothSocket::UnconnectedState:
- debug << "QBluetoothSocket::UnconnectedState";
- break;
- case QBluetoothSocket::ConnectingState:
- debug << "QBluetoothSocket::ConnectingState";
- break;
- case QBluetoothSocket::ConnectedState:
- debug << "QBluetoothSocket::ConnectedState";
- break;
- case QBluetoothSocket::BoundState:
- debug << "QBluetoothSocket::BoundState";
- break;
- case QBluetoothSocket::ClosingState:
- debug << "QBluetoothSocket::ClosingState";
- break;
- case QBluetoothSocket::ListeningState:
- debug << "QBluetoothSocket::ListeningState";
- break;
- case QBluetoothSocket::ServiceLookupState:
- debug << "QBluetoothSocket::ServiceLookupState";
- break;
- default:
- debug << "QBluetoothSocket::SocketState(" << (int)state << ")";
- }
- return debug;
-}
-
-#endif // QT_NO_DEBUG_STREAM
-
-#include "moc_qbluetoothsocket.cpp"
-
QT_END_NAMESPACE