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);
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);
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);
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;
108 Q_ASSERT_SUCCEEDED(hr);
111 Q_ASSERT_SUCCEEDED(hr);
113 Q_ASSERT_SUCCEEDED(hr);
127 m_pendingData.
clear();
136 Q_ASSERT_SUCCEEDED(hr);
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);
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) {
172 HRESULT hr = asyncInfo->GetResults(&tempBuffer);
180 hr = tempBuffer->get_Length(&bufferLength);
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;
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.");
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.");
265 bool m_shuttingDown =
false;
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()));
355 HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
357 Q_ASSERT_SUCCEEDED(hr);
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()));
407 HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
409 Q_ASSERT_SUCCEEDED(hr);
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);
536 Q_ASSERT_SUCCEEDED(hr);
538 hr =
info->get_LocalAddress(&localHost);
539 Q_ASSERT_SUCCEEDED(hr);
542 hr = localHost->get_CanonicalName(
localAddress.GetAddressOf());
543 Q_ASSERT_SUCCEEDED(hr);
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";
578 Q_ASSERT_SUCCEEDED(hr);
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);
599 Q_ASSERT_SUCCEEDED(hr);
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);
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");
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);
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");
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
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
const ushort * utf16() const
Returns the QString as a '\0\'-terminated array of unsigned shorts.
qsizetype size() const
Returns the number of characters in this string.
uint toUInt(bool *ok=nullptr, int base=10) const
Returns the string converted to an {unsigned int} using base base, which is 10 by default and must be...
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
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...
QString sliced(qsizetype pos) const
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
QFileInfo info(fileName)
[8]
myObject disconnect()
[26]
\inmodule QtCore \reentrant
ComPtr< IBufferFactory > bufferFactory