summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2014-06-07 15:18:15 +0400
committerDenis Shienkov <denis.shienkov@gmail.com>2014-06-29 19:47:53 +0200
commitaee836176ff4bf60f6823a9defccee7f49b92a5b (patch)
treecfa98c10870b0ccaaa4589ca072b905ef9c24bd5
parent38f564f7255330710defcf839f4cd04e1ccfc417 (diff)
downloadqtserialport-aee836176ff4bf60f6823a9defccee7f49b92a5b.tar.gz
Improve the ResourceError handling on Windows
To the ResourceError handling we generally relied on triggering of the _q_completeAsyncCommunication(), in case of ejection of an USB device from a host. But it worked with not all USB devices (for example it did not work with the ZTE modems). Even when this worked (for example with the PL2303 devices), then we got the non informative "Unknown error" of the ResourceError string representation. It is more reasonable not to do any custom checks of an event mask when triggered of the _q_completeAsyncCommunication() method. We need allow to detect an errors with means of the ReadFile/GetOverlappedResult/WaitCommEvent syscalls on an invalid device handle. An important note is that returns the different error codes for a different types of devices. For example: * For the USB ZTE and the Samsung Android USB modem returns the ERROR_ACCESS_DENIED error code. * For the FTDI and the Samsung Android Diagnostic Serial Port returns the ERROR_OPERATION_ABORTED error code. * For the USB PL2303 device returns the ERROR_BAD_COMMAND error code. Thus, there is no universal solution of this issue. Each vendor of the driver implements it own way. Therefore for each new type of the device it is necessary to add processing its error code, if we have no it yet. Tested on Windows 7/8 with the USB ZTE and the Android modems, with the USB PL2303 and the FTDI devices and with the Android diagnostic serial port using Qt4 and then Qt5, no regressions found. Task-number: QTBUG-32020 Change-Id: I61c02078ee98221ecef18a27cde3d9bae3674d70 Reviewed-by: Denis Shienkov <denis.shienkov@gmail.com>
-rw-r--r--src/serialport/qserialport_win.cpp30
1 files changed, 9 insertions, 21 deletions
diff --git a/src/serialport/qserialport_win.cpp b/src/serialport/qserialport_win.cpp
index 981ec2e..e9792be 100644
--- a/src/serialport/qserialport_win.cpp
+++ b/src/serialport/qserialport_win.cpp
@@ -575,29 +575,10 @@ void QSerialPortPrivate::_q_completeAsyncCommunication()
}
}
- bool error = false;
-
- // Check for unexpected event. This event triggered when pulled previously
- // opened device from the system, when opened as for not to read and not to
- // write options and so forth.
- if (triggeredEventMask == 0)
- error = true;
-
- // Workaround for standard CDC ACM serial ports, for which triggered an
- // unexpected event EV_TXEMPTY at data transmission.
- if ((originalEventMask & triggeredEventMask) == 0) {
- if ((triggeredEventMask & EV_TXEMPTY) == 0)
- error = true;
- }
-
- if (error)
- q->setError(QSerialPort::ResourceError);
-
if (EV_ERR & triggeredEventMask)
handleLineStatusErrors();
- if (!error)
- startAsyncRead();
+ startAsyncRead();
}
void QSerialPortPrivate::_q_completeAsyncRead()
@@ -663,8 +644,10 @@ bool QSerialPortPrivate::startAsyncCommunication()
initializeOverlappedStructure(communicationOverlapped);
if (!::WaitCommEvent(handle, &triggeredEventMask, &communicationOverlapped)) {
- const QSerialPort::SerialPortError error = decodeSystemError();
+ QSerialPort::SerialPortError error = decodeSystemError();
if (error != QSerialPort::NoError) {
+ if (error == QSerialPort::PermissionError)
+ error = QSerialPort::ResourceError;
q->setError(error);
return false;
}
@@ -693,6 +676,8 @@ bool QSerialPortPrivate::startAsyncRead()
QSerialPort::SerialPortError error = decodeSystemError();
if (error != QSerialPort::NoError) {
+ if (error == QSerialPort::PermissionError)
+ error = QSerialPort::ResourceError;
if (error != QSerialPort::ResourceError)
error = QSerialPort::ReadError;
q->setError(error);
@@ -838,6 +823,9 @@ QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
case ERROR_DEVICE_REMOVED:
error = QSerialPort::ResourceError;
break;
+ case ERROR_OPERATION_ABORTED:
+ error = QSerialPort::ResourceError;
+ break;
default:
error = QSerialPort::UnknownError;
break;