From 5ddbb6b87266d0f8d7dffc03c86c2e80b3735d2c Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 30 Jun 2016 19:27:25 +0300 Subject: Minimize number of system calls at opening Currently, the method QSP::open() several times calls the system functions to get/set of DCB/termios structures for each parameter. It is not rational and should be minimized as possible, in ideally to once executed. Change-Id: If1f308176a82f3c8896fc648bf656f089e099f3f Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialport.cpp | 9 -- src/serialport/qserialport_unix.cpp | 221 +++++++++++++++++++++--------------- src/serialport/qserialport_win.cpp | 172 +++++++++++++++++----------- 3 files changed, 233 insertions(+), 169 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index 45f56c8..d4e9a4f 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -568,15 +568,6 @@ bool QSerialPort::open(OpenMode mode) if (!d->open(mode)) return false; - if (!d->setBaudRate() - || !d->setDataBits(d->dataBits) - || !d->setParity(d->parity) - || !d->setStopBits(d->stopBits) - || !d->setFlowControl(d->flowControl)) { - d->close(); - return false; - } - QIODevice::open(mode); return true; } diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index acc53c8..acd76b5 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -193,6 +193,120 @@ private: QSerialPortPrivate *dptr; }; +static inline void qt_set_common_props(termios *tio, QIODevice::OpenMode m) +{ +#ifdef Q_OS_SOLARIS + tio->c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); + tio->c_oflag &= ~OPOST; + tio->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + tio->c_cflag &= ~(CSIZE|PARENB); + tio->c_cflag |= CS8; +#else + ::cfmakeraw(tio); +#endif + + tio->c_cflag |= CLOCAL; + tio->c_cc[VTIME] = 0; + tio->c_cc[VMIN] = 0; + + if (m & QIODevice::ReadOnly) + tio->c_cflag |= CREAD; +} + +static inline void qt_set_databits(termios *tio, QSerialPort::DataBits databits) +{ + tio->c_cflag &= ~CSIZE; + switch (databits) { + case QSerialPort::Data5: + tio->c_cflag |= CS5; + break; + case QSerialPort::Data6: + tio->c_cflag |= CS6; + break; + case QSerialPort::Data7: + tio->c_cflag |= CS7; + break; + case QSerialPort::Data8: + tio->c_cflag |= CS8; + break; + default: + tio->c_cflag |= CS8; + break; + } +} + +static inline void qt_set_parity(termios *tio, QSerialPort::Parity parity) +{ + tio->c_iflag &= ~(PARMRK | INPCK); + tio->c_iflag |= IGNPAR; + + switch (parity) { + +#ifdef CMSPAR + // Here Installation parity only for GNU/Linux where the macro CMSPAR. + case QSerialPort::SpaceParity: + tio->c_cflag &= ~PARODD; + tio->c_cflag |= PARENB | CMSPAR; + break; + case QSerialPort::MarkParity: + tio->c_cflag |= PARENB | CMSPAR | PARODD; + break; +#endif + case QSerialPort::NoParity: + tio->c_cflag &= ~PARENB; + break; + case QSerialPort::EvenParity: + tio->c_cflag &= ~PARODD; + tio->c_cflag |= PARENB; + break; + case QSerialPort::OddParity: + tio->c_cflag |= PARENB | PARODD; + break; + default: + tio->c_cflag |= PARENB; + tio->c_iflag |= PARMRK | INPCK; + tio->c_iflag &= ~IGNPAR; + break; + } +} + +static inline void qt_set_stopbits(termios *tio, QSerialPort::StopBits stopbits) +{ + switch (stopbits) { + case QSerialPort::OneStop: + tio->c_cflag &= ~CSTOPB; + break; + case QSerialPort::TwoStop: + tio->c_cflag |= CSTOPB; + break; + default: + tio->c_cflag &= ~CSTOPB; + break; + } +} + +static inline void qt_set_flowcontrol(termios *tio, QSerialPort::FlowControl flowcontrol) +{ + switch (flowcontrol) { + case QSerialPort::NoFlowControl: + tio->c_cflag &= ~CRTSCTS; + tio->c_iflag &= ~(IXON | IXOFF | IXANY); + break; + case QSerialPort::HardwareControl: + tio->c_cflag |= CRTSCTS; + tio->c_iflag &= ~(IXON | IXOFF | IXANY); + break; + case QSerialPort::SoftwareControl: + tio->c_cflag &= ~CRTSCTS; + tio->c_iflag |= IXON | IXOFF | IXANY; + break; + default: + tio->c_cflag &= ~CRTSCTS; + tio->c_iflag &= ~(IXON | IXOFF | IXANY); + break; + } +} + bool QSerialPortPrivate::open(QIODevice::OpenMode mode) { QString lockFilePath = serialPortLockFilePath(QSerialPortInfoPrivate::portNameFromSystemLocation(systemLocation)); @@ -605,24 +719,8 @@ bool QSerialPortPrivate::setDataBits(QSerialPort::DataBits dataBits) if (!getTermios(&tio)) return false; - tio.c_cflag &= ~CSIZE; - switch (dataBits) { - case QSerialPort::Data5: - tio.c_cflag |= CS5; - break; - case QSerialPort::Data6: - tio.c_cflag |= CS6; - break; - case QSerialPort::Data7: - tio.c_cflag |= CS7; - break; - case QSerialPort::Data8: - tio.c_cflag |= CS8; - break; - default: - tio.c_cflag |= CS8; - break; - } + qt_set_databits(&tio, dataBits); + return setTermios(&tio); } @@ -632,37 +730,7 @@ bool QSerialPortPrivate::setParity(QSerialPort::Parity parity) if (!getTermios(&tio)) return false; - tio.c_iflag &= ~(PARMRK | INPCK); - tio.c_iflag |= IGNPAR; - - switch (parity) { - -#ifdef CMSPAR - // Here Installation parity only for GNU/Linux where the macro CMSPAR. - case QSerialPort::SpaceParity: - tio.c_cflag &= ~PARODD; - tio.c_cflag |= PARENB | CMSPAR; - break; - case QSerialPort::MarkParity: - tio.c_cflag |= PARENB | CMSPAR | PARODD; - break; -#endif - case QSerialPort::NoParity: - tio.c_cflag &= ~PARENB; - break; - case QSerialPort::EvenParity: - tio.c_cflag &= ~PARODD; - tio.c_cflag |= PARENB; - break; - case QSerialPort::OddParity: - tio.c_cflag |= PARENB | PARODD; - break; - default: - tio.c_cflag |= PARENB; - tio.c_iflag |= PARMRK | INPCK; - tio.c_iflag &= ~IGNPAR; - break; - } + qt_set_parity(&tio, parity); return setTermios(&tio); } @@ -673,17 +741,8 @@ bool QSerialPortPrivate::setStopBits(QSerialPort::StopBits stopBits) if (!getTermios(&tio)) return false; - switch (stopBits) { - case QSerialPort::OneStop: - tio.c_cflag &= ~CSTOPB; - break; - case QSerialPort::TwoStop: - tio.c_cflag |= CSTOPB; - break; - default: - tio.c_cflag &= ~CSTOPB; - break; - } + qt_set_stopbits(&tio, stopBits); + return setTermios(&tio); } @@ -693,24 +752,8 @@ bool QSerialPortPrivate::setFlowControl(QSerialPort::FlowControl flowControl) if (!getTermios(&tio)) return false; - switch (flowControl) { - case QSerialPort::NoFlowControl: - tio.c_cflag &= ~CRTSCTS; - tio.c_iflag &= ~(IXON | IXOFF | IXANY); - break; - case QSerialPort::HardwareControl: - tio.c_cflag |= CRTSCTS; - tio.c_iflag &= ~(IXON | IXOFF | IXANY); - break; - case QSerialPort::SoftwareControl: - tio.c_cflag &= ~CRTSCTS; - tio.c_iflag |= IXON | IXOFF | IXANY; - break; - default: - tio.c_cflag &= ~CRTSCTS; - tio.c_iflag &= ~(IXON | IXOFF | IXANY); - break; - } + qt_set_flowcontrol(&tio, flowControl); + return setTermios(&tio); } @@ -825,25 +868,19 @@ inline bool QSerialPortPrivate::initialize(QIODevice::OpenMode mode) return false; restoredTermios = tio; -#ifdef Q_OS_SOLARIS - tio.c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); - tio.c_oflag &= ~OPOST; - tio.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); - tio.c_cflag &= ~(CSIZE|PARENB); - tio.c_cflag |= CS8; -#else - ::cfmakeraw(&tio); -#endif - tio.c_cflag |= CLOCAL; - tio.c_cc[VTIME] = 0; - tio.c_cc[VMIN] = 0; - if (mode & QIODevice::ReadOnly) - tio.c_cflag |= CREAD; + qt_set_common_props(&tio, mode); + qt_set_databits(&tio, dataBits); + qt_set_parity(&tio, parity); + qt_set_stopbits(&tio, stopBits); + qt_set_flowcontrol(&tio, flowControl); if (!setTermios(&tio)) return false; + if (!setBaudRate()) + return false; + if (mode & QIODevice::ReadOnly) setReadNotificationEnabled(true); diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 7cbb81d..f4f8317 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -81,6 +81,94 @@ QT_BEGIN_NAMESPACE +static inline void qt_set_common_props(DCB *dcb) +{ + dcb->fBinary = TRUE; + dcb->fAbortOnError = FALSE; + dcb->fNull = FALSE; + dcb->fErrorChar = FALSE; + + if (dcb->fDtrControl == DTR_CONTROL_HANDSHAKE) + dcb->fDtrControl = DTR_CONTROL_DISABLE; +} + +static inline void qt_set_baudrate(DCB *dcb, qint32 baudrate) +{ + dcb->BaudRate = baudrate; +} + +static inline void qt_set_databits(DCB *dcb, QSerialPort::DataBits databits) +{ + dcb->ByteSize = databits; +} + +static inline void qt_set_parity(DCB *dcb, QSerialPort::Parity parity) +{ + dcb->fParity = TRUE; + switch (parity) { + case QSerialPort::NoParity: + dcb->Parity = NOPARITY; + dcb->fParity = FALSE; + break; + case QSerialPort::OddParity: + dcb->Parity = ODDPARITY; + break; + case QSerialPort::EvenParity: + dcb->Parity = EVENPARITY; + break; + case QSerialPort::MarkParity: + dcb->Parity = MARKPARITY; + break; + case QSerialPort::SpaceParity: + dcb->Parity = SPACEPARITY; + break; + default: + dcb->Parity = NOPARITY; + dcb->fParity = FALSE; + break; + } +} + +static inline void qt_set_stopbits(DCB *dcb, QSerialPort::StopBits stopbits) +{ + switch (stopbits) { + case QSerialPort::OneStop: + dcb->StopBits = ONESTOPBIT; + break; + case QSerialPort::OneAndHalfStop: + dcb->StopBits = ONE5STOPBITS; + break; + case QSerialPort::TwoStop: + dcb->StopBits = TWOSTOPBITS; + break; + default: + dcb->StopBits = ONESTOPBIT; + break; + } +} + +static inline void qt_set_flowcontrol(DCB *dcb, QSerialPort::FlowControl flowcontrol) +{ + dcb->fInX = FALSE; + dcb->fOutX = FALSE; + dcb->fOutxCtsFlow = FALSE; + dcb->fRtsControl = RTS_CONTROL_DISABLE; + switch (flowcontrol) { + case QSerialPort::NoFlowControl: + break; + case QSerialPort::SoftwareControl: + dcb->fInX = TRUE; + dcb->fOutX = TRUE; + break; + case QSerialPort::HardwareControl: + dcb->fOutxCtsFlow = TRUE; + dcb->fRtsControl = RTS_CONTROL_HANDSHAKE; + break; + default: + break; + } +} + bool QSerialPortPrivate::open(QIODevice::OpenMode mode) { DWORD desiredAccess = 0; @@ -319,7 +407,8 @@ bool QSerialPortPrivate::setBaudRate(qint32 baudRate, QSerialPort::Directions di if (!getDcb(&dcb)) return false; - dcb.BaudRate = baudRate; + qt_set_baudrate(&dcb, baudRate); + return setDcb(&dcb); } @@ -329,7 +418,8 @@ bool QSerialPortPrivate::setDataBits(QSerialPort::DataBits dataBits) if (!getDcb(&dcb)) return false; - dcb.ByteSize = dataBits; + qt_set_databits(&dcb, dataBits); + return setDcb(&dcb); } @@ -339,29 +429,8 @@ bool QSerialPortPrivate::setParity(QSerialPort::Parity parity) if (!getDcb(&dcb)) return false; - dcb.fParity = TRUE; - switch (parity) { - case QSerialPort::NoParity: - dcb.Parity = NOPARITY; - dcb.fParity = FALSE; - break; - case QSerialPort::OddParity: - dcb.Parity = ODDPARITY; - break; - case QSerialPort::EvenParity: - dcb.Parity = EVENPARITY; - break; - case QSerialPort::MarkParity: - dcb.Parity = MARKPARITY; - break; - case QSerialPort::SpaceParity: - dcb.Parity = SPACEPARITY; - break; - default: - dcb.Parity = NOPARITY; - dcb.fParity = FALSE; - break; - } + qt_set_parity(&dcb, parity); + return setDcb(&dcb); } @@ -371,20 +440,8 @@ bool QSerialPortPrivate::setStopBits(QSerialPort::StopBits stopBits) if (!getDcb(&dcb)) return false; - switch (stopBits) { - case QSerialPort::OneStop: - dcb.StopBits = ONESTOPBIT; - break; - case QSerialPort::OneAndHalfStop: - dcb.StopBits = ONE5STOPBITS; - break; - case QSerialPort::TwoStop: - dcb.StopBits = TWOSTOPBITS; - break; - default: - dcb.StopBits = ONESTOPBIT; - break; - } + qt_set_stopbits(&dcb, stopBits); + return setDcb(&dcb); } @@ -394,24 +451,8 @@ bool QSerialPortPrivate::setFlowControl(QSerialPort::FlowControl flowControl) if (!getDcb(&dcb)) return false; - dcb.fInX = FALSE; - dcb.fOutX = FALSE; - dcb.fOutxCtsFlow = FALSE; - dcb.fRtsControl = RTS_CONTROL_DISABLE; - switch (flowControl) { - case QSerialPort::NoFlowControl: - break; - case QSerialPort::SoftwareControl: - dcb.fInX = TRUE; - dcb.fOutX = TRUE; - break; - case QSerialPort::HardwareControl: - dcb.fOutxCtsFlow = TRUE; - dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; - break; - default: - break; - } + qt_set_flowcontrol(&dcb, flowControl); + return setDcb(&dcb); } @@ -623,17 +664,12 @@ inline bool QSerialPortPrivate::initialize() restoredDcb = dcb; - dcb.fBinary = TRUE; - dcb.fInX = FALSE; - dcb.fOutX = FALSE; - dcb.fAbortOnError = FALSE; - dcb.fNull = FALSE; - dcb.fErrorChar = FALSE; - - if (dcb.fDtrControl == DTR_CONTROL_HANDSHAKE) - dcb.fDtrControl = DTR_CONTROL_DISABLE; - - dcb.BaudRate = inputBaudRate; + qt_set_common_props(&dcb); + qt_set_baudrate(&dcb, inputBaudRate); + qt_set_databits(&dcb, dataBits); + qt_set_parity(&dcb, parity); + qt_set_stopbits(&dcb, stopBits); + qt_set_flowcontrol(&dcb, flowControl); if (!setDcb(&dcb)) return false; -- cgit v1.2.1 From 09f6a0f1cacd8d04d5ec8413eed712308395f962 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 7 Jul 2016 18:22:17 +0300 Subject: Use append() instead of memcpy() where possible ... to add the data to the internal QIODevice's buffer, that simplified the code and is more reliable. Change-Id: I61e6c7be3259cd754e4bbe6a3142dcdd6d33f7b6 Reviewed-by: Anton Kudryavtsev Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialport_unix.cpp | 2 +- src/serialport/qserialport_win.cpp | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index acd76b5..8e06ada 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -889,7 +889,7 @@ inline bool QSerialPortPrivate::initialize(QIODevice::OpenMode mode) qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize) { - ::memcpy(writeBuffer.reserve(maxSize), data, maxSize); + writeBuffer.append(data, maxSize); if (!writeBuffer.isEmpty() && !isWriteNotificationEnabled()) setWriteNotificationEnabled(true); return maxSize; diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index f4f8317..ae32fcf 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -472,10 +472,8 @@ bool QSerialPortPrivate::completeAsyncRead(qint64 bytesTransferred) readStarted = false; return false; } - if (bytesTransferred > 0) { - char *ptr = buffer.reserve(bytesTransferred); - ::memcpy(ptr, readChunkBuffer.constData(), bytesTransferred); - } + if (bytesTransferred > 0) + buffer.append(readChunkBuffer.constData(), bytesTransferred); readStarted = false; @@ -620,7 +618,7 @@ qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize) { Q_Q(QSerialPort); - ::memcpy(writeBuffer.reserve(maxSize), data, maxSize); + writeBuffer.append(data, maxSize); actualBytesToWrite += maxSize; if (!writeBuffer.isEmpty() && !writeStarted) { -- cgit v1.2.1 From 86b6a8f27a098d764a5c2f7dc37edb349bd28c3c Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Mon, 11 Jul 2016 10:49:06 +0300 Subject: QSerialPortInfo: use delegate ctor to de-duplicate code Change-Id: I698b9afc7b15bdfca7176ea3ec823da1ba91957c Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialportinfo.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialportinfo.cpp b/src/serialport/qserialportinfo.cpp index 2b69966..d978665 100644 --- a/src/serialport/qserialportinfo.cpp +++ b/src/serialport/qserialportinfo.cpp @@ -87,14 +87,8 @@ QSerialPortInfo::QSerialPortInfo(const QSerialPortInfo &other) Constructs a QSerialPortInfo object from serial \a port. */ QSerialPortInfo::QSerialPortInfo(const QSerialPort &port) + : QSerialPortInfo(port.portName()) { - const auto infos = QSerialPortInfo::availablePorts(); - for (const QSerialPortInfo &info : infos) { - if (port.portName() == info.portName()) { - *this = info; - break; - } - } } /*! -- cgit v1.2.1 From fbb174127c8f6a5c74db1d4d85e43e8467a16f1c Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 7 Jul 2016 21:37:49 +0300 Subject: Start the write timer only when it is inactive Change-Id: Ie6dd49bec6add204b45f15ff344ba6c92adedb0a Reviewed-by: Sergey Belyashov Reviewed-by: Alex Trotsenko Reviewed-by: Denis Shienkov --- src/serialport/qserialport_win.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index ae32fcf..46fc9d9 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -627,7 +627,8 @@ qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize) QObjectPrivate::connect(startAsyncWriteTimer, &QTimer::timeout, this, &QSerialPortPrivate::_q_startAsyncWrite); startAsyncWriteTimer->setSingleShot(true); } - startAsyncWriteTimer->start(0); + if (!startAsyncWriteTimer->isActive()) + startAsyncWriteTimer->start(); } return maxSize; } -- cgit v1.2.1 From bcb847285171cf63abe24f27c54fc309c54a4696 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Mon, 11 Jul 2016 12:33:40 +0300 Subject: QSerialPortInfo: Extract Method anyOfPort Change-Id: Ic0851ee8d491f29922d55f3c0530ccd21ed171a5 Reviewed-by: Denis Shienkov --- src/serialport/qserialportinfo_win.cpp | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp index 398666e..1bab3e9 100644 --- a/src/serialport/qserialportinfo_win.cpp +++ b/src/serialport/qserialportinfo_win.cpp @@ -187,23 +187,6 @@ static QString devicePortName(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInf return portName; } -class SerialPortNameEqualFunctor -{ -public: - explicit SerialPortNameEqualFunctor(const QString &serialPortName) - : m_serialPortName(serialPortName) - { - } - - bool operator() (const QSerialPortInfo &serialPortInfo) const - { - return serialPortInfo.portName() == m_serialPortName; - } - -private: - const QString &m_serialPortName; -}; - static QString deviceDescription(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInfoData) { @@ -288,6 +271,15 @@ static QString deviceSerialNumber(QString instanceIdentifier, return QString(); } +static bool anyOfPorts(const QList &ports, const QString &portName) +{ + const auto end = ports.end(); + auto isPortNamesEquals = [&portName](const QSerialPortInfo &portInfo) { + return portInfo.portName() == portName; + }; + return std::find_if(ports.begin(), end, isPortNamesEquals) != end; +} + QList QSerialPortInfo::availablePorts() { static const struct { @@ -318,10 +310,8 @@ QList QSerialPortInfo::availablePorts() if (portName.isEmpty() || portName.contains(QLatin1String("LPT"))) continue; - if (std::find_if(serialPortInfoList.begin(), serialPortInfoList.end(), - SerialPortNameEqualFunctor(portName)) != serialPortInfoList.end()) { + if (anyOfPorts(serialPortInfoList, portName)) continue; - } QSerialPortInfoPrivate priv; @@ -346,8 +336,7 @@ QList QSerialPortInfo::availablePorts() const auto portNames = portNamesFromHardwareDeviceMap(); for (const QString &portName : portNames) { - if (std::find_if(serialPortInfoList.cbegin(), serialPortInfoList.cend(), - SerialPortNameEqualFunctor(portName)) == serialPortInfoList.cend()) { + if (!anyOfPorts(serialPortInfoList, portName)) { QSerialPortInfoPrivate priv; priv.portName = portName; priv.device = QSerialPortInfoPrivate::portNameToSystemLocation(portName); -- cgit v1.2.1 From 7346857f4f675f57572d54f15cfad9111af2abde Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Sun, 10 Jul 2016 13:12:37 +0300 Subject: Remove mention of Windows CE support As Windows CE support has been stopped since Qt 5.7. Change-Id: I850c5e1e41508502a9e82491f89488facca40f51 Reviewed-by: Anton Kudryavtsev Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialport.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index d4e9a4f..f7656c5 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -514,10 +514,6 @@ void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo) \li Windows \li Removes the prefix "\\\\.\\" or "//./" from the system location and returns the remainder of the string. - \row - \li Windows CE - \li Removes the suffix ":" from the system location - and returns the remainder of the string. \row \li Unix, BSD \li Removes the prefix "/dev/" from the system location @@ -650,9 +646,9 @@ bool QSerialPort::settingsRestoredOnClose() const after that the opening of the port succeeds. \warning Setting the AllDirections flag is supported on all platforms. - Windows and Windows CE support only this mode. + Windows supports only this mode. - \warning Returns equal baud rate in any direction on Windows, Windows CE. + \warning Returns equal baud rate in any direction on Windows. The default value is Baud9600, i.e. 9600 bits per second. */ -- cgit v1.2.1 From 133dbd59fb04974149d2140b267fce91a7cfd4a2 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Mon, 11 Jul 2016 16:58:29 +0300 Subject: Detach buffer's segment for asynchronous write operation QRingBuffer does not guarantee that the read pointer which is returned by QRingBuffer::readPointer() will stay valid after calling QRingBuffer::reserve() or QRingBuffer::append(). Thus, we need to detach the buffer's segment and pass it to the WriteFile() function to ensure it stays unmodified for the whole time of the asynchronous operation. Change-Id: I5a42086b4339a050a4df57c39348864502be2c74 Reviewed-by: Oswald Buddenhagen Reviewed-by: Alex Trotsenko Reviewed-by: Sergey Belyashov Reviewed-by: Anton Kudryavtsev Reviewed-by: Denis Shienkov --- src/serialport/qserialport.cpp | 9 +-------- src/serialport/qserialport_p.h | 2 +- src/serialport/qserialport_win.cpp | 22 +++++++++------------- 3 files changed, 11 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index 481b07e..8b4449b 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -107,7 +107,6 @@ QSerialPortPrivate::QSerialPortPrivate() , startAsyncWriteTimer(0) , originalEventMask(0) , triggeredEventMask(0) - , actualBytesToWrite(0) #elif defined(Q_OS_UNIX) , descriptor(-1) , readNotifier(0) @@ -1260,13 +1259,7 @@ qint64 QSerialPort::bytesAvailable() const qint64 QSerialPort::bytesToWrite() const { Q_D(const QSerialPort); - qint64 bytes = QIODevice::bytesToWrite(); -#ifdef Q_OS_WIN32 - bytes += d->actualBytesToWrite; -#else - bytes += d->writeBuffer.size(); -#endif - return bytes; + return QIODevice::bytesToWrite() + d->writeBuffer.size(); } /*! diff --git a/src/serialport/qserialport_p.h b/src/serialport/qserialport_p.h index 81febed..567ca19 100644 --- a/src/serialport/qserialport_p.h +++ b/src/serialport/qserialport_p.h @@ -224,6 +224,7 @@ public: COMMTIMEOUTS restoredCommTimeouts; HANDLE handle; QByteArray readChunkBuffer; + QByteArray writeChunkBuffer; bool communicationStarted; bool writeStarted; bool readStarted; @@ -234,7 +235,6 @@ public: OVERLAPPED writeCompletionOverlapped; DWORD originalEventMask; DWORD triggeredEventMask; - qint64 actualBytesToWrite; #elif defined(Q_OS_UNIX) diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 1680d5a..056cc31 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -116,7 +116,6 @@ void QSerialPortPrivate::close() readStarted = false; writeStarted = false; writeBuffer.clear(); - actualBytesToWrite = 0; if (settingsRestoredOnClose) { ::SetCommState(handle, &restoredDcb); @@ -198,10 +197,8 @@ bool QSerialPortPrivate::clear(QSerialPort::Directions directions) DWORD flags = 0; if (directions & QSerialPort::Input) flags |= PURGE_RXABORT | PURGE_RXCLEAR; - if (directions & QSerialPort::Output) { + if (directions & QSerialPort::Output) flags |= PURGE_TXABORT | PURGE_TXCLEAR; - actualBytesToWrite = 0; - } if (!::PurgeComm(handle, flags)) { setError(getSystemError()); return false; @@ -275,7 +272,7 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs) bool QSerialPortPrivate::waitForBytesWritten(int msecs) { - if (writeBuffer.isEmpty()) + if (writeBuffer.isEmpty() && writeChunkBuffer.isEmpty()) return false; if (!writeStarted && !_q_startAsyncWrite()) @@ -453,12 +450,13 @@ bool QSerialPortPrivate::completeAsyncWrite(qint64 bytesTransferred) if (writeStarted) { if (bytesTransferred == qint64(-1)) { + writeChunkBuffer.clear(); writeStarted = false; return false; - } else if (bytesTransferred > 0) { - writeBuffer.free(bytesTransferred); - emit q->bytesWritten(bytesTransferred); } + Q_ASSERT(bytesTransferred == writeChunkBuffer.size()); + writeChunkBuffer.clear(); + emit q->bytesWritten(bytesTransferred); writeStarted = false; } @@ -525,10 +523,10 @@ bool QSerialPortPrivate::_q_startAsyncWrite() if (writeBuffer.isEmpty() || writeStarted) return true; - const int writeBytes = writeBuffer.nextDataBlockSize(); + writeChunkBuffer = writeBuffer.read(); ::ZeroMemory(&writeCompletionOverlapped, sizeof(writeCompletionOverlapped)); - if (!::WriteFile(handle, writeBuffer.readPointer(), - writeBytes, Q_NULLPTR, &writeCompletionOverlapped)) { + if (!::WriteFile(handle, writeChunkBuffer.constData(), + writeChunkBuffer.size(), Q_NULLPTR, &writeCompletionOverlapped)) { QSerialPortErrorInfo error = getSystemError(); if (error.errorCode != QSerialPort::NoError) { @@ -539,7 +537,6 @@ bool QSerialPortPrivate::_q_startAsyncWrite() } } - actualBytesToWrite -= writeBytes; writeStarted = true; return true; } @@ -574,7 +571,6 @@ qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize) Q_Q(QSerialPort); ::memcpy(writeBuffer.reserve(maxSize), data, maxSize); - actualBytesToWrite += maxSize; if (!writeBuffer.isEmpty() && !writeStarted) { if (!startAsyncWriteTimer) { -- cgit v1.2.1