QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
qserialport.cpp
Go to the documentation of this file.
1// Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com>
2// Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com>
3// Copyright (C) 2012 Laszlo Papp <lpapp@kde.org>
4// Copyright (C) 2012 Andre Hartmann <aha_1980@gmx.de>
5// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
6
7#include "qserialport.h"
8
9#include <QtCore/qdebug.h>
10
11#include "qserialport_p.h"
12#include "qserialportinfo.h"
13#include "qserialportinfo_p.h"
14
16
18 : errorCode(newErrorCode), errorString(newErrorString)
19{
20 if (errorString.isNull()) {
21 switch (errorCode) {
23 errorString = QSerialPort::tr("No error");
24 break;
26 errorString = QSerialPort::tr("Device is already open");
27 break;
29 errorString = QSerialPort::tr("Device is not open");
30 break;
32 errorString = QSerialPort::tr("Operation timed out");
33 break;
35 errorString = QSerialPort::tr("Error reading from device");
36 break;
38 errorString = QSerialPort::tr("Error writing to device");
39 break;
41 errorString = QSerialPort::tr("Device disappeared from the system");
42 break;
43 default:
44 // an empty string will be interpreted as "Unknown error"
45 // from the QIODevice::errorString()
46 break;
47 }
48 }
49}
50
52{
53 writeBufferChunkSize = QSERIALPORT_BUFFERSIZE;
54 readBufferChunkSize = QSERIALPORT_BUFFERSIZE;
55}
56
58{
59 Q_Q(QSerialPort);
60
61 q->setErrorString(errorInfo.errorString);
62 error.setValue(errorInfo.errorCode);
63 error.notify();
64 emit q->errorOccurred(error);
65}
66
332QSerialPort::QSerialPort(QObject* parent) : QIODevice(*new QSerialPortPrivate, parent)
333{
334}
335
342QSerialPort::QSerialPort(const QString& name, QObject* parent) : QIODevice(*new QSerialPortPrivate, parent)
343{
344 setPortName(name);
345}
346
352QSerialPort::QSerialPort(const QSerialPortInfo& serialPortInfo, QObject* parent)
353 : QIODevice(*new QSerialPortPrivate, parent)
354{
355 setPort(serialPortInfo);
356}
357
362{
363
364 if (isOpen())
365 close();
366}
367
376void QSerialPort::setPortName(const QString& name)
377{
378 Q_D(QSerialPort);
379 d->systemLocation = QSerialPortInfoPrivate::portNameToSystemLocation(name);
380}
381
387void QSerialPort::setPort(const QSerialPortInfo& serialPortInfo)
388{
389 Q_D(QSerialPort);
390 d->systemLocation = serialPortInfo.systemLocation();
391}
392
415{
416 Q_D(const QSerialPort);
418}
419
436bool QSerialPort::open(OpenMode mode)
437{
438 Q_D(QSerialPort);
439
440 if (isOpen()) {
442 return false;
443 }
444
445 // Define while not supported modes.
446 static const OpenMode unsupportedModes = Append | Truncate | Text | Unbuffered;
447 if ((mode & unsupportedModes) || mode == NotOpen) {
448 d->setError(QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError, tr("Unsupported open mode")));
449 return false;
450 }
451
452 clearError();
453 if (!d->open(mode))
454 return false;
455
456 QIODevice::open(mode);
457 return true;
458}
459
469{
470 Q_D(QSerialPort);
471 if (!isOpen()) {
473 return;
474 }
475
476 d->close();
477 d->isBreakEnabled.setValue(false);
478 QIODevice::close();
479}
480
502bool QSerialPort::setBaudRate(qint32 baudRate, Directions directions)
503{
504 Q_D(QSerialPort);
505
506 if (!isOpen() || d->setBaudRate(baudRate, directions)) {
507 if (directions & QSerialPort::Input) {
508 if (d->inputBaudRate != baudRate)
509 d->inputBaudRate = baudRate;
510 else
511 directions &= ~QSerialPort::Input;
512 }
513
514 if (directions & QSerialPort::Output) {
515 if (d->outputBaudRate != baudRate)
516 d->outputBaudRate = baudRate;
517 else
518 directions &= ~QSerialPort::Output;
519 }
520
521 if (directions)
522 emit baudRateChanged(baudRate, directions);
523
524 return true;
525 }
526
527 return false;
528}
529
530qint32 QSerialPort::baudRate(Directions directions) const
531{
532 Q_D(const QSerialPort);
533 if (directions == QSerialPort::AllDirections)
534 return d->inputBaudRate == d->outputBaudRate ? d->inputBaudRate : -1;
535 return directions & QSerialPort::Input ? d->inputBaudRate : d->outputBaudRate;
536}
537
562{
563 Q_D(QSerialPort);
564 d->dataBits.removeBindingUnlessInWrapper();
565 const auto currentDataBits = d->dataBits.valueBypassingBindings();
566 if (!isOpen() || d->setDataBits(dataBits)) {
567 d->dataBits.setValueBypassingBindings(dataBits);
568 if (currentDataBits != dataBits) {
569 d->dataBits.notify();
571 }
572 return true;
573 }
574 return false;
575}
576
578{
579 Q_D(const QSerialPort);
580 return d->dataBits;
581}
582
583QBindable<QSerialPort::DataBits> QSerialPort::bindableDataBits()
584{
585 return &d_func()->dataBits;
586}
587
612{
613 Q_D(QSerialPort);
614 d->parity.removeBindingUnlessInWrapper();
615 const auto currentParity = d->parity.valueBypassingBindings();
616 if (!isOpen() || d->setParity(parity)) {
617 d->parity.setValueBypassingBindings(parity);
618 if (currentParity != parity) {
619 d->parity.notify();
620 emit parityChanged(parity);
621 }
622 return true;
623 }
624 return false;
625}
626
628{
629 Q_D(const QSerialPort);
630 return d->parity;
631}
632
633QBindable<QSerialPort::Parity> QSerialPort::bindableParity()
634{
635 return &d_func()->parity;
636}
637
662{
663 Q_D(QSerialPort);
664 d->stopBits.removeBindingUnlessInWrapper();
665 const auto currentStopBits = d->stopBits.valueBypassingBindings();
666 if (!isOpen() || d->setStopBits(stopBits)) {
667 d->stopBits.setValueBypassingBindings(stopBits);
668 if (currentStopBits != stopBits) {
669 d->stopBits.notify();
671 }
672 return true;
673 }
674 return false;
675}
676
678{
679 Q_D(const QSerialPort);
680 return d->stopBits;
681}
682
683QBindable<QSerialPort::StopBits> QSerialPort::bindableStopBits()
684{
685 return &d_func()->stopBits;
686}
687
712{
713 Q_D(QSerialPort);
714 d->flowControl.removeBindingUnlessInWrapper();
715 const auto currentFlowControl = d->flowControl.valueBypassingBindings();
716 if (!isOpen() || d->setFlowControl(flowControl)) {
717 d->flowControl.setValueBypassingBindings(flowControl);
718 if (currentFlowControl != flowControl) {
719 d->flowControl.notify();
721 }
722 return true;
723 }
724 return false;
725}
726
728{
729 Q_D(const QSerialPort);
730 return d->flowControl;
731}
732
733QBindable<QSerialPort::FlowControl> QSerialPort::bindableFlowControl()
734{
735 return &d_func()->flowControl;
736}
737
761{
762 Q_D(QSerialPort);
763
764 if (!isOpen()) {
766 qWarning("%s: device not open", Q_FUNC_INFO);
767 return false;
768 }
769
770 const bool dataTerminalReady = isDataTerminalReady();
771 const bool retval = d->setDataTerminalReady(set);
772 if (retval && (dataTerminalReady != set))
773 emit dataTerminalReadyChanged(set);
774
775 return retval;
776}
777
779{
780 Q_D(QSerialPort);
781 return d->pinoutSignals() & QSerialPort::DataTerminalReadySignal;
782}
783
812{
813 Q_D(QSerialPort);
814
815 if (!isOpen()) {
817 qWarning("%s: device not open", Q_FUNC_INFO);
818 return false;
819 }
820
821 if (d->flowControl == QSerialPort::HardwareControl) {
823 return false;
824 }
825
826 const bool requestToSend = isRequestToSend();
827 const bool retval = d->setRequestToSend(set);
828 if (retval && (requestToSend != set))
829 emit requestToSendChanged(set);
830
831 return retval;
832}
833
835{
836 Q_D(QSerialPort);
837 return d->pinoutSignals() & QSerialPort::RequestToSendSignal;
838}
839
866QSerialPort::PinoutSignals QSerialPort::pinoutSignals()
867{
868 Q_D(QSerialPort);
869
870 if (!isOpen()) {
872 qWarning("%s: device not open", Q_FUNC_INFO);
874 }
875
876 return d->pinoutSignals();
877}
878
897{
898 Q_D(QSerialPort);
899
900 if (!isOpen()) {
902 qWarning("%s: device not open", Q_FUNC_INFO);
903 return false;
904 }
905
906 return d->flush();
907}
908
918bool QSerialPort::clear(Directions directions)
919{
920 Q_D(QSerialPort);
921
922 if (!isOpen()) {
924 qWarning("%s: device not open", Q_FUNC_INFO);
925 return false;
926 }
927
928 if (directions & Input) {
929 QMutexLocker locker(&d->_readMutex);
930 d->buffer.clear();
931 d->_pendingData.clear();
932 d->_bufferBytesEstimate.store(0, std::memory_order_relaxed);
933 }
934 if (directions & Output)
935 d->writeBuffer.clear();
936 return d->clear(directions);
937}
938
951{
952 Q_D(const QSerialPort);
953 return d->error;
954}
955
961
962QBindable<QSerialPort::SerialPortError> QSerialPort::bindableError() const
963{
964 return &d_func()->error;
965}
966
988{
989 Q_D(const QSerialPort);
990 return d->readBufferMaxSize;
991}
992
1010{
1011 Q_D(QSerialPort);
1012 d->readBufferMaxSize = size;
1013 if (isReadable())
1014 d->startAsyncRead();
1015}
1016
1023{
1024 return true;
1025}
1026
1035{
1036 return QIODevice::bytesAvailable();
1037}
1038
1049{
1050 qint64 pendingBytes = QIODevice::bytesToWrite();
1051 return pendingBytes;
1052}
1053
1063{
1064 return QIODevice::canReadLine();
1065}
1066
1082{
1083 Q_D(QSerialPort);
1084 return d->waitForReadyRead(msecs);
1085}
1086
1111{
1112 Q_D(QSerialPort);
1113 return d->waitForBytesWritten(msecs);
1114}
1115
1133{
1134 Q_D(QSerialPort);
1135 d->isBreakEnabled.removeBindingUnlessInWrapper();
1136 const auto currentSet = d->isBreakEnabled.valueBypassingBindings();
1137 if (isOpen()) {
1138 if (d->setBreakEnabled(set)) {
1139 d->isBreakEnabled.setValueBypassingBindings(set);
1140 if (currentSet != set) {
1141 d->isBreakEnabled.notify();
1142 emit breakEnabledChanged(set);
1143 }
1144 return true;
1145 }
1146 } else {
1148 qWarning("%s: device not open", Q_FUNC_INFO);
1149 }
1150 return false;
1151}
1152
1154{
1155 Q_D(const QSerialPort);
1156 return d->isBreakEnabled;
1157}
1158
1160{
1161 return &d_func()->isBreakEnabled;
1162}
1163
1173qint64 QSerialPort::readData(char* data, qint64 maxSize)
1174{
1175 Q_UNUSED(data);
1176 Q_UNUSED(maxSize);
1177
1178 // QIODevice drains from d->buffer before calling here; refresh estimate so
1179 // Android read-backpressure tracks current buffered bytes.
1180 d_func()->_bufferBytesEstimate.store(d_func()->buffer.size(), std::memory_order_relaxed);
1181
1182 // In any case we need to start the notifications if they were
1183 // disabled by the read handler. If enabled, next call does nothing.
1184 d_func()->startAsyncRead();
1185
1186 // return 0 indicating there may be more data in the future
1187 return qint64(0);
1188}
1189
1193qint64 QSerialPort::readLineData(char* data, qint64 maxSize)
1194{
1195 return QIODevice::readLineData(data, maxSize);
1196}
1197
1201qint64 QSerialPort::writeData(const char* data, qint64 maxSize)
1202{
1203 Q_D(QSerialPort);
1204 return d->writeData(data, maxSize);
1205}
1206
1207QT_END_NAMESPACE
1208
1209#include "moc_qserialport.cpp"
QString errorString
Error error
QSerialPort::SerialPortError errorCode
QSerialPortErrorInfo(QSerialPort::SerialPortError newErrorCode=QSerialPort::UnknownError, const QString &newErrorString=QString())
static QString portNameFromSystemLocation(const QString &source)
static QString portNameToSystemLocation(const QString &source)
Provides information about existing serial ports.
QString systemLocation() const
void setError(const QSerialPortErrorInfo &errorInfo)
Provides functions to access serial ports.
Definition qserialport.h:17
qint64 readData(char *data, qint64 maxSize) override
qint64 readLineData(char *data, qint64 maxSize) override
qint32 baudRate(Directions directions=AllDirections) const
the data baud rate for the desired direction
bool setDataTerminalReady(bool set)
QBindable< Parity > bindableParity()
void requestToSendChanged(bool set)
qint64 readBufferSize() const
void dataTerminalReadyChanged(bool set)
bool isSequential() const override
bool open(OpenMode mode) override
void close() override
bool setStopBits(StopBits stopBits)
void setPortName(const QString &name)
void parityChanged(QSerialPort::Parity parity)
qint64 writeData(const char *data, qint64 maxSize) override
QBindable< StopBits > bindableStopBits()
bool waitForBytesWritten(int msecs=30000) override
void setPort(const QSerialPortInfo &info)
bool waitForReadyRead(int msecs=30000) override
qint64 bytesToWrite() const override
void breakEnabledChanged(bool set)
bool clear(Directions directions=AllDirections)
bool setRequestToSend(bool set)
bool canReadLine() const override
QSerialPort(QObject *parent=nullptr)
void stopBitsChanged(QSerialPort::StopBits stopBits)
void dataBitsChanged(QSerialPort::DataBits dataBits)
StopBits stopBits() const
the number of stop bits in a frame
PinoutSignals pinoutSignals()
DataBits dataBits() const
the data bits in a frame
void clearError()
QBindable< SerialPortError > bindableError() const
virtual ~QSerialPort()
QBindable< DataBits > bindableDataBits()
SerialPortError error() const
the error status of the serial port
@ UnsupportedOperationError
@ DataTerminalReadySignal
Definition qserialport.h:97
bool isRequestToSend()
QString portName() const
void flowControlChanged(QSerialPort::FlowControl flowControl)
bool setBreakEnabled(bool set=true)
QBindable< bool > bindableIsBreakEnabled()
bool setBaudRate(qint32 baudRate, Directions directions=AllDirections)
Parity parity() const
the parity checking mode
QBindable< FlowControl > bindableFlowControl()
FlowControl flowControl() const
the desired flow control mode
bool isDataTerminalReady()
bool setDataBits(DataBits dataBits)
bool setParity(Parity parity)
bool isBreakEnabled() const
qint64 bytesAvailable() const override
bool setFlowControl(FlowControl flowControl)
void setReadBufferSize(qint64 size)
#define QSERIALPORT_BUFFERSIZE
QT_BEGIN_NAMESPACE