summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/qbluetoothsocket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bluetooth/qbluetoothsocket.cpp')
-rw-r--r--src/bluetooth/qbluetoothsocket.cpp143
1 files changed, 103 insertions, 40 deletions
diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp
index 96ed9dae..c7aea0b7 100644
--- a/src/bluetooth/qbluetoothsocket.cpp
+++ b/src/bluetooth/qbluetoothsocket.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
@@ -48,11 +48,14 @@
#include "qbluetoothservicediscoveryagent.h"
-#include <QDebug>
+#include <QtCore/QLoggingCategory>
#include <QSocketNotifier>
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(QT_BT)
+Q_DECLARE_LOGGING_CATEGORY(QT_BT_QNX)
+
/*!
\class QBluetoothSocket
\inmodule QtBluetooth
@@ -63,6 +66,8 @@ QT_BEGIN_NAMESPACE
\l {QBluetoothServiceInfo::RfcommProtocol}{RFCOMM}.
\l {QBluetoothServiceInfo::L2capProtocol}{L2CAP} is a low level datagram-oriented Bluetooth socket.
+ Android and BlackBerry do not support \l {QBluetoothServiceInfo::L2capProtocol}{L2CAP} for socket
+ connections.
\l {QBluetoothServiceInfo::RfcommProtocol}{RFCOMM} is a reliable, stream-oriented socket. RFCOMM
sockets emulate an RS-232 serial port.
@@ -103,6 +108,8 @@ QT_BEGIN_NAMESPACE
\value NetworkError Attempt to read or write from socket returned an error
\value UnsupportedProtocolError The \l {QBluetoothServiceInfo::Protocol}{Protocol} is not
supported on this platform.
+ \value OperationError An operation was attempted while the socket was in a state
+ that did not permit it.
*/
/*!
@@ -166,19 +173,30 @@ QT_BEGIN_NAMESPACE
\fn QString QBluetoothSocket::localName() const
Returns the name of the local device.
+
+ Although some platforms may differ the socket must generally be connected to guarantee
+ the return of a valid name. In particular, this is true when dealing with platforms
+ that support multiple local Bluetooth adapters.
*/
/*!
\fn QBluetoothAddress QBluetoothSocket::localAddress() const
Returns the address of the local device.
+
+ Although some platforms may differ the socket must generally be connected to guarantee
+ the return of a valid address. In particular, this is true when dealing with platforms
+ that support multiple local Bluetooth adapters.
*/
/*!
\fn quint16 QBluetoothSocket::localPort() const
Returns the port number of the local socket if available, otherwise returns 0.
- On BlackBerry, this feature is not supported and returns 0.
+ Although some platforms may differ the socket must generally be connected to guarantee
+ the return of a valid port number.
+
+ On BlackBerry and Android, this feature is not supported and returns 0.
*/
/*!
@@ -197,7 +215,7 @@ QT_BEGIN_NAMESPACE
\fn quint16 QBluetoothSocket::peerPort() const
Return the port number of the peer socket if available, otherwise returns 0.
- On BlackBerry, this feature is not supported.
+ On BlackBerry and Android, this feature is not supported.
*/
/*!
@@ -277,51 +295,62 @@ qint64 QBluetoothSocket::bytesToWrite() const
/*!
Attempts to connect to the service described by \a service.
- The socket is opened in the given \a openMode.
+ The socket is opened in the given \a openMode. The \l socketType() may change
+ depending on the protocol required by \a service.
- For BlueZ, the socket first enters ConnectingState and attempts to connect to the device providing
+ The socket first enters ConnectingState and attempts to connect to the device providing
\a service. If a connection is established, QBluetoothSocket enters ConnectedState and
emits connected().
- On QNX the service connection can be established directly using the UUID of the remote service.
+ At any point, the socket can emit error() to signal that an error occurred.
- At any point, the socket can emit error() to siganl that an error occurred.
+ Note that most platforms require a pairing prior to connecting to the remote device. Otherwise
+ the connection process may fail.
\sa state(), disconnectFromService()
*/
void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, OpenMode openMode)
{
Q_D(QBluetoothSocket);
+
+ if (state() != QBluetoothSocket::UnconnectedState) {
+ qCWarning(QT_BT) << "QBluetoothSocket::connectToService called on busy socket";
+ d->errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
setOpenMode(openMode);
-#ifdef QT_QNX_BLUETOOTH
- if (socketType() != QBluetoothServiceInfo::RfcommProtocol) {
- d->socketError = QBluetoothSocket::UnsupportedProtocolError;
+#if defined(QT_QNX_BLUETOOTH) || defined(QT_ANDROID_BLUETOOTH)
+ if (!d->ensureNativeSocket(service.socketProtocol())) {
d->errorString = tr("Socket type not supported");
- Q_EMIT error(d->socketError);
+ setSocketError(QBluetoothSocket::UnsupportedProtocolError);
return;
}
d->connectToService(service.device().address(), service.serviceUuid(), openMode);
#else
if (service.protocolServiceMultiplexer() > 0) {
if (!d->ensureNativeSocket(QBluetoothServiceInfo::L2capProtocol)) {
- emit error(UnknownSocketError);
+ d->errorString = tr("Unknown socket error");
+ setSocketError(UnknownSocketError);
return;
}
d->connectToService(service.device().address(), service.protocolServiceMultiplexer(), openMode);
} else if (service.serverChannel() > 0) {
if (!d->ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
- emit error(UnknownSocketError);
+ d->errorString = tr("Unknown socket error");
+ setSocketError(UnknownSocketError);
return;
}
d->connectToService(service.device().address(), service.serverChannel(), openMode);
} else {
// try doing service discovery to see if we can find the socket
if(service.serviceUuid().isNull()){
- qWarning() << "No port, no PSM, and no UUID provided, unable to connect";
+ qCWarning(QT_BT) << "No port, no PSM, and no UUID provided, unable to connect";
return;
}
- //qDebug() << "Need a port/psm, doing discovery";
+ qCDebug(QT_BT) << "Need a port/psm, doing discovery";
doDeviceDiscovery(service, openMode);
}
#endif
@@ -333,25 +362,38 @@ void QBluetoothSocket::connectToService(const QBluetoothServiceInfo &service, Op
The socket is opened in the given \a openMode.
- For BlueZ, the socket first enters the ServiceLookupState and queries the connection parameters for
+ For BlueZ, the socket first enters the \l ServiceLookupState and queries the connection parameters for
\a uuid. If the service parameters are successfully retrieved the socket enters
ConnectingState, and attempts to connect to \a address. If a connection is established,
QBluetoothSocket enters Connected State and emits connected().
- On BlackBerry, the service connection can be established directly using the UUID of the remote service.
+ On BlackBerry and Android, the service connection can directly be established
+ using the UUID of the remote service. Therefore these platforms do not require
+ the \l ServiceLookupState and \l socketType() is always set to
+ \l QBluetoothServiceInfo::RfcommProtocol.
At any point, the socket can emit error() to signal that an error occurred.
+ Note that most platforms require a pairing prior to connecting to the remote device. Otherwise
+ the connection process may fail.
+
\sa state(), disconnectFromService()
*/
void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const QBluetoothUuid &uuid, OpenMode openMode)
{
-#ifdef QT_QNX_BLUETOOTH
Q_D(QBluetoothSocket);
- if (socketType() != QBluetoothServiceInfo::RfcommProtocol) {
- d->socketError = QBluetoothSocket::UnsupportedProtocolError;
+
+ if (state() != QBluetoothSocket::UnconnectedState) {
+ qCWarning(QT_BT) << "QBluetoothSocket::connectToService called on busy socket";
+ d->errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+#if defined(QT_QNX_BLUETOOTH) || defined(QT_ANDROID_BLUETOOTH)
+ if (!d->ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
d->errorString = tr("Socket type not supported");
- Q_EMIT error(d->socketError);
+ setSocketError(QBluetoothSocket::UnsupportedProtocolError);
return;
}
d->connectToService(address, uuid, openMode);
@@ -374,30 +416,43 @@ void QBluetoothSocket::connectToService(const QBluetoothAddress &address, const
At any point, the socket can emit error() to signal that an error occurred.
- On BlackBerry, a connection to a service can not be established using a port. Calling this function
+ On BlackBerry and Android, a connection to a service can not be established using a port. Calling this function
will emit a \l {QBluetoothSocket::ServiceNotFoundError}{ServiceNotFoundError}
+ Note that most platforms require a pairing prior to connecting to the remote device. Otherwise
+ the connection process may fail.
+
\sa state(), disconnectFromService()
*/
void QBluetoothSocket::connectToService(const QBluetoothAddress &address, quint16 port, OpenMode openMode)
{
Q_D(QBluetoothSocket);
-#ifdef QT_QNX_BLUETOOTH
+#if defined(QT_QNX_BLUETOOTH) || defined(QT_ANDROID_BLUETOOTH)
Q_UNUSED(port);
Q_UNUSED(openMode);
Q_UNUSED(address);
- d->socketError = QBluetoothSocket::ServiceNotFoundError;
- d->errorString = tr("Connecting to port is not supported on QNX");
- Q_EMIT error(d->socketError);
- qWarning("Connecting to port is not supported");
+ d->errorString = tr("Connecting to port is not supported");
+ setSocketError(QBluetoothSocket::ServiceNotFoundError);
+ qCWarning(QT_BT) << "Connecting to port is not supported";
#else
+ if (state() != QBluetoothSocket::UnconnectedState) {
+ qCWarning(QT_BT) << "QBluetoothSocket::connectToService called on busy socket";
+ d->errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
setOpenMode(openMode);
d->connectToService(address, port, openMode);
#endif
}
/*!
- Returns the socket type.
+ Returns the socket type. The socket automatically adjusts to the protocol
+ offered by the remote service.
+
+ Blackberry and Android only support \l{QBluetoothServiceInfo::RfcommProtocol}{RFCOMM}
+ based sockets.
*/
QBluetoothServiceInfo::Protocol QBluetoothSocket::socketType() const
{
@@ -482,13 +537,15 @@ void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, O
Q_D(QBluetoothSocket);
setSocketState(QBluetoothSocket::ServiceLookupState);
- //qDebug() << "Starting discovery";
+ qCDebug(QT_BT) << "Starting discovery";
if(d->discoveryAgent) {
+ d->discoveryAgent->stop();
delete d->discoveryAgent;
}
- d->discoveryAgent = new QBluetoothServiceDiscoveryAgent(service.device().address(),this);
+ d->discoveryAgent = new QBluetoothServiceDiscoveryAgent(this);
+ d->discoveryAgent->setRemoteAddress(service.device().address());
//qDebug() << "Got agent";
@@ -506,7 +563,7 @@ void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, O
// we have to ID the service somehow
Q_ASSERT(!d->discoveryAgent->uuidFilter().isEmpty());
- //qDebug() << "UUID filter" << d->discoveryAgent->uuidFilter();
+ qCDebug(QT_BT) << "UUID filter" << d->discoveryAgent->uuidFilter();
d->discoveryAgent->start(QBluetoothServiceDiscoveryAgent::FullDiscovery);
}
@@ -514,7 +571,7 @@ void QBluetoothSocket::doDeviceDiscovery(const QBluetoothServiceInfo &service, O
void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service)
{
Q_D(QBluetoothSocket);
- //qDebug() << "FOUND SERVICE!" << service;
+ qCDebug(QT_BT) << "FOUND SERVICE!" << service;
if(service.protocolServiceMultiplexer() != 0 || service.serverChannel() != 0) {
connectToService(service, d->openMode);
d->discoveryAgent->deleteLater();
@@ -524,11 +581,13 @@ void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service)
void QBluetoothSocket::discoveryFinished()
{
- //qDebug() << "Socket discovery finished";
+ qCDebug(QT_BT) << "Socket discovery finished";
Q_D(QBluetoothSocket);
- if(d->discoveryAgent){
- //qDebug() << "Didn't find any";
- emit error(QBluetoothSocket::ServiceNotFoundError);
+ if (d->discoveryAgent){
+ qCDebug(QT_BT) << "Didn't find any";
+ d->errorString = tr("Service cannot be found");
+ setSocketError(ServiceNotFoundError);
+ setSocketState(QBluetoothSocket::UnconnectedState);
d->discoveryAgent->deleteLater();
d->discoveryAgent = 0;
}
@@ -536,6 +595,9 @@ void QBluetoothSocket::discoveryFinished()
void QBluetoothSocket::abort()
{
+ if (state() == UnconnectedState)
+ return;
+
Q_D(QBluetoothSocket);
d->abort();
setSocketState(QBluetoothSocket::UnconnectedState);
@@ -543,9 +605,7 @@ void QBluetoothSocket::abort()
void QBluetoothSocket::disconnectFromService()
{
- // TODO: is this all we need to do?
- Q_D(QBluetoothSocket);
- d->close();
+ close();
}
QString QBluetoothSocket::localName() const
@@ -598,6 +658,9 @@ qint64 QBluetoothSocket::readData(char *data, qint64 maxSize)
void QBluetoothSocket::close()
{
+ if (state() == UnconnectedState)
+ return;
+
Q_D(QBluetoothSocket);
setSocketState(ClosingState);