From 90dbacd9dae2b82fad9c68ca95c06a6d6b1ae030 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Wed, 25 Dec 2013 16:32:28 +0400 Subject: Fix the waitForReadyRead() behavior on Windows It is necessary to compare size of the readBuffer before and after completion of each read operation. If size of readBuffer are equal it means that are no more data available for reading. In this case the method should returns true if an initial size of readBuffer is not equal to the current size of readBuffer. Otherwise in all other cases should be continue waiting until timeout has been expired. Also must not to do check for the NoError code and to hope for valid value of this code inside waitForReadyRead(). Because a last error code do not clears automatically. It lead to false returns of this method in case the error number is not equal to NoError (for example it error remained after failed of any previous method). This check should be implemented in a different way in case of need. But at present this check is unnecessary because result of the waitAnyEvent() cover it. Task-number: QTBUG-33987 Change-Id: Ic8d8e3806fd4863c2720ffb83d5c19eae54d57f0 Reviewed-by: Sergey Belyashov Reviewed-by: Laszlo Papp --- src/serialport/qserialport_win.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index e460c78..4a72da0 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -381,6 +381,9 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs) QElapsedTimer stopWatch; stopWatch.start(); + const qint64 initialReadBufferSize = readBuffer.size(); + qint64 currentReadBufferSize = initialReadBufferSize; + do { bool timedOut = false; HANDLE triggeredEvent = 0; @@ -394,11 +397,12 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs) if (triggeredEvent == communicationOverlapped.hEvent) { _q_canCompleteCommunication(); - if (error != QSerialPort::NoError) - return false; } else if (triggeredEvent == readCompletionOverlapped.hEvent) { _q_canCompleteRead(); - return error == QSerialPort::NoError; + if (qint64(readBuffer.size()) != currentReadBufferSize) + currentReadBufferSize = readBuffer.size(); + else if (initialReadBufferSize != currentReadBufferSize) + return true; } else if (triggeredEvent == writeCompletionOverlapped.hEvent) { _q_canCompleteWrite(); } else { -- cgit v1.2.1 From 14b543782535e34bb28cc82c46e1e1ddda6a3898 Mon Sep 17 00:00:00 2001 From: Laszlo Papp Date: Thu, 16 Jan 2014 18:11:00 +0000 Subject: Fix the broken handle() documentation This is likely to be happening due to the mismatching function signature include the return type between the header and source file. Two things are being fixed: 1) Dropped scope for the Handle just like with the winId case in QWidget. 2) "const" qualifier is now added for the method. Here you can see the documentation that it is empty: http://qt-project.org/doc/qt-5/qserialport.html#handle Change-Id: I5e9e0732cfd746a863de523fe90e58eafa42c081 Reviewed-by: Alex Henrie Reviewed-by: Sergey Belyashov Reviewed-by: Martin Smith --- src/serialport/qserialport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index 5d9442e..1fca425 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -1279,7 +1279,7 @@ bool QSerialPort::waitForReadyRead(int msecs) } /*! - \fn QSerialPort::Handle QSerialPort::handle() + \fn Handle QSerialPort::handle() const \since 5.2 Returns the native serial port descriptor of the object. If the serial port -- cgit v1.2.1 From 1927f5751a86988a9615d5abdf7fe4ef69d41180 Mon Sep 17 00:00:00 2001 From: Laszlo Papp Date: Fri, 24 Jan 2014 08:08:14 +0000 Subject: Refactor the reference in the documentation for property setters/getters The documentation contains broken links due to this, and it is also inconsistent with the rest. Properties should be referred to as properties, not individual methods like setter, getter, notified signal, etc. The change is tested with "make docs" and the broken links are history. Change-Id: Id94cba1f88503754318c865793229e3d3947bec6 Reviewed-by: Sergey Belyashov Reviewed-by: Jerome Pasion Reviewed-by: Martin Smith --- src/serialport/qserialport.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index 1fca425..b41e7a5 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -116,10 +116,10 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed) port to the desired setting using the setBaudRate(), setDataBits(), setParity(), setStopBits(), and setFlowControl() methods. - The status of the control pinout signals is determined with the - isDataTerminalReady(), isRequestToSend, and pinoutSignals() methods. To - change the control line status, use the setDataTerminalReady(), and - setRequestToSend() methods. + There are a couple of properties to work with the pinout signals namely: + QSerialPort::dataTerminalReady, QSerialPort::requestToSend. It is also + possible to use the pinoutSignals() method to query the current pinout + signals set. Once you know that the ports are ready to read or write, you can use the read() or write() methods. Alternatively the @@ -981,8 +981,7 @@ bool QSerialPort::isRequestToSend() \note The serial port has to be open before trying to get the pinout signals; otherwise returns NoSignal and sets the NotOpenError error code. - \sa isDataTerminalReady(), isRequestToSend, setDataTerminalReady(), - setRequestToSend() + \sa QSerialPort::dataTerminalReady, QSerialPort::requestToSend */ QSerialPort::PinoutSignals QSerialPort::pinoutSignals() { -- cgit v1.2.1 From 84ec01711a9869da26f04e14fda5a5fc54073e98 Mon Sep 17 00:00:00 2001 From: Laszlo Papp Date: Mon, 20 Jan 2014 17:48:41 +0000 Subject: Obsolete the TxD/RxD signals They are not much of use due to the low-level OS limitations as of now, hence the obsolete proposal. It can be brought back to life at any point when we have a more clear idea what to do with this API. "faking" this signal as RealTterm probably does it, is not a nice impression for the end users. That would be more like a software "signal" (which we already have in place) rather than a real pinout hardware signal. It is interesting why Windows, Linux, etc do not provide an option for this. There must be some strong reason for it. Change-Id: Ia065e2ee9226d16e724f5e2690b25b954329d78e Reviewed-by: Denis Shienkov Reviewed-by: Sergey Belyashov --- src/serialport/qserialport.cpp | 10 ++++++++-- src/serialport/qserialport.h | 22 ++++++++++++---------- 2 files changed, 20 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index b41e7a5..aa9b616 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -291,8 +291,14 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed) This enum describes the possible RS-232 pinout signals. \value NoSignal No line active - \value TransmittedDataSignal TxD (Transmitted Data). - \value ReceivedDataSignal RxD (Received Data). + \value TransmittedDataSignal TxD (Transmitted Data). This value is + obsolete. It is provided to keep old + source code working. We strongly + advise against using it in new code. + \value ReceivedDataSignal RxD (Received Data). This value is + obsolete. It is provided to keep old + source code working. We strongly + advise against using it in new code. \value DataTerminalReadySignal DTR (Data Terminal Ready). \value DataCarrierDetectSignal DCD (Data Carrier Detect). \value DataSetReadySignal DSR (Data Set Ready). diff --git a/src/serialport/qserialport.h b/src/serialport/qserialport.h index c07af91..795cf33 100644 --- a/src/serialport/qserialport.h +++ b/src/serialport/qserialport.h @@ -131,16 +131,6 @@ public: UnknownFlowControl = -1 }; -#if QT_DEPRECATED_SINCE(5, 2) -#if defined _MSC_VER -#pragma deprecated(UnknownBaud) -#pragma deprecated(UnknownDataBits) -#pragma deprecated(UnknownParity) -#pragma deprecated(UnknownStopBits) -#pragma deprecated(UnknownFlowControl) -#endif -#endif - enum PinoutSignal { NoSignal = 0x00, TransmittedDataSignal = 0x01, @@ -156,6 +146,18 @@ public: }; Q_DECLARE_FLAGS(PinoutSignals, PinoutSignal) +#if QT_DEPRECATED_SINCE(5, 2) +#if defined _MSC_VER +#pragma deprecated(UnknownBaud) +#pragma deprecated(UnknownDataBits) +#pragma deprecated(UnknownParity) +#pragma deprecated(UnknownStopBits) +#pragma deprecated(UnknownFlowControl) +#pragma deprecated(TransmittedDataSignal) +#pragma deprecated(ReceivedDataSignal) +#endif +#endif + #if QT_DEPRECATED_SINCE(5, 2) enum DataErrorPolicy { SkipPolicy, -- cgit v1.2.1 From 61db17af204db5d40e3ae5392c4c134980619e09 Mon Sep 17 00:00:00 2001 From: Jeff Tranter Date: Wed, 29 Jan 2014 14:18:58 -0500 Subject: Fix some typos in documentation. Fix some spelling and grammatical errors in comments that show up in Qt documentation. No changes to code. Change-Id: I185458e162d115eac25326d239b851b5e14ed5cf Reviewed-by: Laszlo Papp --- src/serialport/qserialport.cpp | 54 +++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index cd0c681..56aabda 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -212,12 +212,12 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed) \value Data5 The number of data bits in each character is 5. It is used for Baudot code. It generally only makes - sense with older equipments such as teleprinters. + sense with older equipment such as teleprinters. \value Data6 The number of data bits in each character is 6. It is rarely used. \value Data7 The number of data bits in each character is 7. It is used for true ASCII. It generally only makes - sense with older equipments such as teleprinters. + sense with older equipment such as teleprinters. \value Data8 The number of data bits in each character is 8. It is used for most kinds of data, as this size matches the size of a byte. It is almost universally used in @@ -261,9 +261,9 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed) This enum describes the number of stop bits used. \value OneStop 1 stop bit. - \value OneAndHalfStop 1.5 stop bits. This is only for Windows platform. + \value OneAndHalfStop 1.5 stop bits. This is only for the Windows platform. \value TwoStop 2 stop bits. - \value UnknownStopBits Unknown number of stop bit. This value is obsolete. + \value UnknownStopBits Unknown number of stop bits. This value is obsolete. It is provided to keep old source code working. We strongly advise against using it in new code. @@ -314,7 +314,7 @@ int QSerialPortPrivateData::timeoutValue(int msecs, int elapsed) while parity errors were detected. \value SkipPolicy Skips the bad character. - \value PassZeroPolicy Replaces bad character to zero. + \value PassZeroPolicy Replaces bad character with zero. \value IgnorePolicy Ignores the error for a bad character. \value StopReceivingPolicy Stops data reception on error. \value UnknownPolicy Unknown policy. @@ -422,7 +422,7 @@ QSerialPort::~QSerialPort() /*! Sets the \a name of the serial port. - The name of the serial port can be passed on as either a short name or + The name of the serial port can be passed as either a short name or the long system location if necessary. \sa portName(), QSerialPortInfo @@ -445,9 +445,9 @@ void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo) } /*! - Returns the name set by setPort() or to the QSerialPort constructors. - This name is short, i.e. it extract and convert out from the internal - variable system location of the device. Conversion algorithm is + Returns the name set by setPort() or passed to the QSerialPort constructor. + This name is short, i.e. it is extracted and converted from the internal + variable system location of the device. The conversion algorithm is platform specific: \table \header @@ -459,7 +459,7 @@ void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo) and returns the remainder of the string. \row \li Windows CE - \li Removes the postfix ":" from the system location + \li Removes the suffix ":" from the system location and returns the remainder of the string. \row \li Symbian @@ -494,7 +494,7 @@ QString QSerialPort::portName() const obtained by calling the error() method. \note This method has to be called before setting certain serial port - parameters. See each property documentation for details when it is + parameters. See each property documentation for the details of when it is necessary. \warning The \a mode has to be QIODevice::ReadOnly, QIODevice::WriteOnly, @@ -552,11 +552,11 @@ void QSerialPort::close() /*! \property QSerialPort::settingsRestoredOnClose - \brief the flag which allows to restore the previous settings while closing + \brief the flag which specifies to restore the previous settings when closing the serial port. If this flag is true, the settings will be restored; otherwise not. - The default state of the QSerialPort class is configured to restore the + The default state of the QSerialPort class is to restore the settings. */ void QSerialPort::setSettingsRestoredOnClose(bool restore) @@ -578,9 +578,9 @@ bool QSerialPort::settingsRestoredOnClose() const /*! \fn void QSerialPort::settingsRestoredOnCloseChanged(bool restore) - This signal is emitted after the flag which allows to restore the + This signal is emitted after the flag which specifies to restore the previous settings while closing the serial port has been changed. The new - flag which allows to restore the previous settings while closing the serial + flag which specifies to restore the previous settings while closing the serial port is passed as \a restore. \sa QSerialPort::settingsRestoredOnClose @@ -602,8 +602,8 @@ bool QSerialPort::settingsRestoredOnClose() const with the kernel and hardware. Hence, the two scenarios cannot be completely compared to each other. - \warning Only the AllDirections flag is support for setting this property on - Windows, Windows CE, and Symbian. + \warning Setting the AllDirections flag is only supported on + the Windows, Windows CE, and Symbian platforms. \warning Returns equal baud rate in any direction on Windows, Windows CE, and Symbian. @@ -1029,7 +1029,7 @@ bool QSerialPort::flush() /*! Discards all characters from the output or input buffer, depending on - given directions \a directions. Including clear an internal class buffers and + given directions \a directions. This includes clearing the internal class buffers and the UART (driver) buffers. Also terminate pending read or write operations. If successful, returns true; otherwise returns false. @@ -1083,8 +1083,8 @@ bool QSerialPort::atEnd() const /*! \property QSerialPort::dataErrorPolicy - \brief the error policy how the process receives the character in case of - parity error detection. + \brief the error policy for how the process receives characters in the case where + a parity error is detected. \obsolete If the setting is successful, returns true; otherwise returns false. The @@ -1126,9 +1126,9 @@ QSerialPort::DataErrorPolicy QSerialPort::dataErrorPolicy() const \fn void QSerialPort::dataErrorPolicyChanged(DataErrorPolicy policy) \obsolete - This signal is emitted after the error policy how the process receives the - character in case of parity error detection has been changed. The new error - policy how the process receives the character in case of parity error + This signal is emitted after the error policy for how the process receives + characters in case of parity error detection has been changed. The new error + policy for how the process receives the character in case of parity error detection is passed as \a policy. \sa QSerialPort::dataErrorPolicy @@ -1159,8 +1159,8 @@ void QSerialPort::clearError() /*! \fn void QSerialPort::error(SerialPortError error) - This signal is emitted after the error has been changed. The new erroris - passed as \a error. + This signal is emitted after the error has been changed. The new error + is passed as \a error. \sa QSerialPort::error */ @@ -1186,14 +1186,14 @@ qint64 QSerialPort::readBufferSize() const size bytes. If the buffer size is limited to a certain size, QSerialPort - will not buffer more than this size of data. Exceptionally, a buffer + will not buffer more than this size of data. The special case of a buffer size of 0 means that the read buffer is unlimited and all incoming data is buffered. This is the default. This option is useful if the data is only read at certain points in time (for instance in a real-time streaming application) or if the serial port should be protected against receiving too much data, which may - eventually causes that the application runs out of memory. + eventually cause the application to run out of memory. \sa readBufferSize(), read() */ -- cgit v1.2.1 From df6baa1de99a65dd23586cb2fb308c3a24dd198e Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Fri, 24 Jan 2014 00:11:25 +0400 Subject: Handle the ERROR_INVALID_NAME error code If the user tries to open the serial port with empty port name, Windows returns this error code. The error will be exposed as QSerialPort::DeviceNotFoundError from now. Tested only on Windows 8 (32 bit) with on-board serial port as well as an usb dongle (PL2303) using Qt4 and Qt5. Change-Id: I9a56a7e51dbdab684b6d2a9fdf6398d8d5018e1c Reviewed-by: Laszlo Papp Reviewed-by: Sergey Belyashov --- src/serialport/qserialport_win.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index f9e8a5e..6d288d1 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -862,6 +862,9 @@ QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const case ERROR_FILE_NOT_FOUND: error = QSerialPort::DeviceNotFoundError; break; + case ERROR_INVALID_NAME: + error = QSerialPort::DeviceNotFoundError; + break; case ERROR_ACCESS_DENIED: error = QSerialPort::PermissionError; break; -- cgit v1.2.1 From 1824ad0a6e97e293098c94a038abd7b2343bf572 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 23 Jan 2014 15:32:13 +0400 Subject: Optimize of writing sequence algorithm * The writeSequenceStarted shall be set to true after a successful call of WriteFile() and to be dropped to false in case of write completion. * The method startAsyncWrite() shall not call WriteFile() if the writeBuffer is empty or writing sequence is already started. Also now there is no sense to check a validity of pointers on data in writeBuffer before call of WriteFile() because writeBuffer can not be empty. * It is also expedient to free the writeBuffer in _q_completeAsyncWrite() method only if numberOfBytesTransferred is not zero. Tested on Windows 8 with the on-board and the USB (PL2303) serial ports. Change-Id: Ib70276705fcc3f2396bf7dd6cf6977b62382a64b Reviewed-by: Denis Shienkov --- src/serialport/qserialport_win.cpp | 42 +++++++++++++++----------------------- 1 file changed, 17 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 6d288d1..17b3fb7 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -595,15 +595,13 @@ void QSerialPortPrivate::_q_completeAsyncWrite() q->setError(decodeSystemError()); } - writeBuffer.free(numberOfBytesTransferred); - - if (numberOfBytesTransferred > 0) + if (numberOfBytesTransferred > 0) { + writeBuffer.free(numberOfBytesTransferred); emit q->bytesWritten(numberOfBytesTransferred); + } - if (writeBuffer.isEmpty()) - writeSequenceStarted = false; - else - startAsyncWrite(); + writeSequenceStarted = false; + startAsyncWrite(); } bool QSerialPortPrivate::startAsyncCommunication() @@ -656,30 +654,24 @@ bool QSerialPortPrivate::startAsyncWrite() { Q_Q(QSerialPort); - qint64 nextSize = writeBuffer.nextDataBlockSize(); - const char *ptr = writeBuffer.readPointer(); - - // no more data to write - if (!ptr || nextSize == 0) + if (writeBuffer.isEmpty() || writeSequenceStarted) return true; - writeSequenceStarted = true; - initializeOverlappedStructure(writeCompletionOverlapped); - if (::WriteFile(descriptor, ptr, nextSize, NULL, &writeCompletionOverlapped)) - return true; - - QSerialPort::SerialPortError error = decodeSystemError(); - if (error != QSerialPort::NoError) { - writeSequenceStarted = false; - - if (error != QSerialPort::ResourceError) - error = QSerialPort::WriteError; + if (!::WriteFile(descriptor, writeBuffer.readPointer(), + writeBuffer.nextDataBlockSize(), + NULL, &writeCompletionOverlapped)) { - q->setError(error); - return false; + QSerialPort::SerialPortError error = decodeSystemError(); + if (error != QSerialPort::NoError) { + if (error != QSerialPort::ResourceError) + error = QSerialPort::WriteError; + q->setError(error); + return false; + } } + writeSequenceStarted = true; return true; } -- cgit v1.2.1 From 1335bcd134c012cd00dd6c542bc7b734269b6479 Mon Sep 17 00:00:00 2001 From: Laszlo Papp Date: Thu, 16 Jan 2014 11:47:14 +0000 Subject: Rewrite the short description of the handle() method * handle() is duplicated since the description explains that method. * It is pointless to put the "object" into the sentence. * It is consistent to start the sentence with the "if". Here goes a typical example that is worth following with consistency: "If successful, returns true; otherwise returns false." Change-Id: I1c7648237c75381b8452b8c47a59445fff58ad34 Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialport.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport.cpp b/src/serialport/qserialport.cpp index 56aabda..b878063 100644 --- a/src/serialport/qserialport.cpp +++ b/src/serialport/qserialport.cpp @@ -1282,8 +1282,8 @@ bool QSerialPort::waitForReadyRead(int msecs) \fn QSerialPort::Handle QSerialPort::handle() \since 5.2 - Returns the native serial port descriptor of the object. If the serial port - is not open or the platform is not supported, handle() returns -1. + If the platform is supported and the serial port is open, returns the native + serial port handle; otherwise returns -1. \warning This function is for expert use only; use it at your own risk. Furthermore, this function carries no compatibility promise between minor -- cgit v1.2.1 From e08cc29223aeab7da216963ae80d619f387109b9 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Sun, 26 Jan 2014 15:19:04 +0400 Subject: Add listing of virtual ports from the "AGG Software" The current algorithm takes a name of the serial port from the PortName property which is in the Registry. This value is filled out by the Ports class installer automatically: http://msdn.microsoft.com/en-us/library/windows/hardware/ff546514%28v=vs.85%29.aspx But at using the "AGG Software" software this property is absent. Therefore the algorithm ignores these serial ports. The simplest workaround is use of the PortNumber property which identifies a port number for this software. In this case a port name defines indirectly, by adding a port number to the "COM" suffix. This does not influence other serial ports which are defined through PortName property. Tested on Windows XP and Windows 8 with the cenumerator example. Task-number: QTBUG-32774 Change-Id: I8cda3ed992ff80742511a2952d3fb7e8ac6edc81 Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialportinfo_win.cpp | 37 +++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp index 51f529e..54ea786 100644 --- a/src/serialport/qserialportinfo_win.cpp +++ b/src/serialport/qserialportinfo_win.cpp @@ -137,28 +137,37 @@ static QString deviceInstanceIdentifier(HDEVINFO deviceInfoSet, static QString devicePortName(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInfoData) { - static const wchar_t portKeyName[] = L"PortName"; - const HKEY key = ::SetupDiOpenDevRegKey(deviceInfoSet, deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); if (key == INVALID_HANDLE_VALUE) return QString(); - DWORD dataSize; - if (::RegQueryValueEx(key, portKeyName, NULL, NULL, NULL, &dataSize) != ERROR_SUCCESS) { - ::RegCloseKey(key); - return QString(); - } - - QByteArray data(dataSize, 0); + static const QStringList portNameRegistryKeyList = QStringList() + << QStringLiteral("PortName") + << QStringLiteral("PortNumber"); - if (::RegQueryValueEx(key, portKeyName, NULL, NULL, - reinterpret_cast(data.data()), &dataSize) != ERROR_SUCCESS) { - ::RegCloseKey(key); - return QString(); + QString portName; + foreach (const QString &portNameKey, portNameRegistryKeyList) { + DWORD bytesRequired = 0; + DWORD dataType = 0; + QByteArray outputBuffer; + forever { + const LONG ret = ::RegQueryValueEx(key, reinterpret_cast(portNameKey.utf16()), NULL, &dataType, + reinterpret_cast(outputBuffer.data()), &bytesRequired); + if (ret == ERROR_MORE_DATA) { + outputBuffer.resize(bytesRequired); + continue; + } else if (ret == ERROR_SUCCESS) { + if (dataType == REG_SZ) + portName = QString::fromWCharArray((reinterpret_cast(outputBuffer.constData()))); + else if (dataType == REG_DWORD) + portName = QStringLiteral("COM%1").arg(*(PDWORD(outputBuffer.constData()))); + } + break; + } } ::RegCloseKey(key); - return QString::fromWCharArray(((const wchar_t *)data.constData())); + return portName; } class SerialPortNameEqualFunctor -- cgit v1.2.1 From 3660b4d0ca3dae1c69a3f4e817561844a37d334e Mon Sep 17 00:00:00 2001 From: Laszlo Papp Date: Sun, 2 Feb 2014 09:44:52 +0000 Subject: Use the ternary operator meant for this purpose rather than two returns Change-Id: Ie6b17d95b83ad751130305a6d44cdead3cd46da6 Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialport_win.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 17b3fb7..0a9aec5 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -321,9 +321,7 @@ bool QSerialPortPrivate::sendBreak(int duration) bool QSerialPortPrivate::setBreakEnabled(bool set) { - if (set) - return ::SetCommBreak(descriptor); - return ::ClearCommBreak(descriptor); + return (set ? ::SetCommBreak(descriptor) : ::ClearCommBreak(descriptor)); } qint64 QSerialPortPrivate::systemInputQueueSize () -- cgit v1.2.1 From 78b8866c4d3e846f3dd142bc4bac38385298dc40 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 30 Jan 2014 19:52:48 +0400 Subject: Add enumeration through the SERIALCOMM registry entry When using some software that provide an virtual serial ports functionality is impossible to use the Win32 SetupAPI feature to enumerate these serial ports. For example, such software is "Virtual Serial Ports Emulator" from Eterlogic: http://www.eterlogic.com/Products.VSPE.html The only possible simple way to detect these serial ports it to read the registry key HARDWARE\\DEVICEMAP\\SERIALCOMM: http://msdn.microsoft.com/en-us/library/windows/hardware/ff546502%28v=vs.85%29.aspx In this case it is possible to get only a name of the serial port without any additional information. This method is simply addition to the main SetupAPI functionality. Task-number: QTBUG-36526 Change-Id: Ib505aee66b74b6a8ebe16cf88c3060c8267397a0 Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialportinfo_win.cpp | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'src') diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp index 54ea786..9fceb31 100644 --- a/src/serialport/qserialportinfo_win.cpp +++ b/src/serialport/qserialportinfo_win.cpp @@ -75,6 +75,35 @@ static inline const QList& guidFlagsPairs() return guidFlagsPairList; } +static QStringList portNamesFromHardwareDeviceMap() +{ + HKEY hKey = 0; + if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) + return QStringList(); + + QStringList result; + DWORD index = 0; + static const DWORD maximumValueNameInChars = 16383; + QByteArray outputValueName(maximumValueNameInChars * sizeof(wchar_t), 0); + QByteArray outputBuffer; + DWORD requiredDataBytes = 0; + forever { + DWORD requiredValueNameChars = maximumValueNameInChars; + const LONG ret = ::RegEnumValue(hKey, index, reinterpret_cast(outputValueName.data()), &requiredValueNameChars, + NULL, NULL, reinterpret_cast(outputBuffer.data()), &requiredDataBytes); + if (ret == ERROR_MORE_DATA) { + outputBuffer.resize(requiredDataBytes); + } else if (ret == ERROR_SUCCESS) { + result.append(QString::fromWCharArray(reinterpret_cast(outputBuffer.constData()))); + ++index; + } else { + break; + } + } + ::RegCloseKey(hKey); + return result; +} + static QVariant deviceRegistryProperty(HDEVINFO deviceInfoSet, PSP_DEVINFO_DATA deviceInfoData, DWORD property) @@ -256,6 +285,17 @@ QList QSerialPortInfo::availablePorts() } ::SetupDiDestroyDeviceInfoList(deviceInfoSet); } + + foreach (const QString &portName, portNamesFromHardwareDeviceMap()) { + if (std::find_if(serialPortInfoList.begin(), serialPortInfoList.end(), + SerialPortNameEqualFunctor(portName)) == serialPortInfoList.end()) { + QSerialPortInfo serialPortInfo; + serialPortInfo.d_ptr->portName = portName; + serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(portName); + serialPortInfoList.append(serialPortInfo); + } + } + return serialPortInfoList; } -- cgit v1.2.1 From 7101b2f0c72e20bcce0e5ef11620208c0080c416 Mon Sep 17 00:00:00 2001 From: Laszlo Papp Date: Sat, 1 Feb 2014 19:03:52 +0000 Subject: Add error handling to some missing functions Change-Id: If8dee1819d493fa4b27eba99de611c61bfdfe7a3 Reviewed-by: Denis Shienkov Reviewed-by: Sergey Belyashov --- src/serialport/qserialport_unix.cpp | 84 ++++++++++++++++++++++++++++++------- src/serialport/qserialport_unix_p.h | 4 +- src/serialport/qserialport_win.cpp | 53 ++++++++++++++++++----- 3 files changed, 112 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index b994a0e..0542731 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -227,7 +227,8 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) } #ifdef TIOCEXCL - ::ioctl(descriptor, TIOCEXCL); + if (::ioctl(descriptor, TIOCEXCL) == -1) + q->setError(decodeSystemError()); #endif if (::tcgetattr(descriptor, &restoredTermios) == -1) { @@ -258,16 +259,23 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) void QSerialPortPrivate::close() { + Q_Q(QSerialPort); + if (settingsRestoredOnClose) { - ::tcsetattr(descriptor, TCSANOW, &restoredTermios); + if (::tcsetattr(descriptor, TCSANOW, &restoredTermios) == -1) + q->setError(decodeSystemError()); + #ifdef Q_OS_LINUX - if (isCustomBaudRateSupported) - ::ioctl(descriptor, TIOCSSERIAL, &restoredSerialInfo); + if (isCustomBaudRateSupported) { + if (::ioctl(descriptor, TIOCSSERIAL, &restoredSerialInfo) == -1) + q->setError(decodeSystemError()); + } #endif } #ifdef TIOCNXCL - ::ioctl(descriptor, TIOCNXCL); + if (::ioctl(descriptor, TIOCNXCL) == -1) + q->setError(decodeSystemError()); #endif if (readNotifier) { @@ -288,7 +296,8 @@ void QSerialPortPrivate::close() exceptionNotifier = 0; } - ::close(descriptor); + if (::close(descriptor) == -1) + q->setError(decodeSystemError()); if (lockFileScopedPointer->isLocked()) lockFileScopedPointer->unlock(); @@ -358,14 +367,28 @@ QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals() bool QSerialPortPrivate::setDataTerminalReady(bool set) { + Q_Q(QSerialPort); + int status = TIOCM_DTR; - return ::ioctl(descriptor, set ? TIOCMBIS : TIOCMBIC, &status) != -1; + if (::ioctl(descriptor, set ? TIOCMBIS : TIOCMBIC, &status) == -1) { + q->setError(decodeSystemError()); + return false; + } + + return true; } bool QSerialPortPrivate::setRequestToSend(bool set) { + Q_Q(QSerialPort); + int status = TIOCM_RTS; - return ::ioctl(descriptor, set ? TIOCMBIS : TIOCMBIC, &status) != -1; + if (::ioctl(descriptor, set ? TIOCMBIS : TIOCMBIC, &status) == -1) { + q->setError(decodeSystemError()); + return false; + } + + return true; } bool QSerialPortPrivate::flush() @@ -380,36 +403,65 @@ bool QSerialPortPrivate::flush() bool QSerialPortPrivate::clear(QSerialPort::Directions directions) { - return ::tcflush(descriptor, (directions == QSerialPort::AllDirections) - ? TCIOFLUSH : (directions & QSerialPort::Input) ? TCIFLUSH : TCOFLUSH) != -1; + Q_Q(QSerialPort); + + if (::tcflush(descriptor, (directions == QSerialPort::AllDirections) + ? TCIOFLUSH : (directions & QSerialPort::Input) ? TCIFLUSH : TCOFLUSH) == -1) { + q->setError(decodeSystemError()); + return false; + } + + return true; } bool QSerialPortPrivate::sendBreak(int duration) { - return ::tcsendbreak(descriptor, duration) != -1; + Q_Q(QSerialPort); + + if (::tcsendbreak(descriptor, duration) == -1) { + q->setError(decodeSystemError()); + return false; + } + + return true; } bool QSerialPortPrivate::setBreakEnabled(bool set) { - return ::ioctl(descriptor, set ? TIOCSBRK : TIOCCBRK) != -1; + Q_Q(QSerialPort); + + if (::ioctl(descriptor, set ? TIOCSBRK : TIOCCBRK) == -1) { + q->setError(decodeSystemError()); + return false; + } + + return true; } -qint64 QSerialPortPrivate::systemInputQueueSize () const +qint64 QSerialPortPrivate::systemInputQueueSize () { + Q_Q(QSerialPort); + int nbytes = 0; #ifdef TIOCINQ - if (::ioctl(descriptor, TIOCINQ, &nbytes) == -1) + if (::ioctl(descriptor, TIOCINQ, &nbytes) == -1) { + q->setError(decodeSystemError()); return -1; + } #endif return nbytes; } -qint64 QSerialPortPrivate::systemOutputQueueSize () const +qint64 QSerialPortPrivate::systemOutputQueueSize () { + Q_Q(QSerialPort); + int nbytes = 0; #ifdef TIOCOUTQ - if (::ioctl(descriptor, TIOCOUTQ, &nbytes) == -1) + if (::ioctl(descriptor, TIOCOUTQ, &nbytes) == -1) { + q->setError(decodeSystemError()); return -1; + } #endif return nbytes; } diff --git a/src/serialport/qserialport_unix_p.h b/src/serialport/qserialport_unix_p.h index 7dbb760..c1bb685 100644 --- a/src/serialport/qserialport_unix_p.h +++ b/src/serialport/qserialport_unix_p.h @@ -108,8 +108,8 @@ public: bool sendBreak(int duration); bool setBreakEnabled(bool set); - qint64 systemInputQueueSize () const; - qint64 systemOutputQueueSize () const; + qint64 systemInputQueueSize (); + qint64 systemOutputQueueSize (); void startWriting(); diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 0a9aec5..fef47a0 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -266,6 +266,7 @@ QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals() if (!::DeviceIoControl(descriptor, IOCTL_SERIAL_GET_DTRRTS, NULL, 0, &modemStat, sizeof(modemStat), &bytesReturned, NULL)) { + q->setError(decodeSystemError()); return ret; } @@ -279,12 +280,26 @@ QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals() bool QSerialPortPrivate::setDataTerminalReady(bool set) { - return ::EscapeCommFunction(descriptor, set ? SETDTR : CLRDTR); + Q_Q(QSerialPort); + + if (!::EscapeCommFunction(descriptor, set ? SETDTR : CLRDTR)) { + q->setError(decodeSystemError()); + return false; + } + + return true; } bool QSerialPortPrivate::setRequestToSend(bool set) { - return ::EscapeCommFunction(descriptor, set ? SETRTS : CLRRTS); + Q_Q(QSerialPort); + + if (!::EscapeCommFunction(descriptor, set ? SETRTS : CLRRTS)) { + q->setError(decodeSystemError()); + return false; + } + + return true; } #ifndef Q_OS_WINCE @@ -296,6 +311,8 @@ bool QSerialPortPrivate::flush() bool QSerialPortPrivate::clear(QSerialPort::Directions directions) { + Q_Q(QSerialPort); + DWORD flags = 0; if (directions & QSerialPort::Input) flags |= PURGE_RXABORT | PURGE_RXCLEAR; @@ -303,25 +320,39 @@ bool QSerialPortPrivate::clear(QSerialPort::Directions directions) flags |= PURGE_TXABORT | PURGE_TXCLEAR; writeSequenceStarted = false; } - return ::PurgeComm(descriptor, flags); + if (!::PurgeComm(descriptor, flags)) { + q->setError(decodeSystemError()); + return false; + } + + return true; } #endif bool QSerialPortPrivate::sendBreak(int duration) { - // FIXME: - if (setBreakEnabled(true)) { - ::Sleep(duration); - if (setBreakEnabled(false)) - return true; - } - return false; + if (!setBreakEnabled(true)) + return false; + + ::Sleep(duration); + + if (!setBreakEnabled(false)) + return false; + + return true; } bool QSerialPortPrivate::setBreakEnabled(bool set) { - return (set ? ::SetCommBreak(descriptor) : ::ClearCommBreak(descriptor)); + Q_Q(QSerialPort); + + if (set ? !::SetCommBreak(descriptor) : !::ClearCommBreak(descriptor)) { + q->setError(decodeSystemError()); + return false; + } + + return true; } qint64 QSerialPortPrivate::systemInputQueueSize () -- cgit v1.2.1 From 1dcd4c2f7e5204ff5dc7a0d8c75ca65bbb28048b Mon Sep 17 00:00:00 2001 From: Laszlo Papp Date: Sun, 2 Feb 2014 19:22:42 +0000 Subject: Remove the unused SystemIn/OutputQueue size methods Change-Id: Iafab6ccc376da7a856b409017bbc42c36c016253 Reviewed-by: Denis Shienkov Reviewed-by: Sergey Belyashov --- src/serialport/qserialport_symbian.cpp | 11 ----------- src/serialport/qserialport_symbian_p.h | 3 --- src/serialport/qserialport_unix.cpp | 28 ---------------------------- src/serialport/qserialport_unix_p.h | 3 --- src/serialport/qserialport_win.cpp | 26 -------------------------- src/serialport/qserialport_win_p.h | 3 --- 6 files changed, 74 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport_symbian.cpp b/src/serialport/qserialport_symbian.cpp index 9318696..b904d2b 100644 --- a/src/serialport/qserialport_symbian.cpp +++ b/src/serialport/qserialport_symbian.cpp @@ -237,17 +237,6 @@ bool QSerialPortPrivate::setBreakEnabled(bool set) return false; } -qint64 QSerialPortPrivate::systemInputQueueSize () const -{ - return descriptor.QueryReceiveBuffer(); -} - -qint64 QSerialPortPrivate::systemOutputQueueSize () const -{ - // TODO: Implement me - return 0; -} - void QSerialPortPrivate::startWriting() { // TODO: Implement me diff --git a/src/serialport/qserialport_symbian_p.h b/src/serialport/qserialport_symbian_p.h index 7c3d3ef..5d95ca9 100644 --- a/src/serialport/qserialport_symbian_p.h +++ b/src/serialport/qserialport_symbian_p.h @@ -69,9 +69,6 @@ public: bool sendBreak(int duration); bool setBreakEnabled(bool set); - qint64 systemInputQueueSize () const; - qint64 systemOutputQueueSize () const; - void startWriting(); bool waitForReadyRead(int msec); diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index 0542731..a904c06 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -438,34 +438,6 @@ bool QSerialPortPrivate::setBreakEnabled(bool set) return true; } -qint64 QSerialPortPrivate::systemInputQueueSize () -{ - Q_Q(QSerialPort); - - int nbytes = 0; -#ifdef TIOCINQ - if (::ioctl(descriptor, TIOCINQ, &nbytes) == -1) { - q->setError(decodeSystemError()); - return -1; - } -#endif - return nbytes; -} - -qint64 QSerialPortPrivate::systemOutputQueueSize () -{ - Q_Q(QSerialPort); - - int nbytes = 0; -#ifdef TIOCOUTQ - if (::ioctl(descriptor, TIOCOUTQ, &nbytes) == -1) { - q->setError(decodeSystemError()); - return -1; - } -#endif - return nbytes; -} - void QSerialPortPrivate::startWriting() { if (!isWriteNotificationEnabled()) diff --git a/src/serialport/qserialport_unix_p.h b/src/serialport/qserialport_unix_p.h index c1bb685..1960316 100644 --- a/src/serialport/qserialport_unix_p.h +++ b/src/serialport/qserialport_unix_p.h @@ -108,9 +108,6 @@ public: bool sendBreak(int duration); bool setBreakEnabled(bool set); - qint64 systemInputQueueSize (); - qint64 systemOutputQueueSize (); - void startWriting(); bool waitForReadyRead(int msecs); diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index fef47a0..03775fb 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -355,32 +355,6 @@ bool QSerialPortPrivate::setBreakEnabled(bool set) return true; } -qint64 QSerialPortPrivate::systemInputQueueSize () -{ - Q_Q(QSerialPort); - - COMSTAT cs; - ::ZeroMemory(&cs, sizeof(cs)); - if (!::ClearCommError(descriptor, NULL, &cs)) { - q->setError(decodeSystemError()); - return -1; - } - return cs.cbInQue; -} - -qint64 QSerialPortPrivate::systemOutputQueueSize () -{ - Q_Q(QSerialPort); - - COMSTAT cs; - ::ZeroMemory(&cs, sizeof(cs)); - if (!::ClearCommError(descriptor, NULL, &cs)) { - q->setError(decodeSystemError()); - return -1; - } - return cs.cbOutQue; -} - #ifndef Q_OS_WINCE void QSerialPortPrivate::startWriting() diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h index 3ccdb56..12bb3f1 100644 --- a/src/serialport/qserialport_win_p.h +++ b/src/serialport/qserialport_win_p.h @@ -78,9 +78,6 @@ public: bool sendBreak(int duration); bool setBreakEnabled(bool set); - qint64 systemInputQueueSize (); - qint64 systemOutputQueueSize (); - void startWriting(); bool waitForReadyRead(int msec); -- cgit v1.2.1 From 558efaa9e7827b652a1902c96dc5a275ebd5419a Mon Sep 17 00:00:00 2001 From: Laszlo Papp Date: Sun, 2 Feb 2014 19:52:33 +0000 Subject: Rename the "descriptor" to handle on Windows * Windows uses the term handle instead of descriptor. * It is also consistent with the rest how Qt manages it. Conflicts: src/serialport/qserialport_win.cpp Change-Id: I68a672ea2d8e88e26ad5d822b157ccab79a3d2d9 Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialport_win.cpp | 56 +++++++++++++++++----------------- src/serialport/qserialport_win_p.h | 2 +- src/serialport/qserialport_wince.cpp | 54 ++++++++++++++++---------------- src/serialport/qserialportinfo_win.cpp | 12 ++++---- 4 files changed, 62 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 03775fb..4dc2fe6 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -98,7 +98,7 @@ static void initializeOverlappedStructure(OVERLAPPED &overlapped) QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q) : QSerialPortPrivateData(q) - , descriptor(INVALID_HANDLE_VALUE) + , handle(INVALID_HANDLE_VALUE) , parityErrorOccurred(false) , readChunkBuffer(ReadChunkSize, 0) , readyReadEmitted(0) @@ -151,15 +151,15 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) if (mode & QIODevice::WriteOnly) desiredAccess |= GENERIC_WRITE; - descriptor = ::CreateFile(reinterpret_cast(systemLocation.utf16()), + handle = ::CreateFile(reinterpret_cast(systemLocation.utf16()), desiredAccess, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); - if (descriptor == INVALID_HANDLE_VALUE) { + if (handle == INVALID_HANDLE_VALUE) { q->setError(decodeSystemError()); return false; } - if (!::GetCommState(descriptor, &restoredDcb)) { + if (!::GetCommState(handle, &restoredDcb)) { q->setError(decodeSystemError()); return false; } @@ -175,7 +175,7 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) if (!updateDcb()) return false; - if (!::GetCommTimeouts(descriptor, &restoredCommTimeouts)) { + if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) { q->setError(decodeSystemError()); return false; } @@ -192,7 +192,7 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) if (mode & QIODevice::WriteOnly) writeCompletionNotifier->setEnabled(true); - if (!::SetCommMask(descriptor, originalEventMask)) { + if (!::SetCommMask(handle, originalEventMask)) { q->setError(decodeSystemError()); return false; } @@ -210,7 +210,7 @@ void QSerialPortPrivate::close() { Q_Q(QSerialPort); - if (!::CancelIo(descriptor)) + if (!::CancelIo(handle)) q->setError(decodeSystemError()); readCompletionNotifier->setEnabled(false); @@ -226,16 +226,16 @@ void QSerialPortPrivate::close() parityErrorOccurred = false; if (settingsRestoredOnClose) { - if (!::SetCommState(descriptor, &restoredDcb)) + if (!::SetCommState(handle, &restoredDcb)) q->setError(decodeSystemError()); - else if (!::SetCommTimeouts(descriptor, &restoredCommTimeouts)) + else if (!::SetCommTimeouts(handle, &restoredCommTimeouts)) q->setError(decodeSystemError()); } - if (!::CloseHandle(descriptor)) + if (!::CloseHandle(handle)) q->setError(decodeSystemError()); - descriptor = INVALID_HANDLE_VALUE; + handle = INVALID_HANDLE_VALUE; } #endif // #ifndef Q_OS_WINCE @@ -246,7 +246,7 @@ QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals() DWORD modemStat = 0; - if (!::GetCommModemStatus(descriptor, &modemStat)) { + if (!::GetCommModemStatus(handle, &modemStat)) { q->setError(decodeSystemError()); return QSerialPort::NoSignal; } @@ -263,7 +263,7 @@ QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals() ret |= QSerialPort::DataCarrierDetectSignal; DWORD bytesReturned = 0; - if (!::DeviceIoControl(descriptor, IOCTL_SERIAL_GET_DTRRTS, NULL, 0, + if (!::DeviceIoControl(handle, IOCTL_SERIAL_GET_DTRRTS, NULL, 0, &modemStat, sizeof(modemStat), &bytesReturned, NULL)) { q->setError(decodeSystemError()); @@ -282,7 +282,7 @@ bool QSerialPortPrivate::setDataTerminalReady(bool set) { Q_Q(QSerialPort); - if (!::EscapeCommFunction(descriptor, set ? SETDTR : CLRDTR)) { + if (!::EscapeCommFunction(handle, set ? SETDTR : CLRDTR)) { q->setError(decodeSystemError()); return false; } @@ -294,7 +294,7 @@ bool QSerialPortPrivate::setRequestToSend(bool set) { Q_Q(QSerialPort); - if (!::EscapeCommFunction(descriptor, set ? SETRTS : CLRRTS)) { + if (!::EscapeCommFunction(handle, set ? SETRTS : CLRRTS)) { q->setError(decodeSystemError()); return false; } @@ -306,7 +306,7 @@ bool QSerialPortPrivate::setRequestToSend(bool set) bool QSerialPortPrivate::flush() { - return startAsyncWrite() && ::FlushFileBuffers(descriptor); + return startAsyncWrite() && ::FlushFileBuffers(handle); } bool QSerialPortPrivate::clear(QSerialPort::Directions directions) @@ -320,7 +320,7 @@ bool QSerialPortPrivate::clear(QSerialPort::Directions directions) flags |= PURGE_TXABORT | PURGE_TXCLEAR; writeSequenceStarted = false; } - if (!::PurgeComm(descriptor, flags)) { + if (!::PurgeComm(handle, flags)) { q->setError(decodeSystemError()); return false; } @@ -347,7 +347,7 @@ bool QSerialPortPrivate::setBreakEnabled(bool set) { Q_Q(QSerialPort); - if (set ? !::SetCommBreak(descriptor) : !::ClearCommBreak(descriptor)) { + if (set ? !::SetCommBreak(handle) : !::ClearCommBreak(handle)) { q->setError(decodeSystemError()); return false; } @@ -539,7 +539,7 @@ void QSerialPortPrivate::_q_completeAsyncCommunication() DWORD numberOfBytesTransferred = 0; - if (!::GetOverlappedResult(descriptor, &communicationOverlapped, &numberOfBytesTransferred, FALSE)) + if (!::GetOverlappedResult(handle, &communicationOverlapped, &numberOfBytesTransferred, FALSE)) q->setError(decodeSystemError()); bool error = false; @@ -570,7 +570,7 @@ void QSerialPortPrivate::_q_completeAsyncRead() Q_Q(QSerialPort); DWORD numberOfBytesTransferred = 0; - if (!::GetOverlappedResult(descriptor, &readCompletionOverlapped, &numberOfBytesTransferred, FALSE)) + if (!::GetOverlappedResult(handle, &readCompletionOverlapped, &numberOfBytesTransferred, FALSE)) q->setError(decodeSystemError()); if (numberOfBytesTransferred > 0) { @@ -593,7 +593,7 @@ void QSerialPortPrivate::_q_completeAsyncWrite() Q_Q(QSerialPort); DWORD numberOfBytesTransferred = 0; - if (!::GetOverlappedResult(descriptor, &writeCompletionOverlapped, &numberOfBytesTransferred, FALSE)) { + if (!::GetOverlappedResult(handle, &writeCompletionOverlapped, &numberOfBytesTransferred, FALSE)) { numberOfBytesTransferred = 0; q->setError(decodeSystemError()); } @@ -612,7 +612,7 @@ bool QSerialPortPrivate::startAsyncCommunication() Q_Q(QSerialPort); initializeOverlappedStructure(communicationOverlapped); - if (!::WaitCommEvent(descriptor, &triggeredEventMask, &communicationOverlapped)) { + if (!::WaitCommEvent(handle, &triggeredEventMask, &communicationOverlapped)) { const QSerialPort::SerialPortError error = decodeSystemError(); if (error != QSerialPort::NoError) { q->setError(decodeSystemError()); @@ -638,7 +638,7 @@ bool QSerialPortPrivate::startAsyncRead() } initializeOverlappedStructure(readCompletionOverlapped); - if (::ReadFile(descriptor, readChunkBuffer.data(), bytesToRead, NULL, &readCompletionOverlapped)) + if (::ReadFile(handle, readChunkBuffer.data(), bytesToRead, NULL, &readCompletionOverlapped)) return true; QSerialPort::SerialPortError error = decodeSystemError(); @@ -661,7 +661,7 @@ bool QSerialPortPrivate::startAsyncWrite() return true; initializeOverlappedStructure(writeCompletionOverlapped); - if (!::WriteFile(descriptor, writeBuffer.readPointer(), + if (!::WriteFile(handle, writeBuffer.readPointer(), writeBuffer.nextDataBlockSize(), NULL, &writeCompletionOverlapped)) { @@ -726,7 +726,7 @@ void QSerialPortPrivate::processIoErrors(bool error) } DWORD errors = 0; - if (!::ClearCommError(descriptor, &errors, NULL)) { + if (!::ClearCommError(handle, &errors, NULL)) { q->setError(decodeSystemError()); return; } @@ -749,7 +749,7 @@ bool QSerialPortPrivate::updateDcb() { Q_Q(QSerialPort); - if (!::SetCommState(descriptor, ¤tDcb)) { + if (!::SetCommState(handle, ¤tDcb)) { q->setError(decodeSystemError()); return false; } @@ -760,7 +760,7 @@ bool QSerialPortPrivate::updateCommTimeouts() { Q_Q(QSerialPort); - if (!::SetCommTimeouts(descriptor, ¤tCommTimeouts)) { + if (!::SetCommTimeouts(handle, ¤tCommTimeouts)) { q->setError(decodeSystemError()); return false; } @@ -1030,7 +1030,7 @@ QList QSerialPortPrivate::standardBaudRates() QSerialPort::Handle QSerialPort::handle() const { Q_D(const QSerialPort); - return d->descriptor; + return d->handle; } QT_END_NAMESPACE diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h index 12bb3f1..0ece047 100644 --- a/src/serialport/qserialport_win_p.h +++ b/src/serialport/qserialport_win_p.h @@ -120,7 +120,7 @@ public: DCB restoredDcb; COMMTIMEOUTS currentCommTimeouts; COMMTIMEOUTS restoredCommTimeouts; - HANDLE descriptor; + HANDLE handle; bool parityErrorOccurred; #ifndef Q_OS_WINCE diff --git a/src/serialport/qserialport_wince.cpp b/src/serialport/qserialport_wince.cpp index bb76465..0a454b4 100644 --- a/src/serialport/qserialport_wince.cpp +++ b/src/serialport/qserialport_wince.cpp @@ -62,12 +62,12 @@ public: CommEventNotifier(DWORD mask, QSerialPortPrivate *d, QObject *parent) : QThread(parent), dptr(d), running(true) { connect(this, SIGNAL(eventMask(quint32)), this, SLOT(processNotification(quint32))); - ::SetCommMask(dptr->descriptor, mask); + ::SetCommMask(dptr->handle, mask); } virtual ~CommEventNotifier() { running = false; - ::SetCommMask(dptr->descriptor, 0); + ::SetCommMask(dptr->handle, 0); wait(); } @@ -75,7 +75,7 @@ protected: void run() Q_DECL_OVERRIDE { DWORD mask = 0; while (running) { - if (::WaitCommEvent(dptr->descriptor, &mask, FALSE)) { + if (::WaitCommEvent(dptr->handle, &mask, FALSE)) { // Wait until complete the operation changes the port settings, // see updateDcb(). dptr->settingsChangeMutex.lock(); @@ -115,8 +115,8 @@ class WaitCommEventBreaker : public QThread { Q_OBJECT public: - WaitCommEventBreaker(HANDLE descriptor, int timeout, QObject *parent = 0) - : QThread(parent), descriptor(descriptor), timeout(timeout), worked(false) { + WaitCommEventBreaker(HANDLE handle, int timeout, QObject *parent = 0) + : QThread(parent), handle(handle), timeout(timeout), worked(false) { start(); } @@ -144,12 +144,12 @@ protected: private slots: void processTimeout() { - ::SetCommMask(descriptor, 0); + ::SetCommMask(handle, 0); stop(); } private: - HANDLE descriptor; + HANDLE handle; int timeout; mutable bool worked; }; @@ -158,7 +158,7 @@ private: QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q) : QSerialPortPrivateData(q) - , descriptor(INVALID_HANDLE_VALUE) + , handle(INVALID_HANDLE_VALUE) , parityErrorOccurred(false) , eventNotifier(0) { @@ -180,15 +180,15 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) eventMask |= EV_TXEMPTY; } - descriptor = ::CreateFile(reinterpret_cast(systemLocation.utf16()), + handle = ::CreateFile(reinterpret_cast(systemLocation.utf16()), desiredAccess, 0, NULL, OPEN_EXISTING, 0, NULL); - if (descriptor == INVALID_HANDLE_VALUE) { + if (handle == INVALID_HANDLE_VALUE) { q->setError(decodeSystemError()); return false; } - if (!::GetCommState(descriptor, &restoredDcb)) { + if (!::GetCommState(handle, &restoredDcb)) { q->setError(decodeSystemError()); return false; } @@ -204,7 +204,7 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) if (!updateDcb()) return false; - if (!::GetCommTimeouts(descriptor, &restoredCommTimeouts)) { + if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) { q->setError(decodeSystemError()); return false; } @@ -230,17 +230,17 @@ void QSerialPortPrivate::close() } if (settingsRestoredOnClose) { - ::SetCommState(descriptor, &restoredDcb); - ::SetCommTimeouts(descriptor, &restoredCommTimeouts); + ::SetCommState(handle, &restoredDcb); + ::SetCommTimeouts(handle, &restoredCommTimeouts); } - ::CloseHandle(descriptor); - descriptor = INVALID_HANDLE_VALUE; + ::CloseHandle(handle); + handle = INVALID_HANDLE_VALUE; } bool QSerialPortPrivate::flush() { - return notifyWrite() && ::FlushFileBuffers(descriptor); + return notifyWrite() && ::FlushFileBuffers(handle); } bool QSerialPortPrivate::clear(QSerialPort::Directions directions) @@ -250,7 +250,7 @@ bool QSerialPortPrivate::clear(QSerialPort::Directions directions) flags |= PURGE_RXABORT | PURGE_RXCLEAR; if (directions & QSerialPort::Output) flags |= PURGE_TXABORT | PURGE_TXCLEAR; - return ::PurgeComm(descriptor, flags); + return ::PurgeComm(handle, flags); } void QSerialPortPrivate::startWriting() @@ -337,7 +337,7 @@ bool QSerialPortPrivate::notifyRead() char *ptr = readBuffer.reserve(bytesToRead); DWORD readBytes = 0; - BOOL sucessResult = ::ReadFile(descriptor, ptr, bytesToRead, &readBytes, NULL); + BOOL sucessResult = ::ReadFile(handle, ptr, bytesToRead, &readBytes, NULL); if (!sucessResult) { readBuffer.truncate(bytesToRead); @@ -383,7 +383,7 @@ bool QSerialPortPrivate::notifyWrite() const char *ptr = writeBuffer.readPointer(); DWORD bytesWritten = 0; - if (!::WriteFile(descriptor, ptr, nextSize, &bytesWritten, NULL)) { + if (!::WriteFile(handle, ptr, nextSize, &bytesWritten, NULL)) { q->setError(QSerialPort::WriteError); return false; } @@ -406,8 +406,8 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor // FIXME: Here the situation is not properly handled with zero timeout: // breaker can work out before you call a method WaitCommEvent() // and so it will loop forever! - WaitCommEventBreaker breaker(descriptor, qMax(msecs, 0)); - ::WaitCommEvent(descriptor, &eventMask, NULL); + WaitCommEventBreaker breaker(handle, qMax(msecs, 0)); + ::WaitCommEvent(handle, &eventMask, NULL); breaker.stop(); if (breaker.isWorked()) { @@ -439,17 +439,17 @@ bool QSerialPortPrivate::updateDcb() DWORD eventMask = 0; // Save the event mask - if (!::GetCommMask(descriptor, &eventMask)) + if (!::GetCommMask(handle, &eventMask)) return false; // Break event notifier from WaitCommEvent - ::SetCommMask(descriptor, 0); + ::SetCommMask(handle, 0); // Change parameters - bool ret = ::SetCommState(descriptor, ¤tDcb); + bool ret = ::SetCommState(handle, ¤tDcb); if (!ret) q->setError(decodeSystemError()); // Restore the event mask - ::SetCommMask(descriptor, eventMask); + ::SetCommMask(handle, eventMask); return ret; } @@ -458,7 +458,7 @@ bool QSerialPortPrivate::updateCommTimeouts() { Q_Q(QSerialPort); - if (!::SetCommTimeouts(descriptor, ¤tCommTimeouts)) { + if (!::SetCommTimeouts(handle, ¤tCommTimeouts)) { q->setError(decodeSystemError()); return false; } diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp index 9fceb31..e6296a2 100644 --- a/src/serialport/qserialportinfo_win.cpp +++ b/src/serialport/qserialportinfo_win.cpp @@ -308,28 +308,28 @@ QList QSerialPortInfo::standardBaudRates() bool QSerialPortInfo::isBusy() const { - const HANDLE descriptor = ::CreateFile(reinterpret_cast(systemLocation().utf16()), + const HANDLE handle = ::CreateFile(reinterpret_cast(systemLocation().utf16()), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - if (descriptor == INVALID_HANDLE_VALUE) { + if (handle == INVALID_HANDLE_VALUE) { if (::GetLastError() == ERROR_ACCESS_DENIED) return true; } else { - ::CloseHandle(descriptor); + ::CloseHandle(handle); } return false; } bool QSerialPortInfo::isValid() const { - const HANDLE descriptor = ::CreateFile(reinterpret_cast(systemLocation().utf16()), + const HANDLE handle = ::CreateFile(reinterpret_cast(systemLocation().utf16()), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - if (descriptor == INVALID_HANDLE_VALUE) { + if (handle == INVALID_HANDLE_VALUE) { if (::GetLastError() != ERROR_ACCESS_DENIED) return false; } else { - ::CloseHandle(descriptor); + ::CloseHandle(handle); } return true; } -- cgit v1.2.1 From 27cb087a6af00f4bdbfcbd1a8e064b504f593f21 Mon Sep 17 00:00:00 2001 From: Laszlo Papp Date: Sat, 8 Feb 2014 07:50:51 +0000 Subject: Rename the writeSequenceStarted variable to writeStarted Conflicts: src/serialport/qserialport_win.cpp Change-Id: I786879a485e78e3637d8cb474f86e3bd406bd237 Reviewed-by: Denis Shienkov Reviewed-by: Sergey Belyashov --- src/serialport/qserialport_win.cpp | 14 +++++++------- src/serialport/qserialport_win_p.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 4dc2fe6..3bd0076 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -102,7 +102,7 @@ QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q) , parityErrorOccurred(false) , readChunkBuffer(ReadChunkSize, 0) , readyReadEmitted(0) - , writeSequenceStarted(false) + , writeStarted(false) , communicationNotifier(new QWinEventNotifier(q)) , readCompletionNotifier(new QWinEventNotifier(q)) , writeCompletionNotifier(new QWinEventNotifier(q)) @@ -219,7 +219,7 @@ void QSerialPortPrivate::close() readBuffer.clear(); - writeSequenceStarted = false; + writeStarted = false; writeBuffer.clear(); readyReadEmitted = false; @@ -318,7 +318,7 @@ bool QSerialPortPrivate::clear(QSerialPort::Directions directions) flags |= PURGE_RXABORT | PURGE_RXCLEAR; if (directions & QSerialPort::Output) { flags |= PURGE_TXABORT | PURGE_TXCLEAR; - writeSequenceStarted = false; + writeStarted = false; } if (!::PurgeComm(handle, flags)) { q->setError(decodeSystemError()); @@ -359,7 +359,7 @@ bool QSerialPortPrivate::setBreakEnabled(bool set) void QSerialPortPrivate::startWriting() { - if (!writeSequenceStarted) + if (!writeStarted) startAsyncWrite(); } @@ -603,7 +603,7 @@ void QSerialPortPrivate::_q_completeAsyncWrite() emit q->bytesWritten(numberOfBytesTransferred); } - writeSequenceStarted = false; + writeStarted = false; startAsyncWrite(); } @@ -657,7 +657,7 @@ bool QSerialPortPrivate::startAsyncWrite() { Q_Q(QSerialPort); - if (writeBuffer.isEmpty() || writeSequenceStarted) + if (writeBuffer.isEmpty() || writeStarted) return true; initializeOverlappedStructure(writeCompletionOverlapped); @@ -674,7 +674,7 @@ bool QSerialPortPrivate::startAsyncWrite() } } - writeSequenceStarted = true; + writeStarted = true; return true; } diff --git a/src/serialport/qserialport_win_p.h b/src/serialport/qserialport_win_p.h index 0ece047..ad5f267 100644 --- a/src/serialport/qserialport_win_p.h +++ b/src/serialport/qserialport_win_p.h @@ -126,7 +126,7 @@ public: #ifndef Q_OS_WINCE QByteArray readChunkBuffer; bool readyReadEmitted; - bool writeSequenceStarted; + bool writeStarted; QWinEventNotifier *communicationNotifier; QWinEventNotifier *readCompletionNotifier; QWinEventNotifier *writeCompletionNotifier; -- cgit v1.2.1 From f85c5fc1e25dd16dc625d15036d2dbc9498e8b76 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Thu, 6 Feb 2014 18:38:16 +0400 Subject: Initialize the DCB structure before using it Please refer to the MSDN documentation for details: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363214%28v=vs.85%29.aspx and http://msdn.microsoft.com/en-us/library/windows/desktop/aa363201%28v=vs.85%29.aspx Change-Id: Id60f6d1b4a9237c2ae74063ac52221f42761b004 Reviewed-by: Laszlo Papp Reviewed-by: Sergey Belyashov --- src/serialport/qserialport_win.cpp | 3 +++ src/serialport/qserialport_wince.cpp | 3 +++ 2 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 3bd0076..116206f 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -159,6 +159,9 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) return false; } + ::ZeroMemory(&restoredDcb, sizeof(restoredDcb)); + restoredDcb.DCBlength = sizeof(restoredDcb); + if (!::GetCommState(handle, &restoredDcb)) { q->setError(decodeSystemError()); return false; diff --git a/src/serialport/qserialport_wince.cpp b/src/serialport/qserialport_wince.cpp index 0a454b4..d9116cc 100644 --- a/src/serialport/qserialport_wince.cpp +++ b/src/serialport/qserialport_wince.cpp @@ -188,6 +188,9 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) return false; } + ::ZeroMemory(&restoredDcb, sizeof(restoredDcb)); + restoredDcb.DCBlength = sizeof(restoredDcb); + if (!::GetCommState(handle, &restoredDcb)) { q->setError(decodeSystemError()); return false; -- cgit v1.2.1 From a93fc13093ce6c75f23f8edcf323a1244891f14b Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Tue, 28 Jan 2014 16:22:33 +0400 Subject: Keep the DTR line state at changing of DCB properties Updating of the DCB structure (in case of setup of some properties through setXX() methods) leads to reset of a status of the DTR line to an initial state. For example, after opening of port the DTR state was "high", further the call of method setDataTerminalReady(false) will drop the DTR to "low" state. But if now to change any properties of the device (e.g. to setup a new baud rate), the DTR will again be set to "high". The reason of this behavior is the fDtrControl flag of DCB structure: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363214%28v=vs.85%29.aspx To control of DTR is used the EscapeCommFunction() function which has no relation to the DCB structure. Therefore any re-initialization of the DCB discard the results of the EscapeCommFunction() function in case a state of the fDtrControl flag not equal to the real DTR state. Solution is change of a fDtrControl flag after successfully call of the EscapeCommFunction() function. Then further change of any property will be with a correct DCB. Besides, it is necessary to drop the flag DTR_CONTROL_HANDSHAKE at opening of device. Because in this mode the manual control of the DTR line is forbidden. Thanks to Dr. Alexander W. Lenhardt Task-number: QTBUG-36490 Change-Id: I14b040761f7e28108db87e667eb76f559be436cb Reviewed-by: Sergey Belyashov Reviewed-by: Denis Shienkov --- src/serialport/qserialport_win.cpp | 4 ++++ src/serialport/qserialport_wince.cpp | 3 +++ 2 files changed, 7 insertions(+) (limited to 'src') diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp index 116206f..5641fcb 100644 --- a/src/serialport/qserialport_win.cpp +++ b/src/serialport/qserialport_win.cpp @@ -175,6 +175,9 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) currentDcb.fNull = FALSE; currentDcb.fErrorChar = FALSE; + if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE) + currentDcb.fDtrControl = DTR_CONTROL_DISABLE; + if (!updateDcb()) return false; @@ -290,6 +293,7 @@ bool QSerialPortPrivate::setDataTerminalReady(bool set) return false; } + currentDcb.fDtrControl = set ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE; return true; } diff --git a/src/serialport/qserialport_wince.cpp b/src/serialport/qserialport_wince.cpp index d9116cc..b987c80 100644 --- a/src/serialport/qserialport_wince.cpp +++ b/src/serialport/qserialport_wince.cpp @@ -204,6 +204,9 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) currentDcb.fNull = false; currentDcb.fErrorChar = false; + if (currentDcb.fDtrControl == DTR_CONTROL_HANDSHAKE) + currentDcb.fDtrControl = DTR_CONTROL_DISABLE; + if (!updateDcb()) return false; -- cgit v1.2.1 From 6ce439a6393cd857f3eb9ffeba0ad6594cf4ae63 Mon Sep 17 00:00:00 2001 From: Sebastian Wiedenroth Date: Mon, 10 Feb 2014 03:02:43 +0100 Subject: Don't use cfmakeraw on SunOS The cfmakeraw() function is an extension to POSIX and thus not fully portable. It doesn't exist on Solaris and Illumos. Source: http://www.perkin.org.uk/posts/solaris-portability-cfmakeraw.html Change-Id: Icf514fe32c01e85baff2a0d49321e45a320703b7 Reviewed-by: Laszlo Papp --- src/serialport/qserialport_unix.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index a904c06..844ba13 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -237,7 +237,15 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) } currentTermios = restoredTermios; +#ifdef Q_OS_SOLARIS + currentTermios.c_iflag &= ~(IMAXBEL|IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); + currentTermios.c_oflag &= ~OPOST; + currentTermios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + currentTermios.c_cflag &= ~(CSIZE|PARENB); + currentTermios.c_cflag |= CS8; +#else ::cfmakeraw(¤tTermios); +#endif currentTermios.c_cflag |= CLOCAL; currentTermios.c_cc[VTIME] = 0; currentTermios.c_cc[VMIN] = 0; -- cgit v1.2.1 From 691212d9e492b12590d5b7f4e2b24921911d4b17 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Feb 2014 13:14:05 -0800 Subject: Open file descriptors thread-safely on Unix and don't leak them ::open directly is not thread-safe. You need to pass O_CLOEXEC if the OS supports it. That's the only thread-safe way to open files. qt_safe_open does that for you. This patch also implicitly makes all serial devices be opened with CLOEXEC on all systems, which prevents the file descriptors from leaking to child processes. Change-Id: I83a2657fa8d9ccca1b42182bcd83416091066045 Reviewed-by: Laszlo Papp --- src/serialport/qserialport_unix.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index 844ba13..a788b4d 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -59,6 +59,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE QString serialPortLockFilePath(const QString &portName) @@ -213,7 +215,7 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode) break; } - descriptor = ::open(systemLocation.toLocal8Bit().constData(), flags); + descriptor = qt_safe_open(systemLocation.toLocal8Bit().constData(), flags); if (descriptor == -1) { q->setError(decodeSystemError()); -- cgit v1.2.1 From a8597cbae47076e33b638c2e593f852c8c0a02d5 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 11 Feb 2014 13:16:12 -0800 Subject: Protect against EINTR in Unix non-atomic I/O calls read(), write() and close() may return EINTR, indicating the system call should be restarted. The qt_safe_xxx versions of those functions do it. Change-Id: Ifef3b98131a7e24a5defea3e3af9345a505ad733 Reviewed-by: Laszlo Papp --- src/serialport/qserialport_unix.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialport_unix.cpp b/src/serialport/qserialport_unix.cpp index a788b4d..84f3109 100644 --- a/src/serialport/qserialport_unix.cpp +++ b/src/serialport/qserialport_unix.cpp @@ -306,7 +306,7 @@ void QSerialPortPrivate::close() exceptionNotifier = 0; } - if (::close(descriptor) == -1) + if (qt_safe_close(descriptor) == -1) q->setError(decodeSystemError()); if (lockFileScopedPointer->isLocked()) @@ -1078,7 +1078,7 @@ qint64 QSerialPortPrivate::readFromPort(char *data, qint64 maxSize) if (parity != QSerialPort::MarkParity && parity != QSerialPort::SpaceParity) { #endif - bytesRead = ::read(descriptor, data, maxSize); + bytesRead = qt_safe_read(descriptor, data, maxSize); } else {// Perform parity emulation. bytesRead = readPerChar(data, maxSize); } @@ -1090,11 +1090,11 @@ qint64 QSerialPortPrivate::writeToPort(const char *data, qint64 maxSize) { qint64 bytesWritten = 0; #if defined (CMSPAR) - bytesWritten = ::write(descriptor, data, maxSize); + bytesWritten = qt_safe_write(descriptor, data, maxSize); #else if (parity != QSerialPort::MarkParity && parity != QSerialPort::SpaceParity) { - bytesWritten = ::write(descriptor, data, maxSize); + bytesWritten = qt_safe_write(descriptor, data, maxSize); } else {// Perform parity emulation. bytesWritten = writePerChar(data, maxSize); } @@ -1131,7 +1131,7 @@ qint64 QSerialPortPrivate::writePerChar(const char *data, qint64 maxSize) break; } - int r = ::write(descriptor, data, 1); + int r = qt_safe_write(descriptor, data, 1); if (r < 0) return -1; if (r > 0) { @@ -1157,7 +1157,7 @@ qint64 QSerialPortPrivate::readPerChar(char *data, qint64 maxSize) int prefix = 0; while (ret < maxSize) { - qint64 r = ::read(descriptor, data, 1); + qint64 r = qt_safe_read(descriptor, data, 1); if (r < 0) { if (errno == EAGAIN) // It is ok for nonblocking mode. break; -- cgit v1.2.1 From 65dd36db940bd9b0c1806f66c54bb672b08eb9b8 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Mon, 27 Jan 2014 15:49:35 +0400 Subject: Use QString for device properties The device registry property of the SPDRP_HARDWAREID is not used any more. This property was used earlier for parsing of the VID/PID and had the type of the REG_MULTI_SZ which was interpreted as QStringList, see commit: d8dc10efb1714dcfafa6a08e107fd31fc1e3ce0e The current code is using only string based concept, hence changing the interface to QString. Tested on Windows 8 with on-board and virtual com0com serial ports using the cenumerator example. Change-Id: I31e4f85f1b145021c1b34b81ba890553604a0531 Reviewed-by: Laszlo Papp Reviewed-by: Sergey Belyashov --- src/serialport/qserialportinfo_win.cpp | 65 ++++++++++++---------------------- 1 file changed, 22 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/serialport/qserialportinfo_win.cpp b/src/serialport/qserialportinfo_win.cpp index e6296a2..85d40cc 100644 --- a/src/serialport/qserialportinfo_win.cpp +++ b/src/serialport/qserialportinfo_win.cpp @@ -46,15 +46,14 @@ #include "qserialport_win_p.h" #ifndef Q_OS_WINCE +#include +#include +#include + #include #include #endif -#include -#include -#include -#include - QT_BEGIN_NAMESPACE #ifndef Q_OS_WINCE @@ -104,47 +103,27 @@ static QStringList portNamesFromHardwareDeviceMap() return result; } -static QVariant deviceRegistryProperty(HDEVINFO deviceInfoSet, - PSP_DEVINFO_DATA deviceInfoData, - DWORD property) +static QString deviceRegistryProperty(HDEVINFO deviceInfoSet, + PSP_DEVINFO_DATA deviceInfoData, + DWORD property) { DWORD dataType = 0; - DWORD dataSize = 0; - ::SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, - property, &dataType, NULL, 0, &dataSize); - QByteArray data(dataSize, 0); - if (!::SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, NULL, - reinterpret_cast(data.data()), - dataSize, NULL) - || !dataSize) { - return QVariant(); - } - - switch (dataType) { - - case REG_EXPAND_SZ: - case REG_SZ: { - return QVariant(QString::fromWCharArray(reinterpret_cast(data.constData()))); - } - - case REG_MULTI_SZ: { - QStringList list; - int i = 0; - forever { - QString s = QString::fromWCharArray(reinterpret_cast(data.constData()) + i); - i += s.length() + 1; - if (s.isEmpty()) - break; - list.append(s); + QByteArray devicePropertyByteArray; + DWORD requiredSize = 0; + forever { + if (::SetupDiGetDeviceRegistryProperty(deviceInfoSet, deviceInfoData, property, &dataType, + reinterpret_cast(devicePropertyByteArray.data()), + devicePropertyByteArray.size(), &requiredSize)) { + break; } - return QVariant(list); - } - default: - break; + if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER + || (dataType != REG_SZ && dataType != REG_EXPAND_SZ)) { + return QString(); + } + devicePropertyByteArray.resize(requiredSize); } - - return QVariant(); + return QString::fromWCharArray(reinterpret_cast(devicePropertyByteArray.constData())); } static QString deviceInstanceIdentifier(HDEVINFO deviceInfoSet, @@ -253,9 +232,9 @@ QList QSerialPortInfo::availablePorts() serialPortInfo.d_ptr->portName = s; serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(s); serialPortInfo.d_ptr->description = - deviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_DEVICEDESC).toString(); + deviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_DEVICEDESC); serialPortInfo.d_ptr->manufacturer = - deviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_MFG).toString(); + deviceRegistryProperty(deviceInfoSet, &deviceInfoData, SPDRP_MFG); s = deviceInstanceIdentifier(deviceInfoSet, &deviceInfoData).toUpper(); -- cgit v1.2.1