6#include <QtBluetooth/qbluetoothdeviceinfo.h>
7#include <QtBluetooth/qbluetoothsocket.h>
8#include <QtBluetooth/private/qohosbluetoothlocaldevice_p.h>
9#include <QtBluetooth/private/qohosbluetoothsocket_p.h>
11#include <QtCore/q26numeric.h>
12#include <QtCore/qloggingcategory.h>
18using QtOhosBluetooth::QOhosBluetoothErrorCode;
20Q_DECLARE_LOGGING_CATEGORY(QT_BT_OHOS)
24struct SocketErrorReport
26 QBluetoothSocket::SocketError error = QBluetoothSocket::SocketError::UnknownSocketError;
30SocketErrorReport makeSocketErrorReport(QOhosBluetoothErrorCode errorCode)
33 case QOhosBluetoothErrorCode::PermissionDenied:
35 .error = QBluetoothSocket::SocketError::MissingPermissionsError,
36 .message = QBluetoothSocket::tr(
"Missing permissions for socket operation")};
37 case QOhosBluetoothErrorCode::InvalidParameter:
39 .error = QBluetoothSocket::SocketError::OperationError,
40 .message = QBluetoothSocket::tr(
"Socket operation rejected by the system")};
41 case QOhosBluetoothErrorCode::CapabilityNotSupported:
42 case QOhosBluetoothErrorCode::ProfileNotSupported:
44 .error = QBluetoothSocket::SocketError::UnsupportedProtocolError,
45 .message = QBluetoothSocket::tr(
"Socket type not supported")};
46 case QOhosBluetoothErrorCode::InputOutput:
48 .error = QBluetoothSocket::SocketError::UnknownSocketError,
49 .message = QBluetoothSocket::tr(
"I/O error on socket")};
50 case QOhosBluetoothErrorCode::ServiceStopped:
51 case QOhosBluetoothErrorCode::BluetoothDisabled:
53 .error = QBluetoothSocket::SocketError::NetworkError,
54 .message = QBluetoothSocket::tr(
"Bluetooth is not available")};
55 case QOhosBluetoothErrorCode::UserDidNotRespond:
56 case QOhosBluetoothErrorCode::UserRefused:
57 case QOhosBluetoothErrorCode::OperationFailed:
62 .error = QBluetoothSocket::SocketError::OperationError,
63 .message = QBluetoothSocket::tr(
"Operation failed on socket")};
68QBluetoothSocketPrivateOhos::QBluetoothSocketPrivateOhos()
70 secFlags = QBluetooth::Security::Secure;
73 &m_bluetoothSocketProxy, &QtOhosBluetooth::QOhosBluetoothSocketProxy::connected,
75 [
this](
int socketDescriptor) {
76 if (state != QBluetoothSocket::SocketState::ConnectingState)
79 socket = socketDescriptor;
80 q_ptr->setOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered);
81 q_ptr->setSocketState(QBluetoothSocket::SocketState::ConnectedState);
83 if (!rxBuffer.isEmpty())
84 Q_EMIT q_ptr->readyRead();
88 &m_bluetoothSocketProxy, &QtOhosBluetooth::QOhosBluetoothSocketProxy::disconnected,
91 onProxyDisconnected();
95 &m_bluetoothSocketProxy, &QtOhosBluetooth::QOhosBluetoothSocketProxy::dataReceived,
97 [
this](
const QByteArray &receivedData) {
98 if (state != QBluetoothSocket::SocketState::ConnectingState
99 && state != QBluetoothSocket::SocketState::ConnectedState) {
103 char *target = rxBuffer.reserve(receivedData.size());
104 std::memcpy(target, receivedData.constData(), receivedData.size());
106 if (state == QBluetoothSocket::SocketState::ConnectedState)
107 Q_EMIT q_ptr->readyRead();
111 &m_bluetoothSocketProxy, &QtOhosBluetooth::QOhosBluetoothSocketProxy::errorOccurred,
113 [
this](QOhosBluetoothErrorCode errorCode) {
114 onProxyError(errorCode);
118QBluetoothSocketPrivateOhos::~QBluetoothSocketPrivateOhos()
123void QBluetoothSocketPrivateOhos::onProxyError(QOhosBluetoothErrorCode errorCode)
125 const auto report = makeSocketErrorReport(errorCode);
127 errorString = report.message;
128 q_ptr->setSocketError(report.error);
130 if (state == QBluetoothSocket::SocketState::ConnectingState
131 || state == QBluetoothSocket::SocketState::ClosingState) {
132 socket = QtOhosBluetooth::invalidSocketDescriptor;
133 q_ptr->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
137void QBluetoothSocketPrivateOhos::onProxyDisconnected()
139 socket = QtOhosBluetooth::invalidSocketDescriptor;
140 q_ptr->setOpenMode(QIODevice::NotOpen);
141 q_ptr->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
142 Q_EMIT q_ptr->readChannelFinished();
145bool QBluetoothSocketPrivateOhos::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
149 return type == QBluetoothServiceInfo::RfcommProtocol;
152void QBluetoothSocketPrivateOhos::connectToServiceHelper(
153 const QBluetoothAddress &address,
const QBluetoothUuid &uuid, QIODevice::OpenMode openMode)
155 if (openMode != QIODevice::ReadWrite)
156 qCWarning(QT_BT_OHOS,
"%s: Only read-write socket mode supported.", Q_FUNC_INFO);
158 if (state != QBluetoothSocket::SocketState::UnconnectedState) {
159 qCWarning(QT_BT_OHOS,
"%s: Called on busy socket", Q_FUNC_INFO);
160 errorString = QBluetoothSocket::tr(
"Trying to connect while connection is established");
161 q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError);
166 q_ptr->setSocketState(QBluetoothSocket::SocketState::ConnectingState);
168 const auto secure = (secFlags != QBluetooth::Security::NoSecurity);
170 const auto connectRequested = m_bluetoothSocketProxy.connect(
171 address.toString(), uuid.toString(QUuid::WithoutBraces), secure);
173 if (!connectRequested)
174 q_ptr->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
177void QBluetoothSocketPrivateOhos::connectToService(
178 const QBluetoothServiceInfo &serviceInfo, QIODevice::OpenMode openMode)
180 const auto protocol = serviceInfo.socketProtocol() != QBluetoothServiceInfo::UnknownProtocol
181 ? serviceInfo.socketProtocol()
182 : q_ptr->socketType();
184 if (!ensureNativeSocket(protocol)) {
185 qCWarning(QT_BT_OHOS,
"%s: Only RfcommProtocol supported", Q_FUNC_INFO);
186 errorString = QBluetoothSocket::tr(
"Socket type not supported");
187 q_ptr->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
191 connectToServiceHelper(serviceInfo.device().address(), serviceInfo.serviceUuid(), openMode);
194void QBluetoothSocketPrivateOhos::connectToService(
195 const QBluetoothAddress &address,
const QBluetoothUuid &uuid, QIODevice::OpenMode openMode)
197 if (!ensureNativeSocket(q_ptr->socketType())) {
198 qCWarning(QT_BT_OHOS,
"%s: Only RfcommProtocol supported", Q_FUNC_INFO);
199 errorString = QBluetoothSocket::tr(
"Socket type not supported");
200 q_ptr->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
204 connectToServiceHelper(address, uuid, openMode);
207void QBluetoothSocketPrivateOhos::connectToService(
208 const QBluetoothAddress &, quint16, QIODevice::OpenMode)
211 QT_BT_OHOS,
"%s: HarmonyOS connects to a service by its UUID, not by an RFCOMM port",
213 errorString = QBluetoothSocket::tr(
"Connecting to a port is not supported");
214 q_ptr->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
217void QBluetoothSocketPrivateOhos::abort()
222QString QBluetoothSocketPrivateOhos::localName()
const
224 const auto optLocalDeviceName =
225 QtOhosBluetooth::QOhosBluetoothLocalDeviceProxy::instance()->tryGetLocalDeviceName();
226 return optLocalDeviceName
227 ? *optLocalDeviceName
231QBluetoothAddress QBluetoothSocketPrivateOhos::localAddress()
const
236quint16 QBluetoothSocketPrivateOhos::localPort()
const
241QString QBluetoothSocketPrivateOhos::peerName()
const
243 const auto optName = m_bluetoothSocketProxy.tryGetPeerDeviceName();
249QBluetoothAddress QBluetoothSocketPrivateOhos::peerAddress()
const
251 const auto optAddress = m_bluetoothSocketProxy.tryGetPeerDeviceAddress();
253 ? QBluetoothAddress(*optAddress)
254 : QBluetoothAddress();
257quint16 QBluetoothSocketPrivateOhos::peerPort()
const
262qint64 QBluetoothSocketPrivateOhos::writeData(
const char *data, qint64 maxSize)
264 if (state != QBluetoothSocket::SocketState::ConnectedState) {
265 errorString = QBluetoothSocket::tr(
"No SPP connection between devices. Cannot write.");
266 q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError);
270 if (!m_bluetoothSocketProxy.write(data, maxSize))
273 QMetaObject::invokeMethod(
276 Q_EMIT q_ptr->bytesWritten(maxSize);
278 Qt::QueuedConnection);
283qint64 QBluetoothSocketPrivateOhos::readData(
char *data, qint64 maxSize)
285 if (!rxBuffer.isEmpty())
286 return rxBuffer.read(data, q26::saturate_cast<qsizetype>(maxSize));
288 if (state != QBluetoothSocket::SocketState::ConnectedState) {
289 errorString = QBluetoothSocket::tr(
"Cannot read while not connected");
290 q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError);
297void QBluetoothSocketPrivateOhos::close()
299 m_bluetoothSocketProxy.close();
302bool QBluetoothSocketPrivateOhos::setSocketDescriptor(
303 int socketDescriptor, QBluetoothServiceInfo::Protocol type,
304 QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
306 if (openMode != QIODevice::ReadWrite)
307 qCWarning(QT_BT_OHOS,
"%s: Only read-write socket mode supported.", Q_FUNC_INFO);
309 if (!ensureNativeSocket(type)) {
310 qCWarning(QT_BT_OHOS,
"%s: Only RfcommProtocol supported", Q_FUNC_INFO);
311 errorString = QBluetoothSocket::tr(
"Socket type not supported");
312 q_ptr->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
316 if (socketState != QBluetoothSocket::SocketState::ConnectedState) {
318 QT_BT_OHOS,
"%s: a socket accepted by the server can only be taken over as connected",
320 errorString = QBluetoothSocket::tr(
"Taking over the socket failed");
321 q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError);
325 if (state != QBluetoothSocket::SocketState::UnconnectedState
326 || socket != QtOhosBluetooth::invalidSocketDescriptor) {
327 qCWarning(QT_BT_OHOS,
"%s: Called on busy socket", Q_FUNC_INFO);
328 errorString = QBluetoothSocket::tr(
"Trying to connect while connection is in progress");
329 q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError);
334 QtOhosBluetooth::QOhosBluetoothSocketProxy::takePendingSocketHandle(socketDescriptor);
337 QT_BT_OHOS,
"%s: no socket accepted by the server for descriptor %d", Q_FUNC_INFO,
339 errorString = QBluetoothSocket::tr(
"Taking over the socket failed");
340 q_ptr->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
341 q_ptr->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
347 if (!m_bluetoothSocketProxy.takeOverSocket(std::move(socketHandle))) {
348 errorString = QBluetoothSocket::tr(
"Obtaining data channel for service failed");
349 q_ptr->setSocketError(QBluetoothSocket::SocketError::NetworkError);
350 q_ptr->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
354 socket = socketDescriptor;
355 q_ptr->setOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered);
356 q_ptr->setSocketState(socketState);
361qint64 QBluetoothSocketPrivateOhos::bytesAvailable()
const
363 return rxBuffer.size();
366bool QBluetoothSocketPrivateOhos::canReadLine()
const
368 return rxBuffer.canReadLine();
371qint64 QBluetoothSocketPrivateOhos::bytesToWrite()
const