1#include <QtCore/QMetaObject>
2#include <QtCore/QPointer>
3#include <QtCore/QScopeGuard>
16 qCDebug(AndroidSerialPortLog) <<
"Opening" << systemLocation;
23 qCWarning(AndroidSerialPortLog) <<
"Error opening" << systemLocation;
29 if (descriptor == -1) {
30 qCWarning(AndroidSerialPortLog) <<
"Failed to get device handle for" << systemLocation;
36 if (!_setParameters(inputBaudRate, dataBits, stopBits, parity)) {
37 qCWarning(AndroidSerialPortLog) <<
"Failed to set serial port parameters for" << systemLocation;
42 if (!setFlowControl(flowControl)) {
43 qCWarning(AndroidSerialPortLog) <<
"Failed to set serial port flow control for" << systemLocation;
48 if (mode & QIODevice::ReadOnly) {
49 if (!startAsyncRead()) {
50 qCWarning(AndroidSerialPortLog) <<
"Failed to start async read for" << systemLocation;
54 }
else if (mode & QIODevice::WriteOnly) {
55 if (!_stopAsyncRead()) {
56 qCWarning(AndroidSerialPortLog) <<
"Failed to stop async read for" << systemLocation;
74 qCWarning(AndroidSerialPortLog) <<
"Failed to close device with ID" << _deviceId;
87 qCWarning(AndroidSerialPortLog) <<
"Exception arrived on device ID" << _deviceId <<
":" << ex;
96 qCWarning(AndroidSerialPortLog) <<
"Failed to start async read thread for device ID" << _deviceId;
104 _scheduleReadyRead();
109bool QSerialPortPrivate::_stopAsyncRead()
116 qCWarning(AndroidSerialPortLog) <<
"Failed to stop async read thread for device ID" << _deviceId;
124qint64 QSerialPortPrivate::_drainPendingDataLocked(qint64 maxBytes)
126 const qsizetype pendingSize = _pendingSizeLocked();
127 if (pendingSize <= 0) {
128 _pendingData.clear();
129 _pendingDataOffset = 0;
133 qint64 toDrain = pendingSize;
135 toDrain = qMin(toDrain, maxBytes);
142 buffer.append(_pendingData.constData() + _pendingDataOffset, toDrain);
143 _pendingDataOffset +=
static_cast<qsizetype
>(toDrain);
145 if (_pendingDataOffset >= _pendingData.size()) {
146 _pendingData.clear();
147 _pendingDataOffset = 0;
151 constexpr qsizetype kCompactThreshold = 4096;
152 if (_pendingDataOffset >= kCompactThreshold && (_pendingDataOffset * 2) >= _pendingData.size()) {
153 _compactPendingDataLocked();
157 _bufferBytesEstimate.store(buffer.size(), std::memory_order_relaxed);
161qsizetype QSerialPortPrivate::_pendingSizeLocked()
const
163 return qMax<qsizetype>(0, _pendingData.size() - _pendingDataOffset);
166void QSerialPortPrivate::_compactPendingDataLocked()
168 if (_pendingDataOffset <= 0) {
172 if (_pendingDataOffset >= _pendingData.size()) {
173 _pendingData.clear();
174 _pendingDataOffset = 0;
178 _pendingData.remove(0, _pendingDataOffset);
179 _pendingDataOffset = 0;
186 qint64 droppedBytes = 0;
188 QMutexLocker locker(&_readMutex);
189 int bytesToRead = length;
191 const qint64 totalBuffered = _pendingSizeLocked() + _bufferBytesEstimate.load(std::memory_order_relaxed);
193 if (bytesToRead > headroom) {
194 bytesToRead =
static_cast<int>(qMax(qint64(0), headroom));
195 droppedBytes =
static_cast<qint64
>(length - bytesToRead);
199 if (bytesToRead > 0) {
200 constexpr qsizetype kCompactBeforeAppendThreshold = 8192;
201 if (_pendingDataOffset >= kCompactBeforeAppendThreshold) {
202 _compactPendingDataLocked();
204 _pendingData.append(bytes, bytesToRead);
205 _readWaitCondition.wakeAll();
209 if (droppedBytes > 0) {
210 qCWarning(AndroidSerialPortLog) <<
"Read buffer full, dropping" << droppedBytes <<
"bytes";
213 if (bytesToRead <= 0) {
217 _scheduleReadyRead();
220void QSerialPortPrivate::_scheduleReadyRead()
224 if (!_readyReadPending.exchange(
true)) {
225 QPointer<QSerialPort> guard(q);
226 QMetaObject::invokeMethod(
233 QMutexLocker locker(&_readMutex);
234 if (_pendingSizeLocked() <= 0) {
235 _readyReadPending.store(
false);
242 (void)_drainPendingDataLocked(canAccept);
245 (void)_drainPendingDataLocked();
251 const bool more = (_pendingSizeLocked() > 0);
252 _readyReadPending.store(
false);
254 _readWaitCondition.wakeAll();
257 emit guard->readyRead();
260 _scheduleReadyRead();
263 Qt::QueuedConnection);
267bool QSerialPortPrivate::waitForReadyRead(
int msecs)
269 QMutexLocker locker(&_readMutex);
270 if (!buffer.isEmpty()) {
274 if (_pendingSizeLocked() > 0) {
275 (void)_drainPendingDataLocked();
279 QDeadlineTimer deadline(msecs);
280 while (buffer.isEmpty() && (_pendingSizeLocked() <= 0)) {
281 if (!_readWaitCondition.wait(&_readMutex, deadline)) {
285 if (!buffer.isEmpty()) {
289 if (_pendingSizeLocked() > 0) {
290 (void)_drainPendingDataLocked();
296 qCWarning(AndroidSerialPortLog) <<
"Timeout while waiting for ready read on device ID" << _deviceId;
304 const bool result = _writeDataOneShot(msecs);
306 qCWarning(AndroidSerialPortLog) <<
"Timeout while waiting for bytes written on device ID" << _deviceId;
308 QSerialPort::tr(
"Timeout while waiting for bytes written")));
314bool QSerialPortPrivate::_writeDataOneShot(
int msecs)
316 if (writeBuffer.isEmpty()) {
320 qint64 pendingBytesWritten = 0;
322 while (!writeBuffer.isEmpty()) {
323 const char* dataPtr = writeBuffer.readPointer();
324 const qint64 dataSize = writeBuffer.nextDataBlockSize();
326 const qint64 written = _writeToPort(dataPtr, dataSize, msecs);
328 qCWarning(AndroidSerialPortLog) <<
"Failed to write data one shot on device ID" << _deviceId;
333 writeBuffer.free(written);
334 pendingBytesWritten += written;
337 const bool result = (pendingBytesWritten > 0);
340 emit q->bytesWritten(pendingBytesWritten);
346qint64 QSerialPortPrivate::_writeToPort(
const char* data, qint64 maxSize,
int timeout,
bool async)
350 qCWarning(AndroidSerialPortLog) <<
"Failed to write to port ID" << _deviceId;
359 if (!data || (maxSize <= 0)) {
360 qCWarning(AndroidSerialPortLog) <<
"Invalid data or size in writeData for device ID" << _deviceId;
365 return _writeToPort(data, maxSize);
370 const bool result = _writeDataOneShot();
372 qCWarning(AndroidSerialPortLog) <<
"Flush operation failed for device ID" << _deviceId;
386 qCWarning(AndroidSerialPortLog) <<
"Failed to purge buffers for device ID" << _deviceId;
402 qCWarning(AndroidSerialPortLog) <<
"Failed to set DTR for device ID" << _deviceId;
413 qCWarning(AndroidSerialPortLog) <<
"Failed to set RTS for device ID" << _deviceId;
425 _stopBitsToAndroidStopBits(stopBits_), _parityToAndroidParity(parity_));
427 qCWarning(AndroidSerialPortLog) <<
"Failed to set Parameters for device ID" << _deviceId;
442 qCWarning(AndroidSerialPortLog) <<
"Invalid baud rate value:" << baudRate;
449 qCWarning(AndroidSerialPortLog) <<
"Custom baud rate direction is unsupported:" << directions;
451 QSerialPort::tr(
"Custom baud rate direction is unsupported")));
455 const bool result = _setParameters(baudRate, dataBits, stopBits, parity);
459 qCWarning(AndroidSerialPortLog) <<
"Failed to set baud rate for device ID" << _deviceId;
478 qCWarning(AndroidSerialPortLog) <<
"Invalid Data Bits" << dataBits_;
485 const bool result = _setParameters(
inputBaudRate, dataBits_, stopBits, parity);
487 qCWarning(AndroidSerialPortLog) <<
"Failed to set data bits for device ID" << _deviceId;
508 qCWarning(AndroidSerialPortLog) <<
"Invalid parity type:" << parity_;
515 const bool result = _setParameters(
inputBaudRate, dataBits, stopBits, parity_);
517 qCWarning(AndroidSerialPortLog) <<
"Failed to set parity for device ID" << _deviceId;
534 qCWarning(AndroidSerialPortLog) <<
"Invalid Stop Bits type:" << stopBits_;
541 const bool result = _setParameters(
inputBaudRate, dataBits, stopBits_, parity);
543 qCWarning(AndroidSerialPortLog) <<
"Failed to set StopBits for device ID" << _deviceId;
552 switch (flowControl_) {
560 qCWarning(AndroidSerialPortLog) <<
"Invalid Flow Control type:" << flowControl_;
569 qCWarning(AndroidSerialPortLog) <<
"Failed to set Flow Control for device ID" << _deviceId;
587 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800,
588 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000,
589 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, 4000000,
600 return d->descriptor;
#define QGC_LOGGING_CATEGORY(name, categoryStr)
bool waitForBytesWritten(int msec)
void setError(const QSerialPortErrorInfo &errorInfo)
bool setDataTerminalReady(bool set)
bool setStopBits(QSerialPort::StopBits stopBits)
bool setFlowControl(QSerialPort::FlowControl flowControl)
QSerialPort::PinoutSignals pinoutSignals()
bool clear(QSerialPort::Directions directions)
bool setDataBits(QSerialPort::DataBits dataBits)
static QList< qint32 > standardBaudRates()
qint64 writeData(const char *data, qint64 maxSize)
bool setRequestToSend(bool set)
void exceptionArrived(const QString &ex)
bool setParity(QSerialPort::Parity parity)
void newDataArrived(const char *bytes, int length)
bool setBreakEnabled(bool set)
Provides functions to access serial ports.
@ UnsupportedOperationError
int open(const QString &portName, QSerialPortPrivate *classPtr)
void registerPointer(QSerialPortPrivate *ptr)
int getDeviceHandle(int deviceId)
void unregisterPointer(QSerialPortPrivate *ptr)
bool setDataTerminalReady(int deviceId, bool set)
int write(int deviceId, const char *data, int length, int timeout, bool async)
bool setParameters(int deviceId, int baudRate, int dataBits, int stopBits, int parity)
bool startReadThread(int deviceId)
QSerialPort::PinoutSignals getControlLines(int deviceId)
bool setRequestToSend(int deviceId, bool set)
bool purgeBuffers(int deviceId, bool input, bool output)
bool readThreadRunning(int deviceId)
bool stopReadThread(int deviceId)
bool setFlowControl(int deviceId, int flowControl)
bool setBreak(int deviceId, bool set)
static constexpr qint32 kStandardBaudRates[]
constexpr int INVALID_DEVICE_ID