7#include <QtBluetooth/QBluetoothLocalDevice>
8#include <QtBluetooth/qbluetoothdeviceinfo.h>
9#include <QtBluetooth/qbluetoothserviceinfo.h>
10#include <QtCore/qloggingcategory.h>
11#include <QtCore/QPointer>
12#include <QtCore/private/qfunctions_winrt_p.h>
15#include <windows.devices.bluetooth.h>
16#include <windows.networking.sockets.h>
17#include <windows.storage.streams.h>
21using namespace Microsoft::WRL::Wrappers;
23using namespace ABI::Windows::Devices::Bluetooth::Rfcomm;
25using namespace ABI::Windows::Foundation::Collections;
27using namespace ABI::Windows::Networking::Sockets;
42 hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
44 Q_ASSERT_SUCCEEDED(hr);
51#define READ_BUFFER_SIZE 65536
56 PCWSTR rawString =
string.GetRawBuffer(&
length);
64 ComPtr<IBuffer> tempBuffer;
65 if (
len > UINT32_MAX) {
66 qCWarning(QT_BT_WINDOWS) <<
"writeIOStream can only write up to" << UINT32_MAX <<
"bytes.";
70 HRESULT hr =
g->bufferFactory->Create(ulen, &tempBuffer);
71 Q_ASSERT_SUCCEEDED(hr);
72 hr = tempBuffer->put_Length(ulen);
73 Q_ASSERT_SUCCEEDED(hr);
74 ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
75 hr = tempBuffer.As(&byteArrayAccess);
76 Q_ASSERT_SUCCEEDED(hr);
78 hr = byteArrayAccess->Buffer(&bytes);
79 Q_ASSERT_SUCCEEDED(hr);
80 memcpy(bytes,
data, ulen);
81 ComPtr<IAsyncOperationWithProgress<UINT32, UINT32>> op;
82 hr =
stream->WriteAsync(tempBuffer.Get(), &op);
83 RETURN_IF_FAILED(
"Failed to write to stream",
return -1);
86 RETURN_IF_FAILED(
"Failed to write to stream",
return -1);
103 m_shuttingDown =
true;
106 ComPtr<IAsyncInfo>
info;
108 Q_ASSERT_SUCCEEDED(hr);
111 Q_ASSERT_SUCCEEDED(hr);
113 Q_ASSERT_SUCCEEDED(hr);
126 const QList<QByteArray> newData = std::move(m_pendingData);
127 m_pendingData.
clear();
134 ComPtr<IBuffer> tempBuffer;
136 Q_ASSERT_SUCCEEDED(hr);
137 ComPtr<IInputStream>
stream;
138 hr = m_socket->get_InputStream(&
stream);
139 Q_ASSERT_SUCCEEDED(hr);
140 hr =
stream->ReadAsync(tempBuffer.Get(),
READ_BUFFER_SIZE, InputStreamOptions_Partial, m_readOp.GetAddressOf());
141 Q_ASSERT_SUCCEEDED(hr);
142 QPointer<SocketWorker> thisPtr(
this);
143 hr = m_readOp->put_Completed(
145 AsyncStatus status) {
147 return thisPtr->onReadyRead(asyncInfo, status);
150 Q_ASSERT_SUCCEEDED(hr);
158 if (asyncInfo == m_readOp.Get())
166 if (status ==
Error || status == Canceled) {
171 ComPtr<IBuffer> tempBuffer;
172 HRESULT hr = asyncInfo->GetResults(&tempBuffer);
180 hr = tempBuffer->get_Length(&bufferLength);
195 ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
196 hr = tempBuffer.As(&byteArrayAccess);
203 hr = byteArrayAccess->Buffer(&
data);
210 QByteArray newData(
reinterpret_cast<const char*
>(
data),
int(bufferLength));
213 m_pendingData << newData;
215 UINT32 readBufferLength;
216 ComPtr<IInputStream>
stream;
217 hr = m_socket->get_InputStream(&
stream);
225 hr = tempBuffer->get_Capacity(&readBufferLength);
231 hr = tempBuffer->put_Length(0);
238 hr =
stream->ReadAsync(tempBuffer.Get(), readBufferLength, InputStreamOptions_Partial, &m_readOp);
240 qErrnoWarning(hr,
"onReadyRead(): Could not read into socket stream buffer.");
244 QPointer<SocketWorker> thisPtr(
this);
245 hr = m_readOp->put_Completed(
247 AsyncStatus status) {
249 return thisPtr->onReadyRead(asyncInfo, status);
253 qErrnoWarning(hr,
"onReadyRead(): Failed to set socket read callback.");
263 ComPtr<IStreamSocket> m_socket;
264 QList<QByteArray> m_pendingData;
265 bool m_shuttingDown =
false;
267 ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> m_readOp;
300 hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocket).Get(), &
m_socketObject);
302 qErrnoWarning(hr,
"ensureNativeSocket: Could not create socket instance");
313 QIODevice::OpenMode openMode)
318 errorString = QBluetoothSocket::tr(
"Unknown socket error");
323 HStringReference serviceNameReference(
reinterpret_cast<LPCWSTR
>(serviceName.
utf16()));
326 if (hr == E_ACCESSDENIED) {
327 qErrnoWarning(hr,
"QBluetoothSocketPrivateWinRT::connectToService: Unable to connect to bluetooth socket."
328 "Please check your manifest capabilities.");
332 Q_ASSERT_SUCCEEDED(hr);
336 hr =
m_connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
337 this, &QBluetoothSocketPrivateWinRT::handleConnectOpFinished).Get());
338 RETURN_VOID_IF_FAILED(
"connectToHostByName: Could not register \"connectOp\" callback");
347 errorString = QBluetoothSocket::tr(
"Unknown socket error");
353 HStringReference hostNameRef(
reinterpret_cast<LPCWSTR
>(addressString.utf16()));
354 ComPtr<IHostNameFactory> hostNameFactory;
355 HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
357 Q_ASSERT_SUCCEEDED(hr);
358 ComPtr<IHostName> remoteHost;
359 hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost);
360 RETURN_VOID_IF_FAILED(
"QBluetoothSocketPrivateWinRT::connectToService: Could not create hostname.");
372 qCWarning(QT_BT_WINDOWS) <<
"QBluetoothSocket::connectToService called on busy socket";
373 errorString = QBluetoothSocket::tr(
"Trying to connect while connection is in progress");
381 errorString = QBluetoothSocket::tr(
"Socket type not supported");
386 const QString connectionHostName = service.attribute(0xBEEF).toString();
387 const QString connectionServiceName = service.attribute(0xBEF0).toString();
388 if (service.protocolServiceMultiplexer() > 0) {
392 errorString = QBluetoothSocket::tr(
"Unknown socket error");
398 }
else if (!connectionHostName.isEmpty() && !connectionServiceName.isEmpty()) {
401 errorString = QBluetoothSocket::tr(
"Unknown socket error");
405 HStringReference hostNameRef(
reinterpret_cast<LPCWSTR
>(connectionHostName.utf16()));
406 ComPtr<IHostNameFactory> hostNameFactory;
407 HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
409 Q_ASSERT_SUCCEEDED(hr);
410 ComPtr<IHostName> remoteHost;
411 hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost);
413 }
else if (service.serverChannel() > 0) {
417 errorString = QBluetoothSocket::tr(
"Unknown socket error");
425 if (service.serviceUuid().isNull()
427 qCWarning(QT_BT_WINDOWS) <<
"No port, no PSM, and no UUID provided. Unable to connect";
430 qCDebug(QT_BT_WINDOWS) <<
"Need a port/psm, doing discovery";
441 qCWarning(QT_BT_WINDOWS) <<
"QBluetoothSocketPrivateWinRT::connectToService called on busy socket";
442 errorString = QBluetoothSocket::tr(
"Trying to connect while connection is in progress");
448 errorString = QBluetoothSocket::tr(
"Socket type not supported");
455 service.setDevice(
device);
456 service.setServiceUuid(uuid);
466 qCWarning(QT_BT_WINDOWS) <<
"QBluetoothSocketPrivateWinRT::connectToService called on busy socket";
467 errorString = QBluetoothSocket::tr(
"Trying to connect while connection is in progress");
473 errorString = QBluetoothSocket::tr(
"Socket type not supported");
488 this, &QBluetoothSocketPrivateWinRT::handleNewData);
490 this, &QBluetoothSocketPrivateWinRT::handleError);
503 emit q->readChannelFinished();
523 addressStr = addressStr.sliced(1, addressStr.size() - 2);
534 ComPtr<IStreamSocketInformation>
info;
536 Q_ASSERT_SUCCEEDED(hr);
537 ComPtr<IHostName> localHost;
538 hr =
info->get_LocalAddress(&localHost);
539 Q_ASSERT_SUCCEEDED(hr);
542 hr = localHost->get_CanonicalName(
localAddress.GetAddressOf());
543 Q_ASSERT_SUCCEEDED(hr);
555 ComPtr<IStreamSocketInformation>
info;
557 Q_ASSERT_SUCCEEDED(hr);
558 HString localPortString;
559 hr =
info->get_LocalPort(localPortString.GetAddressOf());
560 Q_ASSERT_SUCCEEDED(hr);
563 if (!
ok ||
port > UINT16_MAX) {
564 qCWarning(QT_BT_WINDOWS) <<
"Unexpected local port";
576 ComPtr<IStreamSocketInformation>
info;
578 Q_ASSERT_SUCCEEDED(hr);
579 ComPtr<IHostName> remoteHost;
580 hr =
info->get_RemoteHostName(&remoteHost);
581 Q_ASSERT_SUCCEEDED(hr);
583 HString remoteHostName;
584 hr = remoteHost->get_DisplayName(remoteHostName.GetAddressOf());
585 Q_ASSERT_SUCCEEDED(hr);
597 ComPtr<IStreamSocketInformation>
info;
599 Q_ASSERT_SUCCEEDED(hr);
600 ComPtr<IHostName> remoteHost;
601 hr =
info->get_RemoteAddress(&remoteHost);
602 Q_ASSERT_SUCCEEDED(hr);
604 HString remoteAddress;
605 hr = remoteHost->get_CanonicalName(remoteAddress.GetAddressOf());
606 Q_ASSERT_SUCCEEDED(hr);
618 ComPtr<IStreamSocketInformation>
info;
620 Q_ASSERT_SUCCEEDED(hr);
621 HString remotePortString;
622 hr =
info->get_RemotePort(remotePortString.GetAddressOf());
623 Q_ASSERT_SUCCEEDED(hr);
626 if (!
ok ||
port > UINT16_MAX) {
627 qCWarning(QT_BT_WINDOWS) <<
"Unexpected remote port";
638 errorString = QBluetoothSocket::tr(
"Cannot write while not connected");
643 ComPtr<IOutputStream>
stream;
646 Q_ASSERT_SUCCEEDED(hr);
651 errorString = QBluetoothSocket::tr(
"Cannot read while not connected");
664 errorString = QBluetoothSocket::tr(
"Cannot read while not connected");
670 if (maxSize > INT_MAX)
690 qCWarning(QT_BT_WINDOWS) <<
"No socket descriptor support on WinRT.";
704 q->setSocketState(socketState);
727void QBluetoothSocketPrivateWinRT::handleNewData(
const QList<QByteArray> &
data)
740 errorString = QBluetoothSocket::tr(
"Network error");
743 errorString = QBluetoothSocket::tr(
"Remote host closed connection");
746 errorString = QBluetoothSocket::tr(
"Unknown socket error");
754 emit q->readChannelFinished();
765 memcpy(writePointer, newData.data(),
size_t(newData.length()));
771HRESULT QBluetoothSocketPrivateWinRT::handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *action, ABI::Windows::Foundation::AsyncStatus status)
775 errorString = QBluetoothSocket::tr(
"Unknown socket error");
781 HRESULT hr = action->GetResults();
786 case HRESULT_FROM_WIN32(WSAETIMEDOUT):
792 case HRESULT_FROM_WIN32(WSAEHOSTUNREACH):
798 case HRESULT_FROM_WIN32(WSAECONNREFUSED):
805 errorString = QBluetoothSocket::tr(
"Unknown socket error");
814 ComPtr<IAsyncInfo>
info;
816 Q_ASSERT_SUCCEEDED(hr);
819 Q_ASSERT_SUCCEEDED(hr);
821 Q_ASSERT_SUCCEEDED(hr);
836#include "qbluetoothsocket_winrt.moc"
IOBluetoothDevice * device
Protocol
This enum describes the socket protocol used by the service.
QBluetoothSocket::OpenMode openMode
QBluetooth::SecurityFlags secFlags
QPrivateLinearBuffer rxBuffer
QBluetoothServiceInfo::Protocol socketType
QBluetoothSocket::SocketState state
void connectToServiceHelper(const QBluetoothAddress &address, quint16 port, QIODevice::OpenMode openMode) override
quint16 peerPort() const override
qint64 writeData(const char *data, qint64 maxSize) override
qint64 readData(char *data, qint64 maxSize) override
QString peerName() const override
Q_INVOKABLE void addToPendingData(const QList< QByteArray > &data)
QBluetoothAddress peerAddress() const override
Microsoft::WRL::ComPtr< ABI::Windows::Foundation::IAsyncAction > m_connectOp
bool ensureNativeSocket(QBluetoothServiceInfo::Protocol type) override
bool setSocketDescriptor(Microsoft::WRL::ComPtr< ABI::Windows::Networking::Sockets::IStreamSocket > socket, QBluetoothServiceInfo::Protocol socketType, QBluetoothSocket::SocketState socketState=QBluetoothSocket::SocketState::ConnectedState, QBluetoothSocket::OpenMode openMode=QBluetoothSocket::ReadWrite) override
Microsoft::WRL::ComPtr< ABI::Windows::Networking::Sockets::IStreamSocket > m_socketObject
QBluetoothAddress localAddress() const override
quint16 localPort() const override
qint64 bytesAvailable() const override
~QBluetoothSocketPrivateWinRT() override
void connectToService(const QBluetoothServiceInfo &service, QIODevice::OpenMode openMode) override
QBluetoothSocketPrivateWinRT()
QList< QByteArray > m_pendingData
bool canReadLine() const override
qint64 bytesToWrite() const override
QString localName() const override
SocketState
This enum describes the state of the Bluetooth socket.
SocketError
This enum describes Bluetooth socket error types.
@ UnsupportedProtocolError
bool isEmpty() const noexcept
void append(parameter_type t)
void unlock() noexcept
Unlocks this mutex locker.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
void deleteLater()
\threadsafe
qsizetype read(char *target, qsizetype size)
char * reserve(qsizetype size)
\macro QT_RESTRICTED_CAST_FROM_ASCII
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
static QString fromWCharArray(const wchar_t *string, qsizetype size=-1)
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Q_INVOKABLE void notifyAboutNewData()
HRESULT onReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status)
void setSocket(ComPtr< IStreamSocket > socket)
void newDataReceived(const QList< QByteArray > &data)
void socketErrorOccured(QBluetoothSocket::SocketError error)
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
static qint64 writeIOStream(ComPtr< IOutputStream > stream, const char *data, qint64 len)
IAsyncOperationWithProgressCompletedHandler< IBuffer *, UINT32 > SocketReadCompletedHandler
IAsyncOperationWithProgress< IBuffer *, UINT32 > IAsyncBufferOperation
static QString fromWinApiAddress(HString address)
static QString qt_QStringFromHString(const HString &string)
void mainThreadCoInit(void *caller)
void mainThreadCoUninit(void *caller)
DBusConnection const char DBusError * error
static QT_BEGIN_NAMESPACE const char * socketType(QSocketNotifier::Type type)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
#define Q_ARG(Type, data)
GLenum GLsizei GLuint GLint * bytesWritten
GLenum GLuint GLenum GLsizei length
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLuint64EXT address
GLdouble GLdouble GLdouble GLdouble q
myObject disconnect()
[26]
\inmodule QtCore \reentrant
ComPtr< IBufferFactory > bufferFactory