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(QBluetoothSocket *qq)
69 : QBluetoothSocketBasePrivate{qq}
71 secFlags = QBluetooth::Security::Secure;
74 &m_bluetoothSocketProxy, &QtOhosBluetooth::QOhosBluetoothSocketProxy::connected,
76 [
this](
int socketDescriptor) {
77 if (state != QBluetoothSocket::SocketState::ConnectingState)
80 socket = socketDescriptor;
81 q_ptr->setOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered);
82 q_ptr->setSocketState(QBluetoothSocket::SocketState::ConnectedState);
84 if (!rxBuffer.isEmpty())
85 Q_EMIT q_ptr->readyRead();
89 &m_bluetoothSocketProxy, &QtOhosBluetooth::QOhosBluetoothSocketProxy::disconnected,
92 onProxyDisconnected();
96 &m_bluetoothSocketProxy, &QtOhosBluetooth::QOhosBluetoothSocketProxy::dataReceived,
98 [
this](
const QByteArray &receivedData) {
99 if (state != QBluetoothSocket::SocketState::ConnectingState
100 && state != QBluetoothSocket::SocketState::ConnectedState) {
104 char *target = rxBuffer.reserve(receivedData.size());
105 std::memcpy(target, receivedData.constData(), receivedData.size());
107 if (state == QBluetoothSocket::SocketState::ConnectedState)
108 Q_EMIT q_ptr->readyRead();
112 &m_bluetoothSocketProxy, &QtOhosBluetooth::QOhosBluetoothSocketProxy::errorOccurred,
114 [
this](QOhosBluetoothErrorCode errorCode) {
115 onProxyError(errorCode);
119QBluetoothSocketPrivateOhos::~QBluetoothSocketPrivateOhos()
124void QBluetoothSocketPrivateOhos::onProxyError(QOhosBluetoothErrorCode errorCode)
126 const auto report = makeSocketErrorReport(errorCode);
128 errorString = report.message;
129 q_ptr->setSocketError(report.error);
131 if (state == QBluetoothSocket::SocketState::ConnectingState
132 || state == QBluetoothSocket::SocketState::ClosingState) {
133 socket = QtOhosBluetooth::invalidSocketDescriptor;
134 q_ptr->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
138void QBluetoothSocketPrivateOhos::onProxyDisconnected()
140 socket = QtOhosBluetooth::invalidSocketDescriptor;
141 q_ptr->setOpenMode(QIODevice::NotOpen);
142 q_ptr->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
143 Q_EMIT q_ptr->readChannelFinished();
146bool QBluetoothSocketPrivateOhos::ensureNativeSocket(QBluetoothServiceInfo::Protocol type)
150 return type == QBluetoothServiceInfo::RfcommProtocol;
153void QBluetoothSocketPrivateOhos::connectToServiceHelper(
154 const QBluetoothAddress &address,
const QBluetoothUuid &uuid, QIODevice::OpenMode openMode)
156 if (openMode != QIODevice::ReadWrite)
157 qCWarning(QT_BT_OHOS,
"%s: Only read-write socket mode supported.", Q_FUNC_INFO);
159 if (state != QBluetoothSocket::SocketState::UnconnectedState) {
160 qCWarning(QT_BT_OHOS,
"%s: Called on busy socket", Q_FUNC_INFO);
161 errorString = QBluetoothSocket::tr(
"Trying to connect while connection is established");
162 q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError);
167 q_ptr->setSocketState(QBluetoothSocket::SocketState::ConnectingState);
169 const auto secure = (secFlags != QBluetooth::Security::NoSecurity);
171 const auto connectRequested = m_bluetoothSocketProxy.connect(
172 address.toString(), uuid.toString(QUuid::WithoutBraces), secure);
174 if (!connectRequested)
175 q_ptr->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
178void QBluetoothSocketPrivateOhos::connectToService(
179 const QBluetoothServiceInfo &serviceInfo, QIODevice::OpenMode openMode)
181 const auto protocol = serviceInfo.socketProtocol() != QBluetoothServiceInfo::UnknownProtocol
182 ? serviceInfo.socketProtocol()
183 : q_ptr->socketType();
185 if (!ensureNativeSocket(protocol)) {
186 qCWarning(QT_BT_OHOS,
"%s: Only RfcommProtocol supported", Q_FUNC_INFO);
187 errorString = QBluetoothSocket::tr(
"Socket type not supported");
188 q_ptr->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
192 connectToServiceHelper(serviceInfo.device().address(), serviceInfo.serviceUuid(), openMode);
195void QBluetoothSocketPrivateOhos::connectToService(
196 const QBluetoothAddress &address,
const QBluetoothUuid &uuid, QIODevice::OpenMode openMode)
198 if (!ensureNativeSocket(q_ptr->socketType())) {
199 qCWarning(QT_BT_OHOS,
"%s: Only RfcommProtocol supported", Q_FUNC_INFO);
200 errorString = QBluetoothSocket::tr(
"Socket type not supported");
201 q_ptr->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
205 connectToServiceHelper(address, uuid, openMode);
208void QBluetoothSocketPrivateOhos::connectToService(
209 const QBluetoothAddress &, quint16, QIODevice::OpenMode)
212 QT_BT_OHOS,
"%s: HarmonyOS connects to a service by its UUID, not by an RFCOMM port",
214 errorString = QBluetoothSocket::tr(
"Connecting to a port is not supported");
215 q_ptr->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
218void QBluetoothSocketPrivateOhos::abort()
223QString QBluetoothSocketPrivateOhos::localName()
const
225 const auto optLocalDeviceName =
226 QtOhosBluetooth::QOhosBluetoothLocalDeviceProxy::instance()->tryGetLocalDeviceName();
227 return optLocalDeviceName
228 ? *optLocalDeviceName
232QBluetoothAddress QBluetoothSocketPrivateOhos::localAddress()
const
237quint16 QBluetoothSocketPrivateOhos::localPort()
const
242QString QBluetoothSocketPrivateOhos::peerName()
const
244 const auto optName = m_bluetoothSocketProxy.tryGetPeerDeviceName();
250QBluetoothAddress QBluetoothSocketPrivateOhos::peerAddress()
const
252 const auto optAddress = m_bluetoothSocketProxy.tryGetPeerDeviceAddress();
254 ? QBluetoothAddress(*optAddress)
255 : QBluetoothAddress();
258quint16 QBluetoothSocketPrivateOhos::peerPort()
const
263qint64 QBluetoothSocketPrivateOhos::writeData(
const char *data, qint64 maxSize)
265 if (state != QBluetoothSocket::SocketState::ConnectedState) {
266 errorString = QBluetoothSocket::tr(
"No SPP connection between devices. Cannot write.");
267 q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError);
271 if (!m_bluetoothSocketProxy.write(data, maxSize))
274 QMetaObject::invokeMethod(
277 Q_EMIT q_ptr->bytesWritten(maxSize);
279 Qt::QueuedConnection);
284qint64 QBluetoothSocketPrivateOhos::readData(
char *data, qint64 maxSize)
286 if (!rxBuffer.isEmpty())
287 return rxBuffer.read(data, q26::saturate_cast<qsizetype>(maxSize));
289 if (state != QBluetoothSocket::SocketState::ConnectedState) {
290 errorString = QBluetoothSocket::tr(
"Cannot read while not connected");
291 q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError);
298void QBluetoothSocketPrivateOhos::close()
300 m_bluetoothSocketProxy.close();
303bool QBluetoothSocketPrivateOhos::setSocketDescriptor(
304 int socketDescriptor, QBluetoothServiceInfo::Protocol type,
305 QBluetoothSocket::SocketState socketState, QBluetoothSocket::OpenMode openMode)
307 if (openMode != QIODevice::ReadWrite)
308 qCWarning(QT_BT_OHOS,
"%s: Only read-write socket mode supported.", Q_FUNC_INFO);
310 if (!ensureNativeSocket(type)) {
311 qCWarning(QT_BT_OHOS,
"%s: Only RfcommProtocol supported", Q_FUNC_INFO);
312 errorString = QBluetoothSocket::tr(
"Socket type not supported");
313 q_ptr->setSocketError(QBluetoothSocket::SocketError::UnsupportedProtocolError);
317 if (socketState != QBluetoothSocket::SocketState::ConnectedState) {
319 QT_BT_OHOS,
"%s: a socket accepted by the server can only be taken over as connected",
321 errorString = QBluetoothSocket::tr(
"Taking over the socket failed");
322 q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError);
326 if (state != QBluetoothSocket::SocketState::UnconnectedState
327 || socket != QtOhosBluetooth::invalidSocketDescriptor) {
328 qCWarning(QT_BT_OHOS,
"%s: Called on busy socket", Q_FUNC_INFO);
329 errorString = QBluetoothSocket::tr(
"Trying to connect while connection is in progress");
330 q_ptr->setSocketError(QBluetoothSocket::SocketError::OperationError);
335 QtOhosBluetooth::QOhosBluetoothSocketProxy::takePendingSocketHandle(socketDescriptor);
338 QT_BT_OHOS,
"%s: no socket accepted by the server for descriptor %d", Q_FUNC_INFO,
340 errorString = QBluetoothSocket::tr(
"Taking over the socket failed");
341 q_ptr->setSocketError(QBluetoothSocket::SocketError::UnknownSocketError);
342 q_ptr->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
348 if (!m_bluetoothSocketProxy.takeOverSocket(std::move(socketHandle))) {
349 errorString = QBluetoothSocket::tr(
"Obtaining data channel for service failed");
350 q_ptr->setSocketError(QBluetoothSocket::SocketError::NetworkError);
351 q_ptr->setSocketState(QBluetoothSocket::SocketState::UnconnectedState);
355 socket = socketDescriptor;
356 q_ptr->setOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered);
357 q_ptr->setSocketState(socketState);
362qint64 QBluetoothSocketPrivateOhos::bytesAvailable()
const
364 return rxBuffer.size();
367bool QBluetoothSocketPrivateOhos::canReadLine()
const
369 return rxBuffer.canReadLine();
372qint64 QBluetoothSocketPrivateOhos::bytesToWrite()
const