diff options
Diffstat (limited to 'src/serialport/qserialport_win.cpp')
-rw-r--r-- | src/serialport/qserialport_win.cpp | 205 |
1 files changed, 118 insertions, 87 deletions
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 7cbb81d..9ab4448 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; @@ -122,7 +210,6 @@ void QSerialPortPrivate::close() readStarted = false; writeStarted = false; writeBuffer.clear(); - actualBytesToWrite = 0; if (settingsRestoredOnClose) { ::SetCommState(handle, &restoredDcb); @@ -204,10 +291,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; @@ -281,7 +366,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()) @@ -319,7 +404,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 +415,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 +426,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 +437,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 +448,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); } @@ -431,10 +469,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; @@ -459,12 +495,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; } @@ -531,10 +568,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, nullptr, &writeCompletionOverlapped)) { + if (!::WriteFile(handle, writeChunkBuffer.constData(), + writeChunkBuffer.size(), nullptr, &writeCompletionOverlapped)) { QSerialPortErrorInfo error = getSystemError(); if (error.errorCode != QSerialPort::NoError) { @@ -545,7 +582,6 @@ bool QSerialPortPrivate::_q_startAsyncWrite() } } - actualBytesToWrite -= writeBytes; writeStarted = true; return true; } @@ -579,8 +615,7 @@ qint64 QSerialPortPrivate::writeData(const char *data, qint64 maxSize) { Q_Q(QSerialPort); - ::memcpy(writeBuffer.reserve(maxSize), data, maxSize); - actualBytesToWrite += maxSize; + writeBuffer.append(data, maxSize); if (!writeBuffer.isEmpty() && !writeStarted) { if (!startAsyncWriteTimer) { @@ -588,7 +623,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; } @@ -623,17 +659,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; |