summaryrefslogtreecommitdiffstats
path: root/src/bluetooth/qbluetoothsocket_winrt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bluetooth/qbluetoothsocket_winrt.cpp')
-rw-r--r--src/bluetooth/qbluetoothsocket_winrt.cpp183
1 files changed, 145 insertions, 38 deletions
diff --git a/src/bluetooth/qbluetoothsocket_winrt.cpp b/src/bluetooth/qbluetoothsocket_winrt.cpp
index ec511974..556d9fc5 100644
--- a/src/bluetooth/qbluetoothsocket_winrt.cpp
+++ b/src/bluetooth/qbluetoothsocket_winrt.cpp
@@ -37,8 +37,7 @@
**
****************************************************************************/
-#include "qbluetoothsocket.h"
-#include "qbluetoothsocket_p.h"
+#include "qbluetoothsocket_winrt_p.h"
#ifdef CLASSIC_APP_BUILD
#define Q_OS_WINRT
@@ -48,6 +47,8 @@
#include <private/qeventdispatcher_winrt_p.h>
#include <QtBluetooth/QBluetoothLocalDevice>
+#include <QtBluetooth/qbluetoothdeviceinfo.h>
+#include <QtBluetooth/qbluetoothserviceinfo.h>
#include <QtCore/qloggingcategory.h>
#include <robuffer.h>
@@ -129,7 +130,12 @@ public:
~SocketWorker()
{
+ }
+ void close()
+ {
+ m_shuttingDown = true;
if (Q_UNLIKELY(m_initialReadOp)) {
+ onReadyRead(m_initialReadOp.Get(), Canceled);
ComPtr<IAsyncInfo> info;
HRESULT hr = m_initialReadOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
@@ -139,9 +145,11 @@ public:
hr = info->Close();
Q_ASSERT_SUCCEEDED(hr);
}
+ m_initialReadOp.Reset();
}
if (m_readOp) {
+ onReadyRead(m_readOp.Get(), Canceled);
ComPtr<IAsyncInfo> info;
HRESULT hr = m_readOp.As(&info);
Q_ASSERT_SUCCEEDED(hr);
@@ -151,6 +159,7 @@ public:
hr = info->Close();
Q_ASSERT_SUCCEEDED(hr);
}
+ m_readOp.Reset();
}
}
@@ -190,6 +199,9 @@ public:
HRESULT onReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status)
{
+ if (m_shuttingDown)
+ return S_OK;
+
if (asyncInfo == m_initialReadOp.Get()) {
m_initialReadOp.Reset();
} else if (asyncInfo == m_readOp.Get()) {
@@ -299,6 +311,7 @@ public:
private:
ComPtr<IStreamSocket> m_socket;
QVector<QByteArray> m_pendingData;
+ bool m_shuttingDown = false;
// Protects pendingData/pendingDatagrams which are accessed from native callbacks
QMutex m_mutex;
@@ -307,26 +320,22 @@ private:
ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> m_readOp;
};
-QBluetoothSocketPrivate::QBluetoothSocketPrivate()
- : socket(-1),
- socketType(QBluetoothServiceInfo::UnknownProtocol),
- state(QBluetoothSocket::UnconnectedState),
- socketError(QBluetoothSocket::NoSocketError),
- secFlags(QBluetooth::NoSecurity),
- m_worker(new SocketWorker())
+QBluetoothSocketPrivateWinRT::QBluetoothSocketPrivateWinRT()
+ : m_worker(new SocketWorker())
{
+ secFlags = QBluetooth::NoSecurity;
connect(m_worker, &SocketWorker::newDataReceived,
- this, &QBluetoothSocketPrivate::handleNewData, Qt::QueuedConnection);
+ this, &QBluetoothSocketPrivateWinRT::handleNewData, Qt::QueuedConnection);
connect(m_worker, &SocketWorker::socketErrorOccured,
- this, &QBluetoothSocketPrivate::handleError, Qt::QueuedConnection);
+ this, &QBluetoothSocketPrivateWinRT::handleError, Qt::QueuedConnection);
}
-QBluetoothSocketPrivate::~QBluetoothSocketPrivate()
+QBluetoothSocketPrivateWinRT::~QBluetoothSocketPrivateWinRT()
{
abort();
}
-bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
+bool QBluetoothSocketPrivateWinRT::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
{
if (socket != -1) {
if (type == socketType)
@@ -350,7 +359,7 @@ bool QBluetoothSocketPrivate::ensureNativeSocket(QBluetoothServiceInfo::Protocol
return true;
}
-void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+void QBluetoothSocketPrivateWinRT::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
{
Q_Q(QBluetoothSocket);
Q_UNUSED(openMode);
@@ -369,14 +378,14 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IHostName> remoteHost;
hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost);
- RETURN_VOID_IF_FAILED("QBluetoothSocketPrivate::connectToService: Could not create hostname.");
+ RETURN_VOID_IF_FAILED("QBluetoothSocketPrivateWinRT::connectToService: Could not create hostname.");
const QString portString = QString::number(port);
HStringReference portReference(reinterpret_cast<LPCWSTR>(portString.utf16()));
hr = m_socketObject->ConnectAsync(remoteHost.Get(), portReference.Get(), &m_connectOp);
if (hr == E_ACCESSDENIED) {
- qErrnoWarning(hr, "QBluetoothSocketPrivate::connectToService: Unable to connect to bluetooth socket."
+ qErrnoWarning(hr, "QBluetoothSocketPrivateWinRT::connectToService: Unable to connect to bluetooth socket."
"Please check your manifest capabilities.");
q->setSocketState(QBluetoothSocket::UnconnectedState);
return;
@@ -388,22 +397,120 @@ void QBluetoothSocketPrivate::connectToService(const QBluetoothAddress &address,
QEventDispatcherWinRT::runOnXamlThread([this]() {
HRESULT hr;
hr = m_connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
- this, &QBluetoothSocketPrivate::handleConnectOpFinished).Get());
+ this, &QBluetoothSocketPrivateWinRT::handleConnectOpFinished).Get());
RETURN_HR_IF_FAILED("connectToHostByName: Could not register \"connectOp\" callback");
return S_OK;
});
}
-void QBluetoothSocketPrivate::abort()
+void QBluetoothSocketPrivateWinRT::connectToService(
+ const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (q->state() != QBluetoothSocket::UnconnectedState
+ && q->state() != QBluetoothSocket::ServiceLookupState) {
+ qCWarning(QT_BT_WINRT) << "QBluetoothSocket::connectToService called on busy socket";
+ errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ // we are checking the service protocol and not socketType()
+ // socketType will change in ensureNativeSocket()
+ if (service.socketProtocol() != QBluetoothServiceInfo::RfcommProtocol) {
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ if (service.protocolServiceMultiplexer() > 0) {
+ Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::L2capProtocol);
+
+ if (!ensureNativeSocket(QBluetoothServiceInfo::L2capProtocol)) {
+ errorString = QBluetoothSocket::tr("Unknown socket error");
+ q->setSocketError(QBluetoothSocket::UnknownSocketError);
+ return;
+ }
+ connectToServiceHelper(service.device().address(), service.protocolServiceMultiplexer(), openMode);
+ } else if (service.serverChannel() > 0) {
+ Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol);
+
+ if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
+ errorString = QBluetoothSocket::tr("Unknown socket error");
+ q->setSocketError(QBluetoothSocket::UnknownSocketError);
+ return;
+ }
+ connectToServiceHelper(service.device().address(), service.serverChannel(), openMode);
+ } else {
+ // try doing service discovery to see if we can find the socket
+ if (service.serviceUuid().isNull()
+ && !service.serviceClassUuids().contains(QBluetoothUuid::SerialPort)) {
+ qCWarning(QT_BT_WINRT) << "No port, no PSM, and no UUID provided. Unable to connect";
+ return;
+ }
+ qCDebug(QT_BT_WINRT) << "Need a port/psm, doing discovery";
+ q->doDeviceDiscovery(service, openMode);
+ }
+}
+
+void QBluetoothSocketPrivateWinRT::connectToService(
+ const QBluetoothAddress &address, const QBluetoothUuid &uuid, QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (q->state() != QBluetoothSocket::UnconnectedState) {
+ qCWarning(QT_BT_WINRT) << "QBluetoothSocketPrivateWinRT::connectToService called on busy socket";
+ errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ if (q->socketType() != QBluetoothServiceInfo::RfcommProtocol) {
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ QBluetoothServiceInfo service;
+ QBluetoothDeviceInfo device(address, QString(), QBluetoothDeviceInfo::MiscellaneousDevice);
+ service.setDevice(device);
+ service.setServiceUuid(uuid);
+ q->doDeviceDiscovery(service, openMode);
+}
+
+void QBluetoothSocketPrivateWinRT::connectToService(
+ const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (q->state() != QBluetoothSocket::UnconnectedState) {
+ qCWarning(QT_BT_WINRT) << "QBluetoothSocketPrivateWinRT::connectToService called on busy socket";
+ errorString = QBluetoothSocket::tr("Trying to connect while connection is in progress");
+ q->setSocketError(QBluetoothSocket::OperationError);
+ return;
+ }
+
+ if (q->socketType() != QBluetoothServiceInfo::RfcommProtocol) {
+ errorString = QBluetoothSocket::tr("Socket type not supported");
+ q->setSocketError(QBluetoothSocket::UnsupportedProtocolError);
+ return;
+ }
+
+ connectToServiceHelper(address, port, openMode);
+}
+
+void QBluetoothSocketPrivateWinRT::abort()
{
Q_Q(QBluetoothSocket);
if (state == QBluetoothSocket::UnconnectedState)
return;
disconnect(m_worker, &SocketWorker::newDataReceived,
- this, &QBluetoothSocketPrivate::handleNewData);
+ this, &QBluetoothSocketPrivateWinRT::handleNewData);
disconnect(m_worker, &SocketWorker::socketErrorOccured,
- this, &QBluetoothSocketPrivate::handleError);
+ this, &QBluetoothSocketPrivateWinRT::handleError);
+ m_worker->close();
m_worker->deleteLater();
if (socket != -1) {
@@ -413,7 +520,7 @@ void QBluetoothSocketPrivate::abort()
q->setSocketState(QBluetoothSocket::UnconnectedState);
}
-QString QBluetoothSocketPrivate::localName() const
+QString QBluetoothSocketPrivateWinRT::localName() const
{
const QBluetoothAddress address = localAddress();
if (address.isNull())
@@ -423,7 +530,7 @@ QString QBluetoothSocketPrivate::localName() const
return device.name();
}
-QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
+QBluetoothAddress QBluetoothSocketPrivateWinRT::localAddress() const
{
if (!m_socketObject)
return QBluetoothAddress();
@@ -441,7 +548,7 @@ QBluetoothAddress QBluetoothSocketPrivate::localAddress() const
return QBluetoothAddress(qt_QStringFromHString(localAddress));
}
-quint16 QBluetoothSocketPrivate::localPort() const
+quint16 QBluetoothSocketPrivateWinRT::localPort() const
{
if (!m_socketObject)
return 0;
@@ -456,7 +563,7 @@ quint16 QBluetoothSocketPrivate::localPort() const
return qt_QStringFromHString(localPortString).toInt();
}
-QString QBluetoothSocketPrivate::peerName() const
+QString QBluetoothSocketPrivateWinRT::peerName() const
{
if (!m_socketObject)
return QString();
@@ -474,7 +581,7 @@ QString QBluetoothSocketPrivate::peerName() const
return qt_QStringFromHString(remoteHostName);
}
-QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
+QBluetoothAddress QBluetoothSocketPrivateWinRT::peerAddress() const
{
if (!m_socketObject)
return QBluetoothAddress();
@@ -492,7 +599,7 @@ QBluetoothAddress QBluetoothSocketPrivate::peerAddress() const
return QBluetoothAddress(qt_QStringFromHString(remoteAddress));
}
-quint16 QBluetoothSocketPrivate::peerPort() const
+quint16 QBluetoothSocketPrivateWinRT::peerPort() const
{
if (!m_socketObject)
return 0;
@@ -507,7 +614,7 @@ quint16 QBluetoothSocketPrivate::peerPort() const
return qt_QStringFromHString(remotePortString).toInt();
}
-qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
+qint64 QBluetoothSocketPrivateWinRT::writeData(const char *data, qint64 maxSize)
{
Q_Q(QBluetoothSocket);
@@ -533,7 +640,7 @@ qint64 QBluetoothSocketPrivate::writeData(const char *data, qint64 maxSize)
return bytesWritten;
}
-qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
+qint64 QBluetoothSocketPrivateWinRT::readData(char *data, qint64 maxSize)
{
Q_Q(QBluetoothSocket);
@@ -549,12 +656,12 @@ qint64 QBluetoothSocketPrivate::readData(char *data, qint64 maxSize)
return 0;
}
-void QBluetoothSocketPrivate::close()
+void QBluetoothSocketPrivateWinRT::close()
{
abort();
}
-bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
+bool QBluetoothSocketPrivateWinRT::setSocketDescriptor(int socketDescriptor, QBluetoothServiceInfo::Protocol socketType,
QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
{
Q_UNUSED(socketDescriptor);
@@ -565,7 +672,7 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(int socketDescriptor, QBluetoo
return false;
}
-bool QBluetoothSocketPrivate::setSocketDescriptor(ComPtr<IStreamSocket> socketPtr, QBluetoothServiceInfo::Protocol socketType,
+bool QBluetoothSocketPrivateWinRT::setSocketDescriptor(ComPtr<IStreamSocket> socketPtr, QBluetoothServiceInfo::Protocol socketType,
QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
{
Q_Q(QBluetoothSocket);
@@ -582,22 +689,22 @@ bool QBluetoothSocketPrivate::setSocketDescriptor(ComPtr<IStreamSocket> socketPt
return true;
}
-qint64 QBluetoothSocketPrivate::bytesAvailable() const
+qint64 QBluetoothSocketPrivateWinRT::bytesAvailable() const
{
return buffer.size();
}
-qint64 QBluetoothSocketPrivate::bytesToWrite() const
+qint64 QBluetoothSocketPrivateWinRT::bytesToWrite() const
{
return 0; // nothing because always unbuffered
}
-bool QBluetoothSocketPrivate::canReadLine() const
+bool QBluetoothSocketPrivateWinRT::canReadLine() const
{
return buffer.canReadLine();
}
-void QBluetoothSocketPrivate::handleNewData(const QVector<QByteArray> &data)
+void QBluetoothSocketPrivateWinRT::handleNewData(const QVector<QByteArray> &data)
{
// Defer putting the data into the list until the next event loop iteration
// (where the readyRead signal is emitted as well)
@@ -605,7 +712,7 @@ void QBluetoothSocketPrivate::handleNewData(const QVector<QByteArray> &data)
Q_ARG(QVector<QByteArray>, data));
}
-void QBluetoothSocketPrivate::handleError(QBluetoothSocket::SocketError error)
+void QBluetoothSocketPrivateWinRT::handleError(QBluetoothSocket::SocketError error)
{
Q_Q(QBluetoothSocket);
switch (error) {
@@ -623,7 +730,7 @@ void QBluetoothSocketPrivate::handleError(QBluetoothSocket::SocketError error)
q->setSocketState(QBluetoothSocket::UnconnectedState);
}
-void QBluetoothSocketPrivate::addToPendingData(const QVector<QByteArray> &data)
+void QBluetoothSocketPrivateWinRT::addToPendingData(const QVector<QByteArray> &data)
{
Q_Q(QBluetoothSocket);
QMutexLocker locker(&m_readMutex);
@@ -636,7 +743,7 @@ void QBluetoothSocketPrivate::addToPendingData(const QVector<QByteArray> &data)
emit q->readyRead();
}
-HRESULT QBluetoothSocketPrivate::handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *action, ABI::Windows::Foundation::AsyncStatus status)
+HRESULT QBluetoothSocketPrivateWinRT::handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *action, ABI::Windows::Foundation::AsyncStatus status)
{
Q_Q(QBluetoothSocket);
if (status != Completed || !m_connectOp) { // Protect against a late callback