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 // Buffered writes were accepted by write(); try to send them unless writing already failed.
477 if (d->error != QSerialPort::WriteError) {
478 (void) d->flushBeforeClose();
479 }
480 d->close();
481 d->isBreakEnabled.setValue(false);
482 QIODevice::close();
483}
484
506bool QSerialPort::setBaudRate(qint32 baudRate, Directions directions)
507{
508 Q_D(QSerialPort);
509
510 if (!isOpen() || d->setBaudRate(baudRate, directions)) {
511 if (directions & QSerialPort::Input) {
512 if (d->inputBaudRate != baudRate)
513 d->inputBaudRate = baudRate;
514 else
515 directions &= ~QSerialPort::Input;
516 }
517
518 if (directions & QSerialPort::Output) {
519 if (d->outputBaudRate != baudRate)
520 d->outputBaudRate = baudRate;
521 else
522 directions &= ~QSerialPort::Output;
523 }
524
525 if (directions)
526 emit baudRateChanged(baudRate, directions);
527
528 return true;
529 }
530
531 return false;
532}
533
534qint32 QSerialPort::baudRate(Directions directions) const
535{
536 Q_D(const QSerialPort);
537 if (directions == QSerialPort::AllDirections)
538 return d->inputBaudRate == d->outputBaudRate ? d->inputBaudRate : -1;
539 return directions & QSerialPort::Input ? d->inputBaudRate : d->outputBaudRate;
540}
541
566{
567 Q_D(QSerialPort);
568 d->dataBits.removeBindingUnlessInWrapper();
569 const auto currentDataBits = d->dataBits.valueBypassingBindings();
570 if (!isOpen() || d->setDataBits(dataBits)) {
571 d->dataBits.setValueBypassingBindings(dataBits);
572 if (currentDataBits != dataBits) {
573 d->dataBits.notify();
575 }
576 return true;
577 }
578 return false;
579}
580
582{
583 Q_D(const QSerialPort);
584 return d->dataBits;
585}
586
587QBindable<QSerialPort::DataBits> QSerialPort::bindableDataBits()
588{
589 return &d_func()->dataBits;
590}
591
616{
617 Q_D(QSerialPort);
618 d->parity.removeBindingUnlessInWrapper();
619 const auto currentParity = d->parity.valueBypassingBindings();
620 if (!isOpen() || d->setParity(parity)) {
621 d->parity.setValueBypassingBindings(parity);
622 if (currentParity != parity) {
623 d->parity.notify();
624 emit parityChanged(parity);
625 }
626 return true;
627 }
628 return false;
629}
630
632{
633 Q_D(const QSerialPort);
634 return d->parity;
635}
636
637QBindable<QSerialPort::Parity> QSerialPort::bindableParity()
638{
639 return &d_func()->parity;
640}
641
666{
667 Q_D(QSerialPort);
668 d->stopBits.removeBindingUnlessInWrapper();
669 const auto currentStopBits = d->stopBits.valueBypassingBindings();
670 if (!isOpen() || d->setStopBits(stopBits)) {
671 d->stopBits.setValueBypassingBindings(stopBits);
672 if (currentStopBits != stopBits) {
673 d->stopBits.notify();
675 }
676 return true;
677 }
678 return false;
679}
680
682{
683 Q_D(const QSerialPort);
684 return d->stopBits;
685}
686
687QBindable<QSerialPort::StopBits> QSerialPort::bindableStopBits()
688{
689 return &d_func()->stopBits;
690}
691
716{
717 Q_D(QSerialPort);
718 d->flowControl.removeBindingUnlessInWrapper();
719 const auto currentFlowControl = d->flowControl.valueBypassingBindings();
720 if (!isOpen() || d->setFlowControl(flowControl)) {
721 d->flowControl.setValueBypassingBindings(flowControl);
722 if (currentFlowControl != flowControl) {
723 d->flowControl.notify();
725 }
726 return true;
727 }
728 return false;
729}
730
732{
733 Q_D(const QSerialPort);
734 return d->flowControl;
735}
736
737QBindable<QSerialPort::FlowControl> QSerialPort::bindableFlowControl()
738{
739 return &d_func()->flowControl;
740}
741
765{
766 Q_D(QSerialPort);
767
768 if (!isOpen()) {
770 qWarning("%s: device not open", Q_FUNC_INFO);
771 return false;
772 }
773
774 const bool dataTerminalReady = isDataTerminalReady();
775 const bool retval = d->setDataTerminalReady(set);
776 if (retval && (dataTerminalReady != set))
777 emit dataTerminalReadyChanged(set);
778
779 return retval;
780}
781
783{
784 Q_D(QSerialPort);
785 return d->pinoutSignals() & QSerialPort::DataTerminalReadySignal;
786}
787
816{
817 Q_D(QSerialPort);
818
819 if (!isOpen()) {
821 qWarning("%s: device not open", Q_FUNC_INFO);
822 return false;
823 }
824
825 if (d->flowControl == QSerialPort::HardwareControl) {
827 return false;
828 }
829
830 const bool requestToSend = isRequestToSend();
831 const bool retval = d->setRequestToSend(set);
832 if (retval && (requestToSend != set))
833 emit requestToSendChanged(set);
834
835 return retval;
836}
837
839{
840 Q_D(QSerialPort);
841 return d->pinoutSignals() & QSerialPort::RequestToSendSignal;
842}
843
870QSerialPort::PinoutSignals QSerialPort::pinoutSignals()
871{
872 Q_D(QSerialPort);
873
874 if (!isOpen()) {
876 qWarning("%s: device not open", Q_FUNC_INFO);
878 }
879
880 return d->pinoutSignals();
881}
882
901{
902 Q_D(QSerialPort);
903
904 if (!isOpen()) {
906 qWarning("%s: device not open", Q_FUNC_INFO);
907 return false;
908 }
909
910 return d->flush();
911}
912
922bool QSerialPort::clear(Directions directions)
923{
924 Q_D(QSerialPort);
925
926 if (!isOpen()) {
928 qWarning("%s: device not open", Q_FUNC_INFO);
929 return false;
930 }
931
932 if (directions & Input) {
933 QMutexLocker locker(&d->_readMutex);
934 d->buffer.clear();
935 d->_pendingData.clear();
936 d->_bufferBytesEstimate.store(0, std::memory_order_relaxed);
937 }
938 if (directions & Output)
939 d->writeBuffer.clear();
940 return d->clear(directions);
941}
942
955{
956 Q_D(const QSerialPort);
957 return d->error;
958}
959
965
966QBindable<QSerialPort::SerialPortError> QSerialPort::bindableError() const
967{
968 return &d_func()->error;
969}
970
992{
993 Q_D(const QSerialPort);
994 return d->readBufferMaxSize;
995}
996
1014{
1015 Q_D(QSerialPort);
1016 d->readBufferMaxSize = size;
1017 if (isReadable())
1018 d->startAsyncRead();
1019}
1020
1027{
1028 return true;
1029}
1030
1039{
1040 return QIODevice::bytesAvailable();
1041}
1042
1053{
1054 qint64 pendingBytes = QIODevice::bytesToWrite();
1055 return pendingBytes;
1056}
1057
1067{
1068 return QIODevice::canReadLine();
1069}
1070
1086{
1087 Q_D(QSerialPort);
1088 return d->waitForReadyRead(msecs);
1089}
1090
1115{
1116 Q_D(QSerialPort);
1117 return d->waitForBytesWritten(msecs);
1118}
1119
1137{
1138 Q_D(QSerialPort);
1139 d->isBreakEnabled.removeBindingUnlessInWrapper();
1140 const auto currentSet = d->isBreakEnabled.valueBypassingBindings();
1141 if (isOpen()) {
1142 if (d->setBreakEnabled(set)) {
1143 d->isBreakEnabled.setValueBypassingBindings(set);
1144 if (currentSet != set) {
1145 d->isBreakEnabled.notify();
1146 emit breakEnabledChanged(set);
1147 }
1148 return true;
1149 }
1150 } else {
1152 qWarning("%s: device not open", Q_FUNC_INFO);
1153 }
1154 return false;
1155}
1156
1158{
1159 Q_D(const QSerialPort);
1160 return d->isBreakEnabled;
1161}
1162
1164{
1165 return &d_func()->isBreakEnabled;
1166}
1167
1177qint64 QSerialPort::readData(char* data, qint64 maxSize)
1178{
1179 Q_UNUSED(data);
1180 Q_UNUSED(maxSize);
1181
1182 // QIODevice drains from d->buffer before calling here; refresh estimate so
1183 // Android read-backpressure tracks current buffered bytes.
1184 d_func()->_bufferBytesEstimate.store(d_func()->buffer.size(), std::memory_order_relaxed);
1185
1186 // In any case we need to start the notifications if they were
1187 // disabled by the read handler. If enabled, next call does nothing.
1188 d_func()->startAsyncRead();
1189
1190 // return 0 indicating there may be more data in the future
1191 return qint64(0);
1192}
1193
1197qint64 QSerialPort::readLineData(char* data, qint64 maxSize)
1198{
1199 return QIODevice::readLineData(data, maxSize);
1200}
1201
1205qint64 QSerialPort::writeData(const char* data, qint64 maxSize)
1206{
1207 Q_D(QSerialPort);
1208 return d->writeData(data, maxSize);
1209}
1210
1211QT_END_NAMESPACE
1212
1213#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