Example #1
0
bool StandardSerialPortBackend::writeDataFrame(const QByteArray &data)
{
//    qDebug() << "!d" << tr("DBG -- Serial Port writeDataFrame...");

    QByteArray copy(data);
    copy.resize(copy.size() + 1);
    copy[copy.size() - 1] = sioChecksum(copy, copy.size() - 1);
    SioWorker::usleep(50);
    return writeRawFrame(copy);
}
Example #2
0
QByteArray StandardSerialPortBackend::readDataFrame(uint size, bool verbose)
{
//    qDebug() << "!d" << tr("DBG -- Serial Port readDataFrame...");

    QByteArray data = readRawFrame(size + 1, verbose);
    if (data.isEmpty()) {
        return data;
    }
    quint8 expected = (quint8)data.at(size);
    quint8 got = sioChecksum(data, size);
    if (expected == got) {
        data.resize(size);
        return data;
    } else {
        if (verbose) {
            qWarning() << "!w" << tr("Data frame checksum error, expected: %1, got: %2. (%3)")
                           .arg(expected)
                           .arg(got)
                           .arg(QString(data.toHex()));
        }
        data.clear();
        return data;
    }
}
Example #3
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;
}