summaryrefslogtreecommitdiffstats
path: root/src/bluetooth
diff options
context:
space:
mode:
authorOliver Wolff <oliver.wolff@qt.io>2019-05-09 15:17:32 +0200
committerOliver Wolff <oliver.wolff@qt.io>2019-05-27 15:45:37 +0200
commit672ebe7690455c6ee13f96ad05d030183a7e57f8 (patch)
tree8cb691389fde4a9225aa0f095fa7acc9d8e870f7 /src/bluetooth
parentea85065cbbc2c51482039384f82ab9bbf32104b1 (diff)
qbluetoothsocket_winrt: Use recommended service connection approach if possible
MSDN documentation states that the recommended way of RFCOMM service connection is via connectionHostName and connectionServiceName (see https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.rfcomm.rfcommdeviceservice). So whenever possible, we should use this information from the native device service when connecting directly to the discovered service. As QBluetoothServiceInfo is basically just a wrapper for the attributes map this information is stored in its private pendant and extracted when a connection attempt is being made. Task-number: QTBUG-62520 Change-Id: I95be5df89a722531393b45fd136d37f302393ca8 Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'src/bluetooth')
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp11
-rw-r--r--src/bluetooth/qbluetoothsocket.cpp7
-rw-r--r--src/bluetooth/qbluetoothsocket_winrt.cpp64
-rw-r--r--src/bluetooth/qbluetoothsocket_winrt_p.h15
4 files changed, 80 insertions, 17 deletions
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp
index 9f82a202..3b99c1c4 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_winrt.cpp
@@ -52,6 +52,7 @@
#include <windows.devices.enumeration.h>
#include <windows.devices.bluetooth.h>
#include <windows.foundation.collections.h>
+#include <windows.networking.h>
#include <windows.storage.streams.h>
#include <wrl.h>
@@ -208,6 +209,14 @@ void QWinRTBluetoothServiceDiscoveryWorker::processServiceSearchResult(quint64 a
hr = service->get_ConnectionServiceName(name.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
const QString serviceName = QString::fromWCharArray(WindowsGetStringRawBuffer(name.Get(), nullptr));
+ ComPtr<ABI::Windows::Networking::IHostName> host;
+ hr = service->get_ConnectionHostName(host.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ HString hostName;
+ hr = host->get_RawName(hostName.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ const QString qHostName = QString::fromWCharArray(WindowsGetStringRawBuffer(hostName.Get(),
+ nullptr));
ComPtr<IRfcommServiceId> id;
hr = service->get_ServiceId(&id);
Q_ASSERT_SUCCEEDED(hr);
@@ -217,6 +226,8 @@ void QWinRTBluetoothServiceDiscoveryWorker::processServiceSearchResult(quint64 a
Q_ASSERT_SUCCEEDED(hr);
QBluetoothServiceInfo info;
+ info.setAttribute(0xBEEF, QVariant(qHostName));
+ info.setAttribute(0xBEF0, QVariant(serviceName));
info.setServiceName(serviceName);
info.setServiceUuid(uuid);
ComPtr<IAsyncOperation<IMapView<UINT32, IBuffer *> *>> op;
diff --git a/src/bluetooth/qbluetoothsocket.cpp b/src/bluetooth/qbluetoothsocket.cpp
index a18b8ed4..db7c8be4 100644
--- a/src/bluetooth/qbluetoothsocket.cpp
+++ b/src/bluetooth/qbluetoothsocket.cpp
@@ -640,6 +640,13 @@ void QBluetoothSocket::serviceDiscovered(const QBluetoothServiceInfo &service)
connectToService(service, d->openMode);
d->discoveryAgent->deleteLater();
d->discoveryAgent = nullptr;
+#ifdef QT_WINRT_BLUETOOTH
+ } else if (!service.attribute(0xBEEF).isNull()
+ && !service.attribute(0xBEF0).isNull()) {
+ connectToService(service, d->openMode);
+ d->discoveryAgent->deleteLater();
+ d->discoveryAgent = nullptr;
+#endif
} else {
qCDebug(QT_BT) << "Could not find port/psm for potential remote service";
}
diff --git a/src/bluetooth/qbluetoothsocket_winrt.cpp b/src/bluetooth/qbluetoothsocket_winrt.cpp
index a4af8f72..72d72040 100644
--- a/src/bluetooth/qbluetoothsocket_winrt.cpp
+++ b/src/bluetooth/qbluetoothsocket_winrt.cpp
@@ -359,10 +359,11 @@ bool QBluetoothSocketPrivateWinRT::ensureNativeSocket(QBluetoothServiceInfo::Pro
return true;
}
-void QBluetoothSocketPrivateWinRT::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+void QBluetoothSocketPrivateWinRT::connectToService(Microsoft::WRL::ComPtr<IHostName> hostName,
+ const QString &serviceName,
+ QIODevice::OpenMode openMode)
{
Q_Q(QBluetoothSocket);
- Q_UNUSED(openMode);
if (socket == -1 && !ensureNativeSocket(socketType)) {
errorString = QBluetoothSocket::tr("Unknown socket error");
@@ -370,20 +371,9 @@ void QBluetoothSocketPrivateWinRT::connectToServiceHelper(const QBluetoothAddres
return;
}
- const QString addressString = address.toString();
- HStringReference hostNameRef(reinterpret_cast<LPCWSTR>(addressString.utf16()));
- ComPtr<IHostNameFactory> hostNameFactory;
- HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
- &hostNameFactory);
- Q_ASSERT_SUCCEEDED(hr);
- ComPtr<IHostName> remoteHost;
- hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost);
- RETURN_VOID_IF_FAILED("QBluetoothSocketPrivateWinRT::connectToService: Could not create hostname.");
-
- const QString portString = QString::number(port);
- HStringReference portReference(reinterpret_cast<LPCWSTR>(portString.utf16()));
+ HStringReference serviceNameReference(reinterpret_cast<LPCWSTR>(serviceName.utf16()));
- hr = m_socketObject->ConnectAsync(remoteHost.Get(), portReference.Get(), &m_connectOp);
+ HRESULT hr = m_socketObject->ConnectAsync(hostName.Get(), serviceNameReference.Get(), &m_connectOp);
if (hr == E_ACCESSDENIED) {
qErrnoWarning(hr, "QBluetoothSocketPrivateWinRT::connectToService: Unable to connect to bluetooth socket."
"Please check your manifest capabilities.");
@@ -404,6 +394,29 @@ void QBluetoothSocketPrivateWinRT::connectToServiceHelper(const QBluetoothAddres
Q_ASSERT_SUCCEEDED(hr);
}
+void QBluetoothSocketPrivateWinRT::connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode)
+{
+ Q_Q(QBluetoothSocket);
+
+ if (socket == -1 && !ensureNativeSocket(socketType)) {
+ errorString = QBluetoothSocket::tr("Unknown socket error");
+ q->setSocketError(QBluetoothSocket::UnknownSocketError);
+ return;
+ }
+
+ const QString addressString = address.toString();
+ HStringReference hostNameRef(reinterpret_cast<LPCWSTR>(addressString.utf16()));
+ ComPtr<IHostNameFactory> hostNameFactory;
+ HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
+ &hostNameFactory);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IHostName> remoteHost;
+ hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost);
+ RETURN_VOID_IF_FAILED("QBluetoothSocketPrivateWinRT::connectToService: Could not create hostname.");
+ const QString portString = QString::number(port);
+ connectToService(remoteHost, portString, openMode);
+}
+
void QBluetoothSocketPrivateWinRT::connectToService(
const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode)
{
@@ -425,6 +438,8 @@ void QBluetoothSocketPrivateWinRT::connectToService(
return;
}
+ const QString connectionHostName = service.attribute(0xBEEF).toString();
+ const QString connectionServiceName = service.attribute(0xBEF0).toString();
if (service.protocolServiceMultiplexer() > 0) {
Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::L2capProtocol);
@@ -434,7 +449,22 @@ void QBluetoothSocketPrivateWinRT::connectToService(
return;
}
connectToServiceHelper(service.device().address(), service.protocolServiceMultiplexer(), openMode);
- } else if (service.serverChannel() > 0) {
+ } else if (!connectionHostName.isEmpty() && !connectionServiceName.isEmpty()) {
+ Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol);
+ if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
+ errorString = QBluetoothSocket::tr("Unknown socket error");
+ q->setSocketError(QBluetoothSocket::UnknownSocketError);
+ return;
+ }
+ HStringReference hostNameRef(reinterpret_cast<LPCWSTR>(connectionHostName.utf16()));
+ ComPtr<IHostNameFactory> hostNameFactory;
+ HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
+ &hostNameFactory);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IHostName> remoteHost;
+ hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost);
+ connectToService(remoteHost, connectionServiceName, openMode);
+ } else if (service.serverChannel() > 0) {
Q_ASSERT(service.socketProtocol() == QBluetoothServiceInfo::RfcommProtocol);
if (!ensureNativeSocket(QBluetoothServiceInfo::RfcommProtocol)) {
@@ -443,7 +473,7 @@ void QBluetoothSocketPrivateWinRT::connectToService(
return;
}
connectToServiceHelper(service.device().address(), service.serverChannel(), openMode);
- } else {
+ } else {
// try doing service discovery to see if we can find the socket
if (service.serviceUuid().isNull()
&& !service.serviceClassUuids().contains(QBluetoothUuid::SerialPort)) {
diff --git a/src/bluetooth/qbluetoothsocket_winrt_p.h b/src/bluetooth/qbluetoothsocket_winrt_p.h
index 40e87f01..de8b7d67 100644
--- a/src/bluetooth/qbluetoothsocket_winrt_p.h
+++ b/src/bluetooth/qbluetoothsocket_winrt_p.h
@@ -57,6 +57,19 @@
QT_FORWARD_DECLARE_CLASS(SocketWorker)
+namespace ABI {
+ namespace Windows {
+ namespace Networking {
+ struct IHostName;
+ }
+ }
+}
+
+namespace Microsoft {
+ namespace WRL {
+ template <typename T> class ComPtr;
+ }
+}
QT_BEGIN_NAMESPACE
class QBluetoothSocketPrivateWinRT final: public QBluetoothSocketBasePrivate
@@ -125,6 +138,8 @@ private slots:
void handleError(QBluetoothSocket::SocketError error);
private:
+ void connectToService(Microsoft::WRL::ComPtr<ABI::Windows::Networking::IHostName> hostName,
+ const QString &serviceName, QIODevice::OpenMode openMode);
HRESULT handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *action,
ABI::Windows::Foundation::AsyncStatus status);