QByteArray StandardSerialPortBackend::readCommandFrame() { // qDebug() << "!d" << tr("DBG -- Serial Port readCommandFrame..."); QByteArray data; DWORD mask; switch (mMethod) { case 0: mask = EV_RING; break; case 1: mask = EV_DSR; break; case 2: mask = EV_CTS; break; case 3: mask = EV_RXCHAR; } if (!SetCommMask(mHandle, mask)) { qCritical() << "!e" << tr("Cannot set serial port event mask: %1").arg(lastErrorMessage()); return data; } int retries = 0, totalRetries = 0; do { data.clear(); OVERLAPPED ov; memset(&ov, 0, sizeof(ov)); ov.hEvent = CreateEvent(0, true, false, 0); HANDLE events[2]; events[0] = ov.hEvent; events[1] = mCancelHandle; if (!WaitCommEvent(mHandle, &mask, &ov)) { if (GetLastError() == ERROR_IO_PENDING) { DWORD x = WaitForMultipleObjects(2, events, false, INFINITE); CloseHandle(ov.hEvent); if (x == WAIT_OBJECT_0 + 1) { data.clear(); return data; } if (x == WAIT_FAILED) { qCritical() << "!e" << tr("Cannot wait for serial port event: %1").arg(lastErrorMessage()); data.clear(); return data; } } else { CloseHandle(ov.hEvent); qCritical() << "!e" << tr("Cannot wait for serial port event: %1").arg(lastErrorMessage()); return data; } } if (!PurgeComm(mHandle, PURGE_RXCLEAR)) { qCritical() << "!e" << tr("Cannot clear serial port read buffer: %1").arg(lastErrorMessage()); return data; } // qDebug() << "!d" << tr("DBG -- Serial Port, just about to readDataFrame..."); data = readDataFrame(4, false); if (!data.isEmpty()) { // qDebug() << "!d" << tr("DBG -- Serial Port, data not empty: [%1]").arg(data.data()); if(mask != EV_RXCHAR) { // do { GetCommModemStatus(mHandle, &mask); } while (mask && !mCanceled); } break; } else { retries++; totalRetries++; if (retries == 2) { retries = 0; if (mHighSpeed) { setNormalSpeed(); } else { setHighSpeed(); } } } // } while (totalRetries < 100); } while (1); return data; }
QByteArray StandardSerialPortBackend::readCommandFrame() { // qDebug() << "!d" << tr("DBG -- Serial Port readCommandFrame..."); QByteArray data; if(mMethod==HANDSHAKE_SOFTWARE) { if (!PurgeComm(mHandle, PURGE_RXCLEAR)) { qCritical() << "!e" << tr("Cannot clear serial port read buffer: %1").arg(lastErrorMessage()); return data; } const int size = 4; quint8 expected = 0; quint8 got = 1; do { DWORD result; char c; if(ReadFile(mHandle, &c, 1, &result, NULL) && result == 1) { data.append(c); if(data.size()==size+2) { data.remove(0,1); } if(data.size()==size+1) { for(int i=0 ; i<mSioDevices.size() ; i++) { if(data.at(0)==mSioDevices[i]) { expected = (quint8)data.at(size); got = sioChecksum(data, size); break; } } } } } while(got!=expected && !mCanceled); if(got==expected) { data.resize(size); // After sending the last byte of the command frame // ATARI does not drop the command line immediately. // Within this small time window ATARI is not able to process the ACK byte. // For the "software handshake" approach, we need to wait here a little bit. QThread::usleep(500); } else { data.clear(); } } else { DWORD MASK; DWORD MODEM_STAT; DWORD tmp; switch (mMethod) { case HANDSHAKE_RI: MASK = EV_RING; MODEM_STAT = MS_RING_ON; break; case HANDSHAKE_DSR: MASK = EV_DSR; MODEM_STAT = MS_DSR_ON; break; case HANDSHAKE_CTS: MASK = EV_CTS; MODEM_STAT = MS_CTS_ON; break; case HANDSHAKE_NO_HANDSHAKE: default: MASK = EV_RXCHAR; MODEM_STAT = 0; break; } if (!SetCommMask(mHandle, MASK)) { qCritical() << "!e" << tr("Cannot set serial port event mask: %1").arg(lastErrorMessage()); return data; } int retries = 0, totalRetries = 0; do { data.clear(); OVERLAPPED ov; memset(&ov, 0, sizeof(ov)); ov.hEvent = CreateEvent(0, true, false, 0); HANDLE events[2]; events[0] = ov.hEvent; events[1] = mCancelHandle; if (!WaitCommEvent(mHandle, &tmp, &ov)) { if (GetLastError() == ERROR_IO_PENDING) { DWORD x = WaitForMultipleObjects(2, events, false, INFINITE); CloseHandle(ov.hEvent); if (x == WAIT_OBJECT_0 + 1) { data.clear(); return data; } if (x == WAIT_FAILED) { qCritical() << "!e" << tr("Cannot wait for serial port event: %1").arg(lastErrorMessage()); data.clear(); return data; } } else { CloseHandle(ov.hEvent); qCritical() << "!e" << tr("Cannot wait for serial port event: %1").arg(lastErrorMessage()); return data; } } // for hardware handshake methods check if the command line status is ON if( (MODEM_STAT != 0) && (!GetCommModemStatus(mHandle, &tmp) || !(tmp & MODEM_STAT)) )continue; if(MASK != EV_RXCHAR) { if (!PurgeComm(mHandle, PURGE_RXCLEAR)) { qCritical() << "!e" << tr("Cannot clear serial port read buffer: %1").arg(lastErrorMessage()); return data; } } // qDebug() << "!d" << tr("DBG -- Serial Port, just about to readDataFrame..."); data = readDataFrame(4, false); if (!data.isEmpty()) { // qDebug() << "!d" << tr("DBG -- Serial Port, data not empty: [%1]").arg(data.data()); if(MASK != EV_RXCHAR) { // do { GetCommModemStatus(mHandle, &tmp); } while ((tmp & MODEM_STAT) && !mCanceled); } else { // After sending the last byte of the command frame // ATARI does not drop the command line immediately. // Within this small time window ATARI is not able to process the ACK byte. // For the "software handshake" approach, we need to wait here a little bit. QThread::usleep(500); } break; } else { retries++; totalRetries++; if (retries == 2) { retries = 0; if (mHighSpeed) { setNormalSpeed(); } else { setHighSpeed(); } } } // } while (totalRetries < 100); } while (1); } return data; }