示例#1
0
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;
}
示例#2
0
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;
}