QSerialPort open error code 10
-
This is my last test for today....
- I run the terminal example under Linux (it's works fine)
- Restart the computer without unplug or switch off the board
- Run hte new code to get the com state (GetCommState). Thanks @Christian-Ehrlicher
- Print screen
- Call SetCommState with these parameters... works under Windows.
- Power off the board
- Power on the board
- Run again my demo and get the com state as before.
- Apart the usual settings like 9600 8 N 1.... I see that Linux set the port with the RTS Control Enable, and now is not set !!
- So, I add this line of code
dcb.fRtsControl = RTS_CONTROL_ENABLE;
- Run again the demo without success....
setCommState error: 87 "Parameter is not correct."
This is the used code:
DWORD desiredAccess = GENERIC_READ | GENERIC_WRITE; HANDLE handle = ::CreateFile(reinterpret_cast<const wchar_t *>(L"COM5"), desiredAccess, 0, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr); if (handle == INVALID_HANDLE_VALUE) { // OOPS const DWORD error = ::GetLastError(); qDebug() << "ERROR:" << error; } DCB dcb; int systemErrorCode = 0; // -------------------------------------------------- // bool QSerialPortPrivate::getDcb(DCB *dcb) ::ZeroMemory(&dcb, sizeof(DCB)); dcb.DCBlength = sizeof(DCB); if (!::GetCommState(handle, &dcb)) { systemErrorCode = ::GetLastError(); qDebug() << "GetCommState error:" << systemErrorCode << qt_error_string(systemErrorCode); return; } // -------------------------------------------------- // 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; if (dcb.fRtsControl != RTS_CONTROL_HANDSHAKE) dcb.fRtsControl = RTS_CONTROL_DISABLE; // -------------------------------------------------- // baud rate dcb.BaudRate = QSerialPort::Baud9600; /* if (!::SetCommState(handle, &dcb)) { systemErrorCode = ::GetLastError(); qDebug() << "BaudRate: setCommState error:" << systemErrorCode << qt_error_string(systemErrorCode); ::CloseHandle(handle); return; } */ // -------------------------------------------------- // byte size dcb.ByteSize = QSerialPort::Data8; /* if (!::SetCommState(handle, &dcb)) { systemErrorCode = ::GetLastError(); qDebug() << "ByteSize: setCommState error:" << systemErrorCode << qt_error_string(systemErrorCode); ::CloseHandle(handle); return; } */ // -------------------------------------------------- // parity dcb.Parity = NOPARITY; dcb.fParity = FALSE; /* if (!::SetCommState(handle, &dcb)) { systemErrorCode = ::GetLastError(); qDebug() << "Parity: setCommState error:" << systemErrorCode << qt_error_string(systemErrorCode); ::CloseHandle(handle); return; } */ // -------------------------------------------------- // stopbit dcb.StopBits = ONESTOPBIT; /* if (!::SetCommState(handle, &dcb)) { systemErrorCode = ::GetLastError(); qDebug() << "StopBit: setCommState error:" << systemErrorCode << qt_error_string(systemErrorCode); ::CloseHandle(handle); return; } */ // -------------------------------------------------- // flow control dcb.fInX = FALSE; dcb.fOutX = FALSE; dcb.fOutxCtsFlow = FALSE; if (dcb.fRtsControl == RTS_CONTROL_HANDSHAKE) 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; // } dcb.fRtsControl = RTS_CONTROL_ENABLE; if (!::SetCommState(handle, &dcb)) { systemErrorCode = ::GetLastError(); qDebug() << "setCommState error:" << systemErrorCode << qt_error_string(systemErrorCode); ::CloseHandle(handle); return; }
-
If this does not work when you did:
... if (!::GetCommState(handle, &dcb)) { systemErrorCode = ::GetLastError(); qDebug() << "GetCommState error:" << systemErrorCode << qt_error_string(systemErrorCode); return; } ...
and then immediatelly:
... if (!::SetCommState(handle, &dcb)) { systemErrorCode = ::GetLastError(); qDebug() << "SetCommState error:" << systemErrorCode << qt_error_string(systemErrorCode); return; } ...
then it is LOL.
Then you can install the serial port sniffer application and to sniff the device I/O control call for the SetCommStat. To see, which parameters are passed with this call e.g using the
hercules
application, and to compare with theqtserialport
.Most likelly, it is a bug in FW of your device (in USB CDC class implementation). Or, maybe it expect some specific DCB structure (some specific DCB flags).
Question: Do you have the specific serial port driver for your device, or do you use the 'standard'
usbser.sys
driver from Windows?PS: On Linux there are different drivers implementation.
-
@kuzulis said in QSerialPort open error code 10:
then it is LOL.
Correct, that was the reason why I asked him to try it out to see if it's a driver problem :)
-
@Christian-Ehrlicher said in QSerialPort open error code 10:
I asked him to try it out to see if it's a driver problem :)
Most likelly, it is a problem in device FW, not in driver (because I assume that there are used the CDC ACM driver). :)
-
@kuzulis said in QSerialPort open error code 10:
If this does not work when you did:
...
if (!::GetCommState(handle, &dcb))
{
systemErrorCode = ::GetLastError();
qDebug() << "GetCommState error:" << systemErrorCode << qt_error_string(systemErrorCode);
return;
}
...and then immediatelly:
...
if (!::SetCommState(handle, &dcb))
{
systemErrorCode = ::GetLastError();
qDebug() << "SetCommState error:" << systemErrorCode << qt_error_string(systemErrorCode);
return;
}
...Doesn't work. Look tha values on the right side... ?!?
Then you can install the serial port sniffer application and to sniff the device I/O control call for the SetCommStat. To see, which parameters are passed with this call e.g using the hercules application, and to compare with the qtserialport.
Do you know some good sniffer program that you have already used?
Most likelly, it is a bug in FW of your device (in USB CDC class implementation). Or, maybe it expect some specific DCB structure (some specific DCB flags).
Question: Do you have the specific serial port driver for your device, or do you use the 'standard' usbser.sys driver from Windows?No, I'm using the standard windows usbser.sys
-
Maybe you can check if the dcb contains a difference when it works (so when it was first started on linux) and when not. Don't know if it helps though.
-
@Christian-Ehrlicher Thanks but I've already done when, in my previuos post I wrote "This is my last test for today...."
-
Even though I haven't solved it I'd like to give you a big thank you.
@Christian-Ehrlicher
@J-Hilk
@KroMignon
@kuzulis
@ollarch
@Pablo-J-RoginaI'll try to contact the board supplier to investigate if there was some fw changes.
-
@addebito Sorry, overread it :)
But I think you have enough to ask the supplier for help since it can be simply reproduced with plain WinAPI calls :)
-
@Christian-Ehrlicher Yes you are right !! ....after 2 days of testing!
-
@addebito , I have an issue more or less the same as you.
I suppose the main issue comes from one program that has opened the serial port and initialed any DCB parameters, when your Qt program opens the device, Qt driver does not reset all DCB data, but some parameters did not suitable for QtSerialPort, so the issue comes up.
here is a DCB that first open after the PC reset:
here is a DCB being opened by another program, it changed XoffLim/XonLim
so, I write some code clear DCB before Qt open serial port:
#if (defined (_WIN32) || defined (_WIN64)) void clearSerialPort (const QString &path) { #include <winbase.h> QString deviceString = path.startsWith(QLatin1String("COM")) ? (QLatin1String("\\\\.\\") + path) : path; HANDLE handle = ::CreateFile( reinterpret_cast<const wchar_t*>(deviceString.utf16()), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr); if (handle == INVALID_HANDLE_VALUE) { return; } DCB dcb; memset(&dcb, 0, sizeof(DCB)); //::ZeroMemory(dcb, sizeof(dcb)); dcb.DCBlength = sizeof(DCB); if (::GetCommState(handle, &dcb)) { dcb.XoffLim = 0; dcb.XonLim = 0; ::SetCommState(handle, &dcb); } ::CloseHandle(handle); } #endif