Beispiel #1
0
void QSerialPortPrivate::close()
{
    Q_Q(QSerialPort);

    if (!::CancelIo(handle))
        q->setError(decodeSystemError());

    readCompletionNotifier->setEnabled(false);
    writeCompletionNotifier->setEnabled(false);
    communicationNotifier->setEnabled(false);

    readBuffer.clear();

    writeStarted = false;
    writeBuffer.clear();

    readyReadEmitted = false;
    parityErrorOccurred = false;

    if (settingsRestoredOnClose) {
        if (!::SetCommState(handle, &restoredDcb))
            q->setError(decodeSystemError());
        else if (!::SetCommTimeouts(handle, &restoredCommTimeouts))
            q->setError(decodeSystemError());
    }

    if (!::CloseHandle(handle))
        q->setError(decodeSystemError());

    handle = INVALID_HANDLE_VALUE;
}
Beispiel #2
0
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{
    Q_Q(QSerialPort);

    // FIXME: Maybe need added check an ReadWrite open mode?
    Q_UNUSED(mode)

    if (!loadDevices()) {
        q->setError(QSerialPort::UnknownError);
        return false;
    }

    RCommServ server;
    errnum = server.Connect();
    if (errnum != KErrNone) {
        q->setError(decodeSystemError());
        return false;
    }

    if (systemLocation.contains("BTCOMM"))
        errnum = server.LoadCommModule(KBluetoothModuleName);
    else if (systemLocation.contains("IRCOMM"))
        errnum = server.LoadCommModule(KInfraRedModuleName);
    else if (systemLocation.contains("ACM"))
        errnum = server.LoadCommModule(KACMModuleName);
    else
        errnum = server.LoadCommModule(KRS232ModuleName);

    if (errnum != KErrNone) {
        q->setError(decodeSystemError());
        return false;
    }

    // In Symbian OS port opening only in R/W mode?
    TPtrC portName(static_cast<const TUint16*>(systemLocation.utf16()), systemLocation.length());
    errnum = descriptor.Open(server, portName, ECommExclusive);

    if (errnum != KErrNone) {
        q->setError(decodeSystemError());
        return false;
    }

    // Save current port settings.
    errnum = descriptor.Config(restoredSettings);
    if (errnum != KErrNone) {
        q->setError(decodeSystemError());
        return false;
    }

    detectDefaultSettings();
    return true;
}
Beispiel #3
0
bool QSerialPortPrivate::startAsyncCommunication()
{
    Q_Q(QSerialPort);

    initializeOverlappedStructure(communicationOverlapped);
    if (!::WaitCommEvent(handle, &triggeredEventMask, &communicationOverlapped)) {
        const QSerialPort::SerialPortError error = decodeSystemError();
        if (error != QSerialPort::NoError) {
            q->setError(decodeSystemError());
            return false;
        }
    }
    return true;
}
Beispiel #4
0
bool QSerialPortPrivate::waitForBytesWritten(int msecs)
{
    Q_Q(QSerialPort);

    if (writeBuffer.isEmpty())
        return false;

    QElapsedTimer stopWatch;
    stopWatch.start();

    forever {
        bool timedOut = false;
        HANDLE triggeredEvent = 0;

        if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &timedOut, &triggeredEvent) || !triggeredEvent) {
            if (!timedOut)
                q->setError(decodeSystemError());
            return false;
        }

        if (triggeredEvent == communicationOverlapped.hEvent) {
             _q_completeAsyncRead();
        } else if (triggeredEvent == readCompletionOverlapped.hEvent) {
            _q_completeAsyncRead();
        } else if (triggeredEvent == writeCompletionOverlapped.hEvent) {
            _q_completeAsyncWrite();
            return error == QSerialPort::NoError;
        } else {
            return false;
        }

    }

    return false;
}
bool QSerialPortPrivate::writeDataOneShot()
{
    Q_Q(QSerialPort);

    pendingBytesWritten = -1;

    while (!writeBuffer.isEmpty())
    {
        pendingBytesWritten = writeToPort(writeBuffer.readPointer(), writeBuffer.nextDataBlockSize());

        if (pendingBytesWritten <= 0)
        {
            QSerialPort::SerialPortError errorL = decodeSystemError();
            if (errorL != QSerialPort::ResourceError)
                errorL = QSerialPort::WriteError;
            q->setError(errorL);
            return false;
        }

        writeBuffer.free(pendingBytesWritten);

        emit q->bytesWritten(pendingBytesWritten);
    }

    return (pendingBytesWritten < 0)? false: true;
}
Beispiel #6
0
void QSerialPortPrivate::processIoErrors(bool error)
{
    Q_Q(QSerialPort);

    if (error) {
        q->setError(QSerialPort::ResourceError);
        return;
    }

    DWORD errors = 0;
    if (!::ClearCommError(handle, &errors, NULL)) {
        q->setError(decodeSystemError());
        return;
    }

    if (errors & CE_FRAME) {
        q->setError(QSerialPort::FramingError);
    } else if (errors & CE_RXPARITY) {
        q->setError(QSerialPort::ParityError);
        parityErrorOccurred = true;
    } else if (errors & CE_BREAK) {
        q->setError(QSerialPort::BreakConditionError);
    } else {
        q->setError(QSerialPort::UnknownError);
    }
}
Beispiel #7
0
bool QSerialPortPrivate::startAsyncRead()
{
    Q_Q(QSerialPort);

    DWORD bytesToRead = policy == QSerialPort::IgnorePolicy ? ReadChunkSize : 1;

    if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) {
        bytesToRead = readBufferMaxSize - readBuffer.size();
        if (bytesToRead == 0) {
            // Buffer is full. User must read data from the buffer
            // before we can read more from the port.
            return false;
        }
    }

    initializeOverlappedStructure(readCompletionOverlapped);
    if (::ReadFile(handle, readChunkBuffer.data(), bytesToRead, NULL, &readCompletionOverlapped))
        return true;

    QSerialPort::SerialPortError error = decodeSystemError();
    if (error != QSerialPort::NoError) {
        if (error != QSerialPort::ResourceError)
            error = QSerialPort::ReadError;
        q->setError(error);

        return false;
    }

    return true;
}
Beispiel #8
0
bool QSerialPortPrivate::updateCommTimeouts()
{
    Q_Q(QSerialPort);

    if (!::SetCommTimeouts(handle, &currentCommTimeouts)) {
        q->setError(decodeSystemError());
        return false;
    }
    return true;
}
Beispiel #9
0
bool QSerialPortPrivate::updateDcb()
{
    Q_Q(QSerialPort);

    if (!::SetCommState(handle, &currentDcb)) {
        q->setError(decodeSystemError());
        return false;
    }
    return true;
}
Beispiel #10
0
bool QSerialPortPrivate::setBreakEnabled(bool set)
{
    Q_Q(QSerialPort);

    if (set ? !::SetCommBreak(handle) : !::ClearCommBreak(handle)) {
        q->setError(decodeSystemError());
        return false;
    }

    return true;
}
Beispiel #11
0
bool QSerialPortPrivate::setRequestToSend(bool set)
{
    Q_Q(QSerialPort);

    if (!::EscapeCommFunction(handle, set ? SETRTS : CLRRTS)) {
        q->setError(decodeSystemError());
        return false;
    }

    return true;
}
Beispiel #12
0
bool QSerialPortPrivate::setDataTerminalReady(bool set)
{
    Q_Q(QSerialPort);

    if (!::EscapeCommFunction(handle, set ? SETDTR : CLRDTR)) {
        q->setError(decodeSystemError());
        return false;
    }

    currentDcb.fDtrControl = set ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE;
    return true;
}
Beispiel #13
0
QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
    : QSerialPortPrivateData(q)
    , handle(INVALID_HANDLE_VALUE)
    , parityErrorOccurred(false)
    , readChunkBuffer(ReadChunkSize, 0)
    , readyReadEmitted(0)
    , writeStarted(false)
    , communicationNotifier(new QWinEventNotifier(q))
    , readCompletionNotifier(new QWinEventNotifier(q))
    , writeCompletionNotifier(new QWinEventNotifier(q))
    , originalEventMask(0)
    , triggeredEventMask(0)
{
    ::ZeroMemory(&communicationOverlapped, sizeof(communicationOverlapped));
    communicationOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!communicationOverlapped.hEvent)
        q->setError(decodeSystemError());
    else {
        communicationNotifier->setHandle(communicationOverlapped.hEvent);
        q->connect(communicationNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_completeAsyncCommunication()));
    }

    ::ZeroMemory(&readCompletionOverlapped, sizeof(readCompletionOverlapped));
    readCompletionOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!readCompletionOverlapped.hEvent)
        q->setError(decodeSystemError());
    else {
        readCompletionNotifier->setHandle(readCompletionOverlapped.hEvent);
        q->connect(readCompletionNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_completeAsyncRead()));
    }

    ::ZeroMemory(&writeCompletionOverlapped, sizeof(writeCompletionOverlapped));
    writeCompletionOverlapped.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!writeCompletionOverlapped.hEvent)
        q->setError(decodeSystemError());
    else {
        writeCompletionNotifier->setHandle(writeCompletionOverlapped.hEvent);
        q->connect(writeCompletionNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_completeAsyncWrite()));
    }
}
Beispiel #14
0
QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals()
{
    Q_Q(QSerialPort);

    DWORD modemStat = 0;

    if (!::GetCommModemStatus(handle, &modemStat)) {
        q->setError(decodeSystemError());
        return QSerialPort::NoSignal;
    }

    QSerialPort::PinoutSignals ret = QSerialPort::NoSignal;

    if (modemStat & MS_CTS_ON)
        ret |= QSerialPort::ClearToSendSignal;
    if (modemStat & MS_DSR_ON)
        ret |= QSerialPort::DataSetReadySignal;
    if (modemStat & MS_RING_ON)
        ret |= QSerialPort::RingIndicatorSignal;
    if (modemStat & MS_RLSD_ON)
        ret |= QSerialPort::DataCarrierDetectSignal;

    DWORD bytesReturned = 0;
    if (!::DeviceIoControl(handle, IOCTL_SERIAL_GET_DTRRTS, NULL, 0,
                          &modemStat, sizeof(modemStat),
                          &bytesReturned, NULL)) {
        q->setError(decodeSystemError());
        return ret;
    }

    if (modemStat & SERIAL_DTR_STATE)
        ret |= QSerialPort::DataTerminalReadySignal;
    if (modemStat & SERIAL_RTS_STATE)
        ret |= QSerialPort::RequestToSendSignal;

    return ret;
}
Beispiel #15
0
bool QSerialPortPrivate::flush()
{
    Q_Q(QSerialPort);

    bool returnValue = true;

    if (!startAsyncWrite())
        returnValue = false;

    if (!::FlushFileBuffers(handle)) {
        q->setError(decodeSystemError());
        returnValue = false;
    }

    return returnValue;

}
Beispiel #16
0
void QSerialPortPrivate::_q_completeAsyncCommunication()
{
    Q_Q(QSerialPort);

    DWORD numberOfBytesTransferred = 0;

    if (!::GetOverlappedResult(handle, &communicationOverlapped, &numberOfBytesTransferred, FALSE))
        q->setError(decodeSystemError());

    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;
    }

    // Start processing a caught error.
    if (error || (EV_ERR & triggeredEventMask))
        processIoErrors(error);

    if (triggeredEventMask & (EV_CTS | EV_DSR | EV_RLSD | EV_RING) )
    {
        QSerialPort::PinoutSignals signals_mask = 0;
        if (triggeredEventMask & EV_CTS)  signals_mask |= QSerialPort::ClearToSendSignal;
        if (triggeredEventMask & EV_DSR)  signals_mask |= QSerialPort::DataSetReadySignal;
        //No definition in PinoutSignals if (triggeredEventMask & EV_RLSD) signals_mask |= QSerialPort::ReceivedDataSignal;
        if (triggeredEventMask & EV_RING) signals_mask |= QSerialPort::RingIndicatorSignal;
        emit q->pinoutSignalsChanged(signals_mask);

    }

    if (!error && (triggeredEventMask & EV_RXCHAR) )
        startAsyncRead();
    else
        startAsyncCommunication();

}
Beispiel #17
0
void QSerialPortPrivate::_q_completeAsyncWrite()
{
    Q_Q(QSerialPort);

    DWORD numberOfBytesTransferred = 0;
    if (!::GetOverlappedResult(handle, &writeCompletionOverlapped, &numberOfBytesTransferred, FALSE)) {
        numberOfBytesTransferred = 0;
        q->setError(decodeSystemError());
    }

    if (numberOfBytesTransferred > 0) {
        writeBuffer.free(numberOfBytesTransferred);
        emit q->bytesWritten(numberOfBytesTransferred);
    }

    writeStarted = false;
    startAsyncWrite();
}
Beispiel #18
0
bool QSerialPortPrivate::clear(QSerialPort::Directions directions)
{
    Q_Q(QSerialPort);

    DWORD flags = 0;
    if (directions & QSerialPort::Input)
        flags |= PURGE_RXABORT | PURGE_RXCLEAR;
    if (directions & QSerialPort::Output) {
        flags |= PURGE_TXABORT | PURGE_TXCLEAR;
        writeStarted = false;
    }
    if (!::PurgeComm(handle, flags)) {
        q->setError(decodeSystemError());
        return false;
    }

    return true;
}
Beispiel #19
0
bool QSerialPortPrivate::waitForReadyRead(int msecs)
{
    Q_Q(QSerialPort);

    QElapsedTimer stopWatch;
    stopWatch.start();

    const qint64 initialReadBufferSize = readBuffer.size();
    qint64 currentReadBufferSize = initialReadBufferSize;

    do {
        bool timedOut = false;
        HANDLE triggeredEvent = 0;

        if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &timedOut, &triggeredEvent) || !triggeredEvent) {
            // This is occur timeout or another error
            if (!timedOut)
                q->setError(decodeSystemError());
            return false;
        }

        if (triggeredEvent == communicationOverlapped.hEvent) {
            _q_completeAsyncCommunication();
        } else if (triggeredEvent == readCompletionOverlapped.hEvent) {
            _q_completeAsyncRead();
            if (qint64(readBuffer.size()) != currentReadBufferSize)
                currentReadBufferSize = readBuffer.size();
            else if (initialReadBufferSize != currentReadBufferSize)
                return true;
        } else if (triggeredEvent == writeCompletionOverlapped.hEvent) {
            _q_completeAsyncWrite();
        } else {
            return false;
        }

    } while (msecs == -1 || timeoutValue(msecs, stopWatch.elapsed()) > 0);

    return false;
}
Beispiel #20
0
void QSerialPortPrivate::_q_completeAsyncRead()
{
    Q_Q(QSerialPort);

    DWORD numberOfBytesTransferred = 0;
    if (!::GetOverlappedResult(handle, &readCompletionOverlapped, &numberOfBytesTransferred, FALSE))
        q->setError(decodeSystemError());

    if (numberOfBytesTransferred > 0) {

        readBuffer.append(readChunkBuffer.left(numberOfBytesTransferred));

        if (!emulateErrorPolicy())
            emitReadyRead();
    }

    // start async read for possible remainder into driver queue
    if ((numberOfBytesTransferred > 0) && (policy == QSerialPort::IgnorePolicy))
        startAsyncRead();
    else // driver queue is emplty, so startup wait comm event
        startAsyncCommunication();
}
Beispiel #21
0
bool QSerialPortPrivate::startAsyncWrite()
{
    Q_Q(QSerialPort);

    if (writeBuffer.isEmpty() || writeStarted)
        return true;

    initializeOverlappedStructure(writeCompletionOverlapped);
    if (!::WriteFile(handle, writeBuffer.readPointer(),
                     writeBuffer.nextDataBlockSize(),
                     NULL, &writeCompletionOverlapped)) {

        QSerialPort::SerialPortError error = decodeSystemError();
        if (error != QSerialPort::NoError) {
            if (error != QSerialPort::ResourceError)
                error = QSerialPort::WriteError;
            q->setError(error);
            return false;
        }
    }

    writeStarted = true;
    return true;
}
Beispiel #22
0
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{
    Q_Q(QSerialPort);

    DWORD desiredAccess = 0;
    originalEventMask = EV_ERR | EV_CTS | EV_DSR | EV_RING /*| EV_RLSD*/;

    if (mode & QIODevice::ReadOnly) {
        desiredAccess |= GENERIC_READ;
        originalEventMask |= EV_RXCHAR;
    }
    if (mode & QIODevice::WriteOnly)
        desiredAccess |= GENERIC_WRITE;

    handle = ::CreateFile(reinterpret_cast<const wchar_t*>(systemLocation.utf16()),
                              desiredAccess, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

    if (handle == INVALID_HANDLE_VALUE) {
        q->setError(decodeSystemError());
        return false;
    }

    ::ZeroMemory(&restoredDcb, sizeof(restoredDcb));
    restoredDcb.DCBlength = sizeof(restoredDcb);

    if (!::GetCommState(handle, &restoredDcb)) {
        q->setError(decodeSystemError());
        return false;
    }

    currentDcb = restoredDcb;
    currentDcb.fBinary = TRUE;
    currentDcb.fInX = FALSE;
    currentDcb.fOutX = FALSE;
    currentDcb.fAbortOnError = FALSE;
    currentDcb.fNull = FALSE;
    currentDcb.fErrorChar = FALSE;

    if (currentDcb.fDtrControl ==  DTR_CONTROL_HANDSHAKE)
        currentDcb.fDtrControl = DTR_CONTROL_DISABLE;

    if (!updateDcb())
        return false;

    if (!::GetCommTimeouts(handle, &restoredCommTimeouts)) {
        q->setError(decodeSystemError());
        return false;
    }

    ::ZeroMemory(&currentCommTimeouts, sizeof(currentCommTimeouts));
    currentCommTimeouts.ReadIntervalTimeout = MAXDWORD;

    if (!updateCommTimeouts())
        return false;

    if (mode & QIODevice::ReadOnly)
        readCompletionNotifier->setEnabled(true);

    if (mode & QIODevice::WriteOnly)
        writeCompletionNotifier->setEnabled(true);

    if (!::SetCommMask(handle, originalEventMask)) {
        q->setError(decodeSystemError());
        return false;
    }

    if (!startAsyncCommunication())
        return false;

    communicationNotifier->setEnabled(true);

    return true;
}