Commit 62fca265 authored by Lorenz Meier's avatar Lorenz Meier
Browse files

Merged APM config changes, reverted some really ridiculous non-programming changes

parents b6c11a8d 34eaf1fb
This diff is collapsed.
/****************************************************************************
**
** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com>
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSerialPort module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSERIALPORT_H
#define QSERIALPORT_H
#include <QtCore/qiodevice.h>
#include <qserialportglobal.h>
//#include <QtSerialPort/qserialportglobal.h>
QT_BEGIN_NAMESPACE
class QSerialPortInfo;
class QSerialPortPrivate;
class Q_SERIALPORT_EXPORT QSerialPort : public QIODevice
{
Q_OBJECT
Q_PROPERTY(qint32 baudRate READ baudRate WRITE setBaudRate NOTIFY baudRateChanged)
Q_PROPERTY(DataBits dataBits READ dataBits WRITE setDataBits NOTIFY dataBitsChanged)
Q_PROPERTY(Parity parity READ parity WRITE setParity NOTIFY parityChanged)
Q_PROPERTY(StopBits stopBits READ stopBits WRITE setStopBits NOTIFY stopBitsChanged)
Q_PROPERTY(FlowControl flowControl READ flowControl WRITE setFlowControl NOTIFY flowControlChanged)
Q_PROPERTY(DataErrorPolicy dataErrorPolicy READ dataErrorPolicy WRITE setDataErrorPolicy NOTIFY dataErrorPolicyChanged)
Q_PROPERTY(bool dataTerminalReady READ isDataTerminalReady WRITE setDataTerminalReady NOTIFY dataTerminalReadyChanged)
Q_PROPERTY(bool requestToSend READ isRequestToSend WRITE setRequestToSend NOTIFY requestToSendChanged)
Q_PROPERTY(SerialPortError error READ error RESET clearError NOTIFY error)
Q_PROPERTY(bool settingsRestoredOnClose READ settingsRestoredOnClose WRITE setSettingsRestoredOnClose NOTIFY settingsRestoredOnCloseChanged)
Q_ENUMS( Directions Rate DataBits Parity StopBits FlowControl PinoutSignals DataErrorPolicy SerialPortError )
public:
enum Direction {
Input = 1,
Output = 2,
AllDirections = Input | Output
};
Q_DECLARE_FLAGS(Directions, Direction)
enum BaudRate {
Baud1200 = 1200,
Baud2400 = 2400,
Baud4800 = 4800,
Baud9600 = 9600,
Baud19200 = 19200,
Baud38400 = 38400,
Baud57600 = 57600,
Baud115200 = 115200,
UnknownBaud = -1
};
enum DataBits {
Data5 = 5,
Data6 = 6,
Data7 = 7,
Data8 = 8,
UnknownDataBits = -1
};
enum Parity {
NoParity = 0,
EvenParity = 2,
OddParity = 3,
SpaceParity = 4,
MarkParity = 5,
UnknownParity = -1
};
enum StopBits {
OneStop = 1,
OneAndHalfStop = 3,
TwoStop = 2,
UnknownStopBits = -1
};
enum FlowControl {
NoFlowControl,
HardwareControl,
SoftwareControl,
UnknownFlowControl = -1
};
enum PinoutSignal {
NoSignal = 0x00,
TransmittedDataSignal = 0x01,
ReceivedDataSignal = 0x02,
DataTerminalReadySignal = 0x04,
DataCarrierDetectSignal = 0x08,
DataSetReadySignal = 0x10,
RingIndicatorSignal = 0x20,
RequestToSendSignal = 0x40,
ClearToSendSignal = 0x80,
SecondaryTransmittedDataSignal = 0x100,
SecondaryReceivedDataSignal = 0x200
};
Q_DECLARE_FLAGS(PinoutSignals, PinoutSignal)
enum DataErrorPolicy {
SkipPolicy,
PassZeroPolicy,
IgnorePolicy,
StopReceivingPolicy,
UnknownPolicy = -1
};
enum SerialPortError {
NoError,
DeviceNotFoundError,
PermissionError,
OpenError,
ParityError,
FramingError,
BreakConditionError,
WriteError,
ReadError,
ResourceError,
UnsupportedOperationError,
UnknownError
};
explicit QSerialPort(QObject *parent = 0);
explicit QSerialPort(const QString &name, QObject *parent = 0);
explicit QSerialPort(const QSerialPortInfo &info, QObject *parent = 0);
virtual ~QSerialPort();
void setPortName(const QString &name);
QString portName() const;
void setPort(const QSerialPortInfo &info);
bool open(OpenMode mode) Q_DECL_OVERRIDE;
void close() Q_DECL_OVERRIDE;
void setSettingsRestoredOnClose(bool restore);
bool settingsRestoredOnClose() const;
bool setBaudRate(qint32 baudRate, Directions dir = AllDirections);
qint32 baudRate(Directions dir = AllDirections) const;
bool setDataBits(DataBits dataBits);
DataBits dataBits() const;
bool setParity(Parity parity);
Parity parity() const;
bool setStopBits(StopBits stopBits);
StopBits stopBits() const;
bool setFlowControl(FlowControl flow);
FlowControl flowControl() const;
bool setDataTerminalReady(bool set);
bool isDataTerminalReady();
bool setRequestToSend(bool set);
bool isRequestToSend();
PinoutSignals pinoutSignals();
bool flush();
bool clear(Directions dir = AllDirections);
bool atEnd() const Q_DECL_OVERRIDE;
bool setDataErrorPolicy(DataErrorPolicy policy = IgnorePolicy);
DataErrorPolicy dataErrorPolicy() const;
SerialPortError error() const;
void clearError();
qint64 readBufferSize() const;
void setReadBufferSize(qint64 size);
bool isSequential() const Q_DECL_OVERRIDE;
qint64 bytesAvailable() const Q_DECL_OVERRIDE;
qint64 bytesToWrite() const Q_DECL_OVERRIDE;
bool canReadLine() const Q_DECL_OVERRIDE;
bool waitForReadyRead(int msecs) Q_DECL_OVERRIDE;
bool waitForBytesWritten(int msecs) Q_DECL_OVERRIDE;
bool sendBreak(int duration = 0);
bool setBreakEnabled(bool set = true);
Q_SIGNALS:
void baudRateChanged(qint32 baudRate, QSerialPort::Directions dir);
void dataBitsChanged(QSerialPort::DataBits dataBits);
void parityChanged(QSerialPort::Parity parity);
void stopBitsChanged(QSerialPort::StopBits stopBits);
void flowControlChanged(QSerialPort::FlowControl flow);
void dataErrorPolicyChanged(QSerialPort::DataErrorPolicy policy);
void dataTerminalReadyChanged(bool set);
void requestToSendChanged(bool set);
void error(QSerialPort::SerialPortError serialPortError);
void settingsRestoredOnCloseChanged(bool restore);
protected:
qint64 readData(char *data, qint64 maxSize) Q_DECL_OVERRIDE;
qint64 readLineData(char *data, qint64 maxSize) Q_DECL_OVERRIDE;
qint64 writeData(const char *data, qint64 maxSize) Q_DECL_OVERRIDE;
private:
void setError(QSerialPort::SerialPortError error, const QString &errorString = QString());
QSerialPortPrivate * const d_ptr;
Q_DECLARE_PRIVATE(QSerialPort)
Q_DISABLE_COPY(QSerialPort)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QSerialPort::Directions)
Q_DECLARE_OPERATORS_FOR_FLAGS(QSerialPort::PinoutSignals)
QT_END_NAMESPACE
#endif // QSERIALPORT_H
INCLUDEPATH += $$PWD
unix {
CONFIG += link_pkgconfig
packagesExist(libudev) {
DEFINES += HAVE_LIBUDEV
PKGCONFIG += libudev
}
}
PUBLIC_HEADERS += \
$$PWD/qserialportglobal.h \
$$PWD/qserialport.h \
$$PWD/qserialportinfo.h
PRIVATE_HEADERS += \
$$PWD/qserialport_p.h \
$$PWD/qserialportinfo_p.h
SOURCES += \
$$PWD/qserialport.cpp \
$$PWD/qserialportinfo.cpp
win32 {
PRIVATE_HEADERS += \
$$PWD/qserialport_win_p.h
SOURCES += \
$$PWD/qserialport_win.cpp \
$$PWD/qserialportinfo_win.cpp
LIBS += -lsetupapi -ladvapi32
}
unix:!symbian {
PRIVATE_HEADERS += \
$$PWD/qttylocker_unix_p.h \
$$PWD/qserialport_unix_p.h
SOURCES += \
$$PWD/qttylocker_unix.cpp \
$$PWD/qserialport_unix.cpp \
$$PWD/qserialportinfo_unix.cpp
macx {
SOURCES += $$PWD/qserialportinfo_mac.cpp
LIBS += -framework IOKit -framework CoreFoundation
} else {
linux*:contains( DEFINES, HAVE_LIBUDEV ) {
LIBS += -ludev
}
}
}
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
/****************************************************************************
**
** Copyright (C) 2011-2012 Denis Shienkov <denis.shienkov@gmail.com>
** Copyright (C) 2011 Sergey Belyashov <Sergey.Belyashov@gmail.com>
** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSerialPort module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSERIALPORT_P_H
#define QSERIALPORT_P_H
#include "qserialport.h"
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
#include <private/qringbuffer_p.h>
#else
#include "qt4support/qringbuffer_p.h"
#endif
QT_BEGIN_NAMESPACE
class QSerialPortPrivateData
{
Q_DECLARE_PUBLIC(QSerialPort)
public:
enum IoConstants {
ReadChunkSize = 512,
WriteChunkSize = 512
};
QSerialPortPrivateData(QSerialPort *q);
int timeoutValue(int msecs, int elapsed);
qint64 readBufferMaxSize;
QRingBuffer readBuffer;
QRingBuffer writeBuffer;
QSerialPort::SerialPortError error;
QString systemLocation;
qint32 inputBaudRate;
qint32 outputBaudRate;
QSerialPort::DataBits dataBits;
QSerialPort::Parity parity;
QSerialPort::StopBits stopBits;
QSerialPort::FlowControl flow;
QSerialPort::DataErrorPolicy policy;
bool dataTerminalReady;
bool requestToSend;
bool settingsRestoredOnClose;
QSerialPort * const q_ptr;
};
QT_END_NAMESPACE
#endif // QSERIALPORT_P_H
/****************************************************************************
**
** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSerialPort module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qserialport_symbian_p.h"
#include <QtCore/qmap.h>
#include <e32base.h>
//#include <e32test.h>
#include <f32file.h>
QT_BEGIN_NAMESPACE
// Physical device driver.
#ifdef __WINS__
_LIT(KPddName, "ECDRV");
#else // defined (__EPOC32__)
_LIT(KPddName, "EUART");
#endif
// Logical device driver.
_LIT(KLddName,"ECOMM");
// Modules names.
_LIT(KRS232ModuleName, "ECUART");
_LIT(KBluetoothModuleName, "BTCOMM");
_LIT(KInfraRedModuleName, "IRCOMM");
_LIT(KACMModuleName, "ECACM");
// Return false on error load.
static bool loadDevices()
{
TInt r = KErrNone;
#ifdef __WINS__
RFs fileServer;
r = User::LeaveIfError(fileServer.Connect());
if (r != KErrNone)
return false;
fileServer.Close ();
#endif
r = User::LoadPhysicalDevice(KPddName);
if (r != KErrNone && r != KErrAlreadyExists)
return false; //User::Leave(r);
r = User::LoadLogicalDevice(KLddName);
if (r != KErrNone && r != KErrAlreadyExists)
return false; //User::Leave(r);
#ifndef __WINS__
r = StartC32();
if (r != KErrNone && r != KErrAlreadyExists)
return false; //User::Leave(r);
#endif
return true;
}
QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
: QSerialPortPrivateData(q)
, errnum(KErrNone)
{
}
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{
// FIXME: Maybe need added check an ReadWrite open mode?
Q_UNUSED(mode)
if (!loadDevices()) {
q_ptr->setError(QSerialPort::UnknownError);
return false;
}
RCommServ server;
errnum = server.Connect();
if (errnum != KErrNone) {
q_ptr->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_ptr->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_ptr->setError(decodeSystemError());
return false;
}
// Save current port settings.
errnum = descriptor.Config(restoredSettings);
if (errnum != KErrNone) {
q_ptr->setError(decodeSystemError());
return false;
}
detectDefaultSettings();
return true;
}
void QSerialPortPrivate::close()
{
if (settingsRestoredOnClose)
descriptor.SetConfig(restoredSettings);
descriptor.Close();
}
QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals() const
{
QSerialPort::PinoutSignals ret = QSerialPort::NoSignal;
TUint signalMask = 0;
descriptor.Signals(signalMask);
if (signalMask & KSignalCTS)
ret |= QSerialPort::ClearToSendSignal;
if (signalMask & KSignalDSR)
ret |= QSerialPort::DataSetReadySignal;
if (signalMask & KSignalDCD)
ret |= QSerialPort::DataCarrierDetectSignal;
if (signalMask & KSignalRNG)
ret |= QSerialPort::RingIndicatorSignal;
if (signalMask & KSignalRTS)
ret |= QSerialPort::RequestToSendSignal;
if (signalMask & KSignalDTR)
ret |= QSerialPort::DataTerminalReadySignal;
//if (signalMask & KSignalBreak)
// ret |=
return ret;
}
bool QSerialPortPrivate::setDataTerminalReady(bool set)
{
TInt r;
if (set)
r = descriptor.SetSignalsToMark(KSignalDTR);
else
r = descriptor.SetSignalsToSpace(KSignalDTR);
return r == KErrNone;
}
bool QSerialPortPrivate::setRequestToSend(bool set)
{
TInt r;
if (set)
r = descriptor.SetSignalsToMark(KSignalRTS);
else
r = descriptor.SetSignalsToSpace(KSignalRTS);
return r == KErrNone;
}
bool QSerialPortPrivate::flush()
{
// TODO: Implement me
return false;
}
bool QSerialPortPrivate::clear(QSerialPort::Directions dir)
{
TUint flags = 0;
if (dir & QSerialPort::Input)
flags |= KCommResetRx;
if (dir & QSerialPort::Output)
flags |= KCommResetTx;
TInt r = descriptor.ResetBuffers(flags);
return r == KErrNone;
}
bool QSerialPortPrivate::sendBreak(int duration)
{
TRequestStatus status;
descriptor.Break(status, TTimeIntervalMicroSeconds32(duration * 1000));
return false;
}
bool QSerialPortPrivate::setBreakEnabled(bool set)
{
// TODO: Implement me
return false;
}
qint64 QSerialPortPrivate::systemInputQueueSize () const
{
return descriptor.QueryReceiveBuffer();
}
qint64 QSerialPortPrivate::systemOutputQueueSize () const
{
// TODO: Implement me
return 0;
}
qint64 QSerialPortPrivate::bytesAvailable() const
{
return readBuffer.size();
}
qint64 QSerialPortPrivate::readFromBuffer(char *data, qint64 maxSize)
{
// TODO: Implement me
return -1;
}
qint64 QSerialPortPrivate::writeToBuffer(const char *data, qint64 maxSize)
{
// TODO: Implement me
return -1;
}
bool QSerialPortPrivate::waitForReadyRead(int msec)
{
// TODO: Implement me
return false;
}
bool QSerialPortPrivate::waitForBytesWritten(int msec)
{
// TODO: Implement me
return false;
}
bool QSerialPortPrivate::setBaudRate(qint32 baudRate, QSerialPort::Directions dir)
{
if (dir != QSerialPort::AllDirections) {
q_ptr->setError(QSerialPort::UnsupportedOperationError);
return false;
}
baudRate = settingFromBaudRate(baudRate);
if (baudRate)
currentSettings().iRate = static_cast<TBps>(baudRate);
else {
q_ptr->setError(QSerialPort::UnsupportedOperationError);
return false;
}
return updateCommConfig();
}
bool QSerialPortPrivate::setDataBits(QSerialPort::DataBits dataBits)
{
switch (dataBits) {
case QSerialPort::Data5:
currentSettings().iDataBits = EData5;
break;
case QSerialPort::Data6:
currentSettings().iDataBits = EData6;
break;
case QSerialPort::Data7:
currentSettings().iDataBits = EData7;
break;
case QSerialPort::Data8:
currentSettings().iDataBits = EData8;
break;
default:
currentSettings().iDataBits = EData8;
break;
}
return updateCommConfig();
}
bool QSerialPortPrivate::setParity(QSerialPort::Parity parity)
{
switch (parity) {
case QSerialPort::NoParity:
currentSettings().iParity = EParityNone;
break;
case QSerialPort::EvenParity:
currentSettings().iParity = EParityEven;
break;
case QSerialPort::OddParity:
currentSettings().iParity = EParityOdd;
break;
case QSerialPort::MarkParity:
currentSettings().iParity = EParityMark;
break;
case QSerialPort::SpaceParity:
currentSettings().iParity = EParitySpace;
break;
default:
currentSettings().iParity = EParityNone;
break;
}
return updateCommConfig();
}
bool QSerialPortPrivate::setStopBits(QSerialPort::StopBits stopBits)
{
switch (stopBits) {
case QSerialPort::OneStop:
currentSettings().iStopBits = EStop1;
break;
case QSerialPort::TwoStop:
currentSettings().iStopBits = EStop2;
break;
default:
currentSettings().iStopBits = EStop1;
break;
}
return updateCommConfig();
}
bool QSerialPortPrivate::setFlowControl(QSerialPort::FlowControl flow)
{
switch (flow) {
case QSerialPort::NoFlowControl:
currentSettings().iHandshake = KConfigFailDSR;
break;
case QSerialPort::HardwareControl:
currentSettings().iHandshake = KConfigObeyCTS | KConfigFreeRTS;
break;
case QSerialPort::SoftwareControl:
currentSettings().iHandshake = KConfigObeyXoff | KConfigSendXoff;
break;
default:
currentSettings().iHandshake = KConfigFailDSR;
break;
}
return updateCommConfig();
}
bool QSerialPortPrivate::setDataErrorPolicy(QSerialPort::DataErrorPolicy policy)
{
// TODO: Implement me
return false;
}
bool QSerialPortPrivate::notifyRead()
{
// TODO: Implement me
return false;
}
bool QSerialPortPrivate::notifyWrite()
{
// TODO: Implement me
return false;
}
bool QSerialPortPrivate::updateCommConfig()
{
if (descriptor.SetConfig(currentSettings) != KErrNone) {
q_ptr->setError(QSerialPort::UnsupportedOperationError);
return false;
}
return true;
}
void QSerialPortPrivate::detectDefaultSettings()
{
// Detect baud rate.
inputBaudRate = baudRateFromSetting(currentSettings().iRate);
outputBaudRate = inputBaudRate;
// Detect databits.
switch (currentSettings().iDataBits) {
case EData5:
dataBits = QSerialPort::Data5;
break;
case EData6:
dataBits = QSerialPort::Data6;
break;
case EData7:
dataBits = QSerialPort::Data7;
break;
case EData8:
dataBits = QSerialPort::Data8;
break;
default:
dataBits = QSerialPort::UnknownDataBits;
break;
}
// Detect parity.
switch (currentSettings().iParity) {
case EParityNone:
parity = QSerialPort::NoParity;
break;
case EParityEven:
parity = QSerialPort::EvenParity;
break;
case EParityOdd:
parity = QSerialPort::OddParity;
break;
case EParityMark:
parity = QSerialPort::MarkParity;
break;
case EParitySpace:
parity = QSerialPort::SpaceParity;
break;
default:
parity = QSerialPort::UnknownParity;
break;
}
// Detect stopbits.
switch (currentSettings().iStopBits) {
case EStop1:
stopBits = QSerialPort::OneStop;
break;
case EStop2:
stopBits = QSerialPort::TwoStop;
break;
default:
stopBits = QSerialPort::UnknownStopBits;
break;
}
// Detect flow control.
if ((currentSettings().iHandshake & (KConfigObeyXoff | KConfigSendXoff))
== (KConfigObeyXoff | KConfigSendXoff))
flow = QSerialPort::SoftwareControl;
else if ((currentSettings().iHandshake & (KConfigObeyCTS | KConfigFreeRTS))
== (KConfigObeyCTS | KConfigFreeRTS))
flow = QSerialPort::HardwareControl;
else if (currentSettings().iHandshake & KConfigFailDSR)
flow = QSerialPort::NoFlowControl;
else
flow = QSerialPort::UnknownFlowControl;
}
QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
{
QSerialPort::SerialPortError error;
switch (errnum) {
case KErrPermissionDenied:
error = QSerialPort::DeviceNotFoundError;
break;
case KErrLocked:
error = QSerialPort::PermissionError;
break;
case KErrAccessDenied:
error = QSerialPort::PermissionError;
break;
default:
error = QSerialPort::UnknownError;
break;
}
return error;
}
bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectForWrite,
bool checkRead, bool checkWrite,
int msecs, bool *timedOut)
{
// FIXME: I'm not sure in implementation this method.
// Someone needs to check and correct.
TRequestStatus timerStatus;
TRequestStatus readStatus;
TRequestStatus writeStatus;
if (msecs > 0) {
if (!selectTimer.Handle()) {
if (selectTimer.CreateLocal() != KErrNone)
return false;
}
selectTimer.HighRes(timerStatus, msecs * 1000);
}
if (checkRead)
descriptor.NotifyDataAvailable(readStatus);
if (checkWrite)
descriptor.NotifyOutputEmpty(writeStatus);
enum { STATUSES_COUNT = 3 };
TRequestStatus *statuses[STATUSES_COUNT];
TInt num = 0;
statuses[num++] = &timerStatus;
statuses[num++] = &readStatus;
statuses[num++] = &writeStatus;
User::WaitForNRequest(statuses, num);
bool result = false;
// By timeout?
if (timerStatus != KRequestPending) {
Q_ASSERT(selectForRead);
*selectForRead = false;
Q_ASSERT(selectForWrite);
*selectForWrite = false;
} else {
selectTimer.Cancel();
User::WaitForRequest(timerStatus);
// By read?
if (readStatus != KRequestPending) {
Q_ASSERT(selectForRead);
*selectForRead = true;
}
// By write?
if (writeStatus != KRequestPending) {
Q_ASSERT(selectForWrite);
*selectForWrite = true;
}
if (checkRead)
descriptor.NotifyDataAvailableCancel();
if (checkWrite)
descriptor.NotifyOutputEmptyCancel();
result = true;
}
return result;
}
QString QSerialPortPrivate::portNameToSystemLocation(const QString &port)
{
// Port name is equval to port systemLocation.
return port;
}
QString QSerialPortPrivate::portNameFromSystemLocation(const QString &location)
{
// Port name is equval to port systemLocation.
return location;
}
typedef QMap<qint32, qint32> BaudRateMap;
// This table contains correspondences standard pairs values of
// baud rates that are defined in files
// - d32comm.h for Symbian^3
// - d32public.h for Symbian SR1
static const BaudRateMap createStandardBaudRateMap()
{
BaudRateMap baudRateMap;
baudRateMap.insert(50, EBps50)
baudRateMap.insert(75, EBps75)
baudRateMap.insert(110, EBps110)
baudRateMap.insert(134, EBps134)
baudRateMap.insert(150, EBps150)
baudRateMap.insert(300, EBps300)
baudRateMap.insert(600, EBps600)
baudRateMap.insert(1200, EBps1200)
baudRateMap.insert(1800, EBps1800)
baudRateMap.insert(2000, EBps2000)
baudRateMap.insert(2400, EBps2400)
baudRateMap.insert(3600, EBps3600)
baudRateMap.insert(4800, EBps4800)
baudRateMap.insert(7200, EBps7200)
baudRateMap.insert(9600, EBps9600)
baudRateMap.insert(19200, EBps19200)
baudRateMap.insert(38400, EBps38400)
baudRateMap.insert(57600, EBps57600)
baudRateMap.insert(115200, EBps115200)
baudRateMap.insert(230400, EBps230400)
baudRateMap.insert(460800, EBps460800)
baudRateMap.insert(576000, EBps576000)
baudRateMap.insert(921600, EBps921600)
baudRateMap.insert(1152000, EBps1152000)
// << baudRateMap.insert(1843200, EBps1843200) only for Symbian SR1
baudRateMap.insert(4000000, EBps4000000);
return baudRateMap;
}
static const BaudRateMap& standardBaudRateMap()
{
static const BaudRateMap baudRateMap = createStandardBaudRateMap();
return baudRateMap;
}
qint32 QSerialPortPrivate::baudRateFromSetting(qint32 setting)
{
return standardBaudRateMap().key(setting);
}
qint32 QSerialPortPrivate::settingFromBaudRate(qint32 baudRate)
{
return standardBaudRateMap().value(baudRate);
}
QList<qint32> QSerialPortPrivate::standardBaudRates()
{
return standardBaudRateMap().keys();
}
QT_END_NAMESPACE
/****************************************************************************
**
** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSerialPort module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSERIALPORT_SYMBIAN_P_H
#define QSERIALPORT_SYMBIAN_P_H
#include "qserialport_p.h"
#include <c32comm.h>
QT_BEGIN_NAMESPACE
class QSerialPortPrivate : public QSerialPortPrivateData
{
public:
QSerialPortPrivate(QSerialPort *q);
bool open(QIODevice::OpenMode mode);
void close();
QSerialPort::PinoutSignals pinoutSignals() const;
bool setDataTerminalReady(bool set);
bool setRequestToSend(bool set);
bool flush();
bool clear(QSerialPort::Directions dir);
bool sendBreak(int duration);
bool setBreakEnabled(bool set);
qint64 systemInputQueueSize () const;
qint64 systemOutputQueueSize () const;
qint64 bytesAvailable() const;
qint64 readFromBuffer(char *data, qint64 maxSize);
qint64 writeToBuffer(const char *data, qint64 maxSize);
bool waitForReadyRead(int msec);
bool waitForBytesWritten(int msec);
bool setBaudRate(qint32 baudRate, QSerialPort::Directions dir);
bool setDataBits(QSerialPort::DataBits dataBits);
bool setParity(QSerialPort::Parity parity);
bool setStopBits(QSerialPort::StopBits stopBits);
bool setFlowControl(QSerialPort::FlowControl flowControl);
bool setDataErrorPolicy(QSerialPort::DataErrorPolicy policy);
bool notifyRead();
bool notifyWrite();
static QString portNameToSystemLocation(const QString &port);
static QString portNameFromSystemLocation(const QString &location);
static qint32 baudRateFromSetting(qint32 setting);
static qint32 settingFromBaudRate(qint32 baudRate);
static QList<qint32> standardBaudRates();
TCommConfig currentSettings;
TCommConfig restoredSettings;
RComm descriptor;
mutable RTimer selectTimer;
TInt errnum;
private:
bool updateCommConfig();
void detectDefaultSettings();
QSerialPort::SerialPortError decodeSystemError() const;
bool waitForReadOrWrite(bool *selectForRead, bool *selectForWrite,
bool checkRead, bool checkWrite,
int msecs, bool *timedOut);
};
QT_END_NAMESPACE
#endif // QSERIALPORT_SYMBIAN_P_H
This diff is collapsed.
/****************************************************************************
**
** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com>
** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSerialPort module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSERIALPORT_UNIX_P_H
#define QSERIALPORT_UNIX_P_H
#include "qserialport_p.h"
#include <limits.h>
#include <termios.h>
#ifdef Q_OS_LINUX
# include <linux/serial.h>
#endif
QT_BEGIN_NAMESPACE
class QSocketNotifier;
class QSerialPortPrivate : public QSerialPortPrivateData
{
public:
QSerialPortPrivate(QSerialPort *q);
bool open(QIODevice::OpenMode mode);
void close();
QSerialPort::PinoutSignals pinoutSignals() const;
bool setDataTerminalReady(bool set);
bool setRequestToSend(bool set);
bool flush();
bool clear(QSerialPort::Directions dir);
bool sendBreak(int duration);
bool setBreakEnabled(bool set);
qint64 systemInputQueueSize () const;
qint64 systemOutputQueueSize () const;
qint64 bytesAvailable() const;
qint64 readFromBuffer(char *data, qint64 maxSize);
qint64 writeToBuffer(const char *data, qint64 maxSize);
bool waitForReadyRead(int msecs);
bool waitForBytesWritten(int msecs);
bool setBaudRate(qint32 baudRate, QSerialPort::Directions dir);
bool setDataBits(QSerialPort::DataBits dataBits);
bool setParity(QSerialPort::Parity parity);
bool setStopBits(QSerialPort::StopBits stopBits);
bool setFlowControl(QSerialPort::FlowControl flow);
bool setDataErrorPolicy(QSerialPort::DataErrorPolicy policy);
bool readNotification();
bool writeNotification(int maxSize = INT_MAX);
bool exceptionNotification();
static QString portNameToSystemLocation(const QString &port);
static QString portNameFromSystemLocation(const QString &location);
static qint32 baudRateFromSetting(qint32 setting);
static qint32 settingFromBaudRate(qint32 baudRate);
static QList<qint32> standardBaudRates();
struct termios currentTermios;
struct termios restoredTermios;
#ifdef Q_OS_LINUX
struct serial_struct currentSerialInfo;
struct serial_struct restoredSerialInfo;
#endif
int descriptor;
bool isCustomBaudRateSupported;
QSocketNotifier *readNotifier;
QSocketNotifier *writeNotifier;
QSocketNotifier *exceptionNotifier;
bool readPortNotifierCalled;
bool readPortNotifierState;
bool readPortNotifierStateSet;
bool emittedReadyRead;
bool emittedBytesWritten;
private:
bool updateTermios();
void detectDefaultSettings();
QSerialPort::SerialPortError decodeSystemError() const;
bool isReadNotificationEnabled() const;
void setReadNotificationEnabled(bool enable);
bool isWriteNotificationEnabled() const;
void setWriteNotificationEnabled(bool enable);
bool isExceptionNotificationEnabled() const;
void setExceptionNotificationEnabled(bool enable);
bool waitForReadOrWrite(bool *selectForRead, bool *selectForWrite,
bool checkRead, bool checkWrite,
int msecs, bool *timedOut);
qint64 readFromPort(char *data, qint64 maxSize);
qint64 writeToPort(const char *data, qint64 maxSize);
#ifndef CMSPAR
qint64 writePerChar(const char *data, qint64 maxSize);
#endif
qint64 readPerChar(char *data, qint64 maxSize);
};
QT_END_NAMESPACE
#endif // QSERIALPORT_UNIX_P_H
This diff is collapsed.
/****************************************************************************
**
** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com>
** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSerialPort module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSERIALPORT_WIN_P_H
#define QSERIALPORT_WIN_P_H
#include "qserialport_p.h"
#include <qt_windows.h>
#ifndef Q_OS_WINCE
#include <QtCore/qhash.h>
QT_BEGIN_NAMESPACE
class QWinEventNotifier;
#else
#include <QtCore/qmutex.h>
QT_BEGIN_NAMESPACE
class QThread;
#endif
#ifndef Q_OS_WINCE
class AbstractOverlappedEventNotifier;
#endif
class QSerialPortPrivate : public QSerialPortPrivateData
{
public:
QSerialPortPrivate(QSerialPort *q);
bool open(QIODevice::OpenMode mode);
void close();
QSerialPort::PinoutSignals pinoutSignals() const;
bool setDataTerminalReady(bool set);
bool setRequestToSend(bool set);
bool flush();
bool clear(QSerialPort::Directions dir);
bool sendBreak(int duration);
bool setBreakEnabled(bool set);
qint64 systemInputQueueSize () const;
qint64 systemOutputQueueSize () const;
qint64 bytesAvailable() const;
qint64 readFromBuffer(char *data, qint64 maxSize);
qint64 writeToBuffer(const char *data, qint64 maxSize);
bool waitForReadyRead(int msec);
bool waitForBytesWritten(int msec);
bool setBaudRate(qint32 baudRate, QSerialPort::Directions dir);
bool setDataBits(QSerialPort::DataBits dataBits);
bool setParity(QSerialPort::Parity parity);
bool setStopBits(QSerialPort::StopBits stopBits);
bool setFlowControl(QSerialPort::FlowControl flowControl);
bool setDataErrorPolicy(QSerialPort::DataErrorPolicy policy);
bool processIoErrors(bool error);
#ifndef Q_OS_WINCE
bool startAsyncRead();
bool startAsyncWrite(int maxSize = INT_MAX);
bool completeAsyncRead(DWORD numberOfBytes);
bool completeAsyncWrite(DWORD numberOfBytes);
AbstractOverlappedEventNotifier *lookupFreeWriteCompletionNotifier();
AbstractOverlappedEventNotifier *lookupCommEventNotifier();
AbstractOverlappedEventNotifier *lookupReadCompletionNotifier();
#else
bool notifyRead();
bool notifyWrite(int maxSize = INT_MAX);
#endif
static QString portNameToSystemLocation(const QString &port);
static QString portNameFromSystemLocation(const QString &location);
static qint32 baudRateFromSetting(qint32 setting);
static qint32 settingFromBaudRate(qint32 baudRate);
static QList<qint32> standardBaudRates();
DCB currentDcb;
DCB restoredDcb;
COMMTIMEOUTS currentCommTimeouts;
COMMTIMEOUTS restoredCommTimeouts;
HANDLE descriptor;
bool parityErrorOccurred;
#ifndef Q_OS_WINCE
QHash<HANDLE, AbstractOverlappedEventNotifier *> notifiers;
qint64 actualReadBufferSize;
qint64 actualWriteBufferSize;
qint64 acyncWritePosition;
bool readyReadEmitted;
bool writeSequenceStarted;
#else
QThread *eventNotifier;
QMutex settingsChangeMutex;
#endif
private:
bool updateDcb();
bool updateCommTimeouts();
void detectDefaultSettings();
QSerialPort::SerialPortError decodeSystemError() const;
#ifndef Q_OS_WINCE
bool waitAnyEvent(int msecs, bool *timedOut,
AbstractOverlappedEventNotifier **triggeredNotifier);
#else
bool waitForReadOrWrite(bool *selectForRead, bool *selectForWrite,
bool checkRead, bool checkWrite,
int msecs, bool *timedOut);
#endif
};
QT_END_NAMESPACE
#endif // QSERIALPORT_WIN_P_H
/****************************************************************************
**
** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com>
** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org>
** Copyright (C) 2012 Andre Hartmann <aha_1980@gmx.de>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSerialPort module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qserialport_win_p.h"
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qthread.h>
#include <QtCore/qtimer.h>
QT_BEGIN_NAMESPACE
class QSerialPortPrivate;
class CommEventNotifier : public QThread
{
Q_OBJECT
signals:
void eventMask(quint32 mask);
public:
CommEventNotifier(DWORD mask, QSerialPortPrivate *d, QObject *parent)
: QThread(parent), dptr(d), running(true) {
connect(this, SIGNAL(eventMask(quint32)), this, SLOT(processNotification(quint32)));
::SetCommMask(dptr->descriptor, mask);
}
virtual ~CommEventNotifier() {
running = false;
::SetCommMask(dptr->descriptor, 0);
wait();
}
protected:
void run() Q_DECL_OVERRIDE {
DWORD mask = 0;
while (running) {
if (::WaitCommEvent(dptr->descriptor, &mask, FALSE)) {
// Wait until complete the operation changes the port settings,
// see updateDcb().
dptr->settingsChangeMutex.lock();
dptr->settingsChangeMutex.unlock();
emit eventMask(quint32(mask));
}
}
}
private slots:
void processNotification(quint32 eventMask) {
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 ((eventMask == 0)
|| ((eventMask & (EV_ERR | EV_RXCHAR | EV_TXEMPTY)) == 0)) {
error = true;
}
if (error || (EV_ERR & eventMask))
dptr->processIoErrors(error);
if (EV_RXCHAR & eventMask)
dptr->notifyRead();
if (EV_TXEMPTY & eventMask)
dptr->notifyWrite(QSerialPortPrivateData::WriteChunkSize);
}
private:
QSerialPortPrivate *dptr;
mutable bool running;
};
class WaitCommEventBreaker : public QThread
{
Q_OBJECT
public:
WaitCommEventBreaker(HANDLE descriptor, int timeout, QObject *parent = 0)
: QThread(parent), descriptor(descriptor), timeout(timeout), worked(false) {
start();
}
virtual ~WaitCommEventBreaker() {
stop();
wait();
}
void stop() {
exit(0);
}
bool isWorked() const {
return worked;
}
protected:
void run() {
QTimer timer;
QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(processTimeout()), Qt::DirectConnection);
timer.start(timeout);
exec();
worked = true;
}
private slots:
void processTimeout() {
::SetCommMask(descriptor, 0);
stop();
}
private:
HANDLE descriptor;
int timeout;
mutable bool worked;
};
QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
: QSerialPortPrivateData(q)
, descriptor(INVALID_HANDLE_VALUE)
, parityErrorOccurred(false)
, eventNotifier(0)
{
}
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{
DWORD desiredAccess = 0;
DWORD eventMask = EV_ERR;
if (mode & QIODevice::ReadOnly) {
desiredAccess |= GENERIC_READ;
eventMask |= EV_RXCHAR;
}
if (mode & QIODevice::WriteOnly) {
desiredAccess |= GENERIC_WRITE;
eventMask |= EV_TXEMPTY;
}
descriptor = ::CreateFile(reinterpret_cast<const wchar_t*>(systemLocation.utf16()),
desiredAccess, 0, NULL, OPEN_EXISTING, 0, NULL);
if (descriptor == INVALID_HANDLE_VALUE) {
q_ptr->setError(decodeSystemError());
return false;
}
if (!::GetCommState(descriptor, &restoredDcb)) {
q_ptr->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 (!updateDcb())
return false;
if (!::GetCommTimeouts(descriptor, &restoredCommTimeouts)) {
q_ptr->setError(decodeSystemError());
return false;
}
::memset(&currentCommTimeouts, 0, sizeof(currentCommTimeouts));
currentCommTimeouts.ReadIntervalTimeout = MAXDWORD;
if (!updateCommTimeouts())
return false;
eventNotifier = new CommEventNotifier(eventMask, this, q_ptr);
eventNotifier->start();
detectDefaultSettings();
return true;
}
void QSerialPortPrivate::close()
{
if (eventNotifier) {
eventNotifier->deleteLater();
eventNotifier = 0;
}
if (settingsRestoredOnClose) {
::SetCommState(descriptor, &restoredDcb);
::SetCommTimeouts(descriptor, &restoredCommTimeouts);
}
::CloseHandle(descriptor);
descriptor = INVALID_HANDLE_VALUE;
}
bool QSerialPortPrivate::flush()
{
return notifyWrite() && ::FlushFileBuffers(descriptor);
}
bool QSerialPortPrivate::clear(QSerialPort::Directions dir)
{
DWORD flags = 0;
if (dir & QSerialPort::Input)
flags |= PURGE_RXABORT | PURGE_RXCLEAR;
if (dir & QSerialPort::Output)
flags |= PURGE_TXABORT | PURGE_TXCLEAR;
return ::PurgeComm(descriptor, flags);
}
qint64 QSerialPortPrivate::bytesAvailable() const
{
return readBuffer.size();
}
qint64 QSerialPortPrivate::readFromBuffer(char *data, qint64 maxSize)
{
if (readBuffer.isEmpty())
return 0;
if (maxSize == 1) {
*data = readBuffer.getChar();
return 1;
}
const qint64 bytesToRead = qMin(qint64(readBuffer.size()), maxSize);
qint64 readSoFar = 0;
while (readSoFar < bytesToRead) {
const char *ptr = readBuffer.readPointer();
const int bytesToReadFromThisBlock = qMin(int(bytesToRead - readSoFar),
readBuffer.nextDataBlockSize());
::memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
readSoFar += bytesToReadFromThisBlock;
readBuffer.free(bytesToReadFromThisBlock);
}
return readSoFar;
}
qint64 QSerialPortPrivate::writeToBuffer(const char *data, qint64 maxSize)
{
char *ptr = writeBuffer.reserve(maxSize);
if (maxSize == 1)
*ptr = *data;
else
::memcpy(ptr, data, maxSize);
// trigger write sequence
notifyWrite(QSerialPortPrivateData::WriteChunkSize);
return maxSize;
}
bool QSerialPortPrivate::waitForReadyRead(int msec)
{
if (!readBuffer.isEmpty())
return true;
QElapsedTimer stopWatch;
stopWatch.start();
forever {
bool readyToRead = false;
bool readyToWrite = false;
bool timedOut = false;
if (!waitForReadOrWrite(&readyToRead, &readyToWrite,
true, !writeBuffer.isEmpty(),
timeoutValue(msec, stopWatch.elapsed()),
&timedOut)) {
return false;
}
if (readyToRead) {
if (notifyRead())
return true;
}
if (readyToWrite)
notifyWrite(WriteChunkSize);
}
return false;
}
bool QSerialPortPrivate::waitForBytesWritten(int msec)
{
if (writeBuffer.isEmpty())
return false;
QElapsedTimer stopWatch;
stopWatch.start();
forever {
bool readyToRead = false;
bool readyToWrite = false;
bool timedOut = false;
if (!waitForReadOrWrite(&readyToRead, &readyToWrite,
true, !writeBuffer.isEmpty(),
timeoutValue(msec, stopWatch.elapsed()),
&timedOut)) {
return false;
}
if (readyToRead) {
if (!notifyRead())
return false;
}
if (readyToWrite) {
if (notifyWrite(WriteChunkSize))
return true;
}
}
return false;
}
bool QSerialPortPrivate::notifyRead()
{
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;
}
}
char *ptr = readBuffer.reserve(bytesToRead);
DWORD readBytes = 0;
BOOL sucessResult = ::ReadFile(descriptor, ptr, bytesToRead, &readBytes, NULL);
if (!sucessResult) {
readBuffer.truncate(bytesToRead);
q_ptr->setError(QSerialPort::ReadError);
return false;
}
readBuffer.truncate(readBytes);
// Process emulate policy.
if ((policy != QSerialPort::IgnorePolicy) && parityErrorOccurred) {
parityErrorOccurred = false;
switch (policy) {
case QSerialPort::SkipPolicy:
readBuffer.getChar();
return true;
case QSerialPort::PassZeroPolicy:
readBuffer.getChar();
readBuffer.putChar('\0');
break;
case QSerialPort::StopReceivingPolicy:
// FIXME: Maybe need disable read notifier?
break;
default:
break;
}
}
if (readBytes > 0)
emit q_ptr->readyRead();
return true;
}
bool QSerialPortPrivate::notifyWrite(int maxSize)
{
int nextSize = qMin(writeBuffer.nextDataBlockSize(), maxSize);
const char *ptr = writeBuffer.readPointer();
DWORD bytesWritten = 0;
if (!::WriteFile(descriptor, ptr, nextSize, &bytesWritten, NULL)) {
q_ptr->setError(QSerialPort::WriteError);
return false;
}
writeBuffer.free(bytesWritten);
if (bytesWritten > 0)
emit q_ptr->bytesWritten(bytesWritten);
return true;
}
bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectForWrite,
bool checkRead, bool checkWrite,
int msecs, bool *timedOut)
{
DWORD eventMask = 0;
// FIXME: Here the situation is not properly handled with zero timeout:
// breaker can work out before you call a method WaitCommEvent()
// and so it will loop forever!
WaitCommEventBreaker breaker(descriptor, qMax(msecs, 0));
::WaitCommEvent(descriptor, &eventMask, NULL);
breaker.stop();
if (breaker.isWorked())
*timedOut = true;
if (!breaker.isWorked()) {
if (checkRead) {
Q_ASSERT(selectForRead);
*selectForRead = eventMask & EV_RXCHAR;
}
if (checkWrite) {
Q_ASSERT(selectForWrite);
*selectForWrite = eventMask & EV_TXEMPTY;
}
return true;
}
return false;
}
bool QSerialPortPrivate::updateDcb()
{
QMutexLocker locker(&settingsChangeMutex);
DWORD eventMask = 0;
// Save the event mask
if (!::GetCommMask(descriptor, &eventMask))
return false;
// Break event notifier from WaitCommEvent
::SetCommMask(descriptor, 0);
// Change parameters
bool ret = ::SetCommState(descriptor, &currentDcb);
if (!ret)
q_ptr->setError(decodeSystemError());
// Restore the event mask
::SetCommMask(descriptor, eventMask);
return ret;
}
bool QSerialPortPrivate::updateCommTimeouts()
{
if (!::SetCommTimeouts(descriptor, &currentCommTimeouts)) {
q_ptr->setError(decodeSystemError());
return false;
}
return true;
}
static const QLatin1String defaultPathPostfix(":");
QString QSerialPortPrivate::portNameToSystemLocation(const QString &port)
{
QString ret = port;
if (!ret.contains(defaultPathPostfix))
ret.append(defaultPathPostfix);
return ret;
}
QString QSerialPortPrivate::portNameFromSystemLocation(const QString &location)
{
QString ret = location;
if (ret.contains(defaultPathPostfix))
ret.remove(defaultPathPostfix);
return ret;
}
#include "qserialport_wince.moc"
QT_END_NAMESPACE
/****************************************************************************
**
** Copyright (C) 2012 Denis Shienkov <denis.shienkov@gmail.com>
** Copyright (C) 2012 Laszlo Papp <lpapp@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSerialPort module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSERIALPORTGLOBAL_H
#define QSERIALPORTGLOBAL_H
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
#ifndef QT_STATIC
# if defined(QT_BUILD_SERIALPORT_LIB)
# define Q_SERIALPORT_EXPORT Q_DECL_EXPORT
# else
//# define Q_SERIALPORT_EXPORT Q_DECL_IMPORT
# endif
#else
# define Q_SERIALPORT_EXPORT
#endif
# define Q_SERIALPORT_EXPORT
// The macro has been available only since Qt 5.0
#ifndef Q_DECL_OVERRIDE
#define Q_DECL_OVERRIDE
#endif
QT_END_NAMESPACE
#endif // QSERIALPORTGLOBAL_H
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment