Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qbluetoothserver_ohos.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtBluetooth/qbluetoothserver.h>
7#include <QtBluetooth/qbluetoothsocket.h>
8#include <QtBluetooth/private/qbluetoothserver_p.h>
9#include <QtBluetooth/private/qohosbluetoothaccess_p.h>
10#include <QtBluetooth/private/qohosbluetoothcommon_p.h>
11#include <QtBluetooth/private/qohosbluetoothserver_p.h>
12#include <QtBluetooth/private/qohosbluetoothsocket_p.h>
13
14#include <QtCore/q20utility.h>
15#include <QtCore/qloggingcategory.h>
16
17#include <memory>
18
20
21using QtOhosBluetooth::QOhosBluetoothErrorCode;
22
23Q_DECLARE_LOGGING_CATEGORY(QT_BT_OHOS)
24
25namespace {
26
27QBluetoothServer::Error mapToServerError(QOhosBluetoothErrorCode errorCode)
28{
29 switch (errorCode) {
30 case QOhosBluetoothErrorCode::PermissionDenied:
31 return QBluetoothServer::MissingPermissionsError;
32 case QOhosBluetoothErrorCode::CapabilityNotSupported:
33 case QOhosBluetoothErrorCode::ProfileNotSupported:
34 return QBluetoothServer::UnsupportedProtocolError;
35 case QOhosBluetoothErrorCode::InputOutput:
36 return QBluetoothServer::InputOutputError;
37 case QOhosBluetoothErrorCode::BluetoothDisabled:
38 case QOhosBluetoothErrorCode::ServiceStopped:
39 return QBluetoothServer::PoweredOffError;
40 case QOhosBluetoothErrorCode::InvalidParameter:
41 case QOhosBluetoothErrorCode::UserDidNotRespond:
42 case QOhosBluetoothErrorCode::UserRefused:
43 case QOhosBluetoothErrorCode::OperationFailed:
44 break;
45 }
46
47 return QBluetoothServer::UnknownError;
48}
49
50}
51
52QBluetoothServerPrivate::QBluetoothServerPrivate(
53 QBluetoothServiceInfo::Protocol sType, QBluetoothServer *parent)
54 : serverType(sType)
55 , q_ptr(parent)
56{
57}
58
59QBluetoothServerPrivate::~QBluetoothServerPrivate() = default;
60
61bool QBluetoothServerPrivate::isListening() const
62{
63 return socket != nullptr && socket->state() == QBluetoothSocket::SocketState::ListeningState;
64}
65
66void QBluetoothServerPrivate::resetServerContext()
67{
68 socket = nullptr;
69 m_bluetoothServerProxyContext.reset();
70}
71
72void QBluetoothServer::close()
73{
74 d_ptr->resetServerContext();
75}
76
77bool QBluetoothServer::listen(const QBluetoothAddress &address, quint16 port)
78{
79 if (!address.isNull()) {
80 qCWarning(
81 QT_BT_OHOS,
82 "%s: HarmonyOS does not support multi device adapters. Ignoring local adapter address ...",
83 Q_FUNC_INFO);
84 }
85
86 const auto reportError = [this](Error error) {
87 d_ptr->m_lastError = error;
88 QMetaObject::invokeMethod(
89 this,
90 [this, error]() {
91 Q_EMIT errorOccurred(error);
92 },
93 Qt::QueuedConnection);
94 };
95
96 if (serverType() != QBluetoothServiceInfo::RfcommProtocol) {
97 reportError(UnsupportedProtocolError);
98 return false;
99 }
100
101 if (!QtOhosBluetooth::checkAccessBluetoothPermissionGranted(Q_FUNC_INFO)) {
102 reportError(MissingPermissionsError);
103 return false;
104 }
105
106 auto accessProxy = QtOhosBluetooth::QOhosBluetoothAccessProxy::instance();
107 if (accessProxy->tryGetBluetoothState()
108 != QtOhosBluetooth::QOhosBluetoothAccessProxy::BluetoothState::STATE_ON) {
109 reportError(PoweredOffError);
110 return false;
111 }
112
113 if (isListening()) {
114 reportError(ServiceAlreadyRegisteredError);
115 return false;
116 }
117
118 if (d_ptr->m_bluetoothServerProxyContext
119 && !d_ptr->m_bluetoothServerProxyContext->bluetoothServerProxy->isServiceRegistered()) {
120 d_ptr->resetServerContext();
121 }
122
123 if (!d_ptr->m_bluetoothServerProxyContext) {
124 d_ptr->m_bluetoothServerProxyContext = QtOhosBluetooth::makeServerProxyContext(port);
125 if (!d_ptr->m_bluetoothServerProxyContext) {
126 reportError(ServiceAlreadyRegisteredError);
127 return false;
128 }
129 d_ptr->m_bluetoothServerProxyContext->securityFlags = d_ptr->securityFlags;
130 d_ptr->socket = d_ptr->m_bluetoothServerProxyContext->bluetoothSocket.get();
131
132 auto serverProxy = d_ptr->m_bluetoothServerProxyContext->bluetoothServerProxy.get();
133
134 QObject::connect(
135 serverProxy, &QtOhosBluetooth::QOhosBluetoothServerProxy::clientAccepted,
136 this,
137 [this](int clientSocketDescriptor) {
138 auto context = d_ptr->m_bluetoothServerProxyContext;
139 if (!context) {
140 QtOhosBluetooth::QOhosBluetoothSocketProxy::dropPendingSocketHandle(
141 clientSocketDescriptor);
142 return;
143 }
144
145 if (q20::cmp_greater_equal(
146 context->pendingConnectionSockets.size(),
147 d_ptr->maxPendingConnections)) {
148 qCDebug(
149 QT_BT_OHOS,
150 "%s: maximum number of pending connections reached. Rejecting the client ...",
151 Q_FUNC_INFO);
152 QtOhosBluetooth::QOhosBluetoothSocketProxy::dropPendingSocketHandle(
153 clientSocketDescriptor);
154 return;
155 }
156
157 auto pendingConnectionSocket = std::make_unique<QBluetoothSocket>();
158 const auto socketDescriptorSet = pendingConnectionSocket->setSocketDescriptor(
159 clientSocketDescriptor, QBluetoothServiceInfo::RfcommProtocol,
160 QBluetoothSocket::SocketState::ConnectedState, QBluetoothSocket::ReadWrite);
161
162 if (!socketDescriptorSet) {
163 QtOhosBluetooth::QOhosBluetoothSocketProxy::dropPendingSocketHandle(
164 clientSocketDescriptor);
165 return;
166 }
167
168 context->pendingConnectionSockets.push_back(std::move(pendingConnectionSocket));
169 Q_EMIT newConnection();
170 });
171
172 QObject::connect(
173 serverProxy, &QtOhosBluetooth::QOhosBluetoothServerProxy::errorOccurred,
174 this,
175 [this](QOhosBluetoothErrorCode errorCode) {
176 d_ptr->m_lastError = mapToServerError(errorCode);
177 Q_EMIT errorOccurred(d_ptr->m_lastError);
178 });
179
180 QObject::connect(
181 serverProxy, &QtOhosBluetooth::QOhosBluetoothServerProxy::acceptingStopped,
182 this,
183 [this]() {
184 auto context = d_ptr->m_bluetoothServerProxyContext;
185 if (context && context->bluetoothServerProxy->isServiceRegistered())
186 return;
187
188 if (d_ptr->socket)
189 d_ptr->socket->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
190 });
191 }
192
193 d_ptr->socket->setSocketState(QBluetoothSocket::SocketState::ListeningState);
194 return true;
195}
196
197void QBluetoothServer::setMaxPendingConnections(int numConnections)
198{
199 d_ptr->maxPendingConnections = numConnections;
200}
201
202bool QBluetoothServer::hasPendingConnections() const
203{
204 auto context = d_ptr->m_bluetoothServerProxyContext;
205 return context && !context->pendingConnectionSockets.empty();
206}
207
208QBluetoothSocket *QBluetoothServer::nextPendingConnection()
209{
210 auto context = d_ptr->m_bluetoothServerProxyContext;
211 if (!context || context->pendingConnectionSockets.empty())
212 return nullptr;
213
214 auto pendingConnectionSocket = std::move(context->pendingConnectionSockets.front());
215 context->pendingConnectionSockets.pop_front();
216
217 return pendingConnectionSocket.release();
218}
219
220QBluetoothAddress QBluetoothServer::serverAddress() const
221{
222 return {};
223}
224
225quint16 QBluetoothServer::serverPort() const
226{
227 auto context = d_ptr->m_bluetoothServerProxyContext;
228 return context ? context->port : 0;
229}
230
231void QBluetoothServer::setSecurityFlags(QBluetooth::SecurityFlags security)
232{
233 if (isListening()) {
234 qCWarning(
235 QT_BT_OHOS,
236 "%s: the security flags must be set before listen(). Ignoring the new flags ...",
237 Q_FUNC_INFO);
238 return;
239 }
240
241 d_ptr->securityFlags = security;
242}
243
244QBluetooth::SecurityFlags QBluetoothServer::securityFlags() const
245{
246 return d_ptr->securityFlags;
247}
248
249QT_END_NAMESPACE
Combined button and popup list for selecting options.