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
Returns the system location of the serial port.
void setError(const QSerialPortErrorInfo &errorInfo)
Provides functions to access serial ports.
Definition qserialport.h:17
qint64 readData(char *data, qint64 maxSize) override
\reimp
qint64 readLineData(char *data, qint64 maxSize) override
\reimp
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)
This signal is emitted after the state (high or low) of the line signal RTS has been changed.
qint64 readBufferSize() const
Returns the size of the internal read buffer.
void dataTerminalReadyChanged(bool set)
This signal is emitted after the state (high or low) of the line signal DTR has been changed.
bool isSequential() const override
\reimp
bool open(OpenMode mode) override
\reimp
void close() override
\reimp
bool setStopBits(StopBits stopBits)
void setPortName(const QString &name)
Sets the name of the serial port.
void baudRateChanged(qint32 baudRate, QSerialPort::Directions directions)
This signal is emitted after the baud rate has been changed.
void parityChanged(QSerialPort::Parity parity)
This signal is emitted after the parity checking mode has been changed.
qint64 writeData(const char *data, qint64 maxSize) override
\reimp
QBindable< StopBits > bindableStopBits()
bool waitForBytesWritten(int msecs=30000) override
\reimp
void setPort(const QSerialPortInfo &info)
Sets the port stored in the serial port info instance serialPortInfo.
bool waitForReadyRead(int msecs=30000) override
\reimp
DataBits
This enum describes the number of data bits used.
Definition qserialport.h:60
qint64 bytesToWrite() const override
\reimp
void breakEnabledChanged(bool set)
bool clear(Directions directions=AllDirections)
Discards all characters from the output or input buffer, depending on given directions directions.
bool setRequestToSend(bool set)
bool canReadLine() const override
\reimp
QSerialPort(QObject *parent=nullptr)
Constructs a new serial port object with the given parent.
void stopBitsChanged(QSerialPort::StopBits stopBits)
This signal is emitted after the number of stop bits in a frame has been changed.
void dataBitsChanged(QSerialPort::DataBits dataBits)
This signal is emitted after the data bits in a frame has been changed.
bool flush()
This function writes as much as possible from the internal write buffer to the underlying serial port...
Parity
This enum describes the parity scheme used.
Definition qserialport.h:69
StopBits stopBits() const
the number of stop bits in a frame
PinoutSignals pinoutSignals()
Returns the state of the line signals in a bitmap format.
DataBits dataBits() const
the data bits in a frame
void clearError()
QBindable< SerialPortError > bindableError() const
virtual ~QSerialPort()
Closes the serial port, if necessary, and then destroys object.
QBindable< DataBits > bindableDataBits()
SerialPortError error() const
the error status of the serial port
SerialPortError
This enum describes the errors that may be contained by the QSerialPort::error property.
@ UnsupportedOperationError
@ DataTerminalReadySignal
Definition qserialport.h:97
bool isRequestToSend()
QString portName() const
Returns the name set by setPort() or passed to the QSerialPort constructor.
void flowControlChanged(QSerialPort::FlowControl flowControl)
This signal is emitted after the flow control mode has been changed.
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()
StopBits
This enum describes the number of stop bits used.
Definition qserialport.h:79
FlowControl flowControl() const
the desired flow control mode
bool isDataTerminalReady()
bool setDataBits(DataBits dataBits)
FlowControl
This enum describes the flow control used.
Definition qserialport.h:87
bool setParity(Parity parity)
bool isBreakEnabled() const
qint64 bytesAvailable() const override
\reimp
bool setFlowControl(FlowControl flowControl)
void setReadBufferSize(qint64 size)
Sets the size of QSerialPort's internal read buffer to be size bytes.
#define QSERIALPORT_BUFFERSIZE
QT_BEGIN_NAMESPACE