Dev...
This commit is contained in:
parent
10f3b23711
commit
a955ae9ea8
@ -1,5 +1,5 @@
|
||||
QT += Network
|
||||
|
||||
#QT += Network
|
||||
QT += gui declarative network
|
||||
|
||||
HEADERS += \
|
||||
Sources/MasterCtrl.h \
|
||||
@ -7,7 +7,9 @@ HEADERS += \
|
||||
Sources/485NetworkCommIF.h \
|
||||
Sources/EthernetNetworkCommIF.h \
|
||||
Sources/232NetworkCommIF.h \
|
||||
Sources/NetworkProtocol.h
|
||||
Sources/NetworkProtocol.h \
|
||||
Sources/AbstractNetworkInterface.h \
|
||||
Sources/DeadboltDevice.h \
|
||||
|
||||
SOURCES += \
|
||||
Sources/main.cpp \
|
||||
@ -15,7 +17,14 @@ SOURCES += \
|
||||
Sources/485NetworkCommIF.cpp \
|
||||
Sources/232NetworkCommIF.cpp \
|
||||
Sources/EthernetNetworkCommIF.cpp \
|
||||
Sources/NetworkProtocol.cpp
|
||||
Sources/NetworkProtocol.cpp \
|
||||
Sources/DeadboltDevice.cpp
|
||||
|
||||
|
||||
#win32:SOURCES += $$PWD/Source/qextserialport/win_qextserialport.cpp \
|
||||
# $$PWD/Source/qextserialport/qextserialenumerator_win.cpp
|
||||
#win32:DEFINES += _TTY_WIN_ WINVER=0x0501
|
||||
|
||||
INCLUDEPATH += $$PWD/ \
|
||||
$$PWD/Sources/
|
||||
$$PWD/Sources/ \
|
||||
$$PWD/Sources/qextserialport/
|
||||
|
||||
@ -1,5 +1,19 @@
|
||||
#include "232NetworkCommIF.h"
|
||||
|
||||
C232NetworkCommIF::C232NetworkCommIF()
|
||||
C232NetworkCommIF::C232NetworkCommIF(CAbstractNetworkCommIF *DeviceHandle)
|
||||
{
|
||||
mDeviceHandle = DeviceHandle;
|
||||
mNetworkProtocol = new CNetworkProtocol(this);
|
||||
}
|
||||
C232NetworkCommIF::~C232NetworkCommIF()
|
||||
{
|
||||
delete mNetworkProtocol;
|
||||
}
|
||||
|
||||
int C232NetworkCommIF::NewFrameReceived(QByteArray Frame)
|
||||
{
|
||||
//FWD to device...
|
||||
//Nothing to do with the data here, up it goes to the device!
|
||||
mDeviceHandle->NewFrameReceived(Frame);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1,10 +1,22 @@
|
||||
#ifndef _232NETWORKCOMMIF_H
|
||||
#define _232NETWORKCOMMIF_H
|
||||
|
||||
class C232NetworkCommIF
|
||||
#include "GlobalDefine.h"
|
||||
#include "AbstractNetworkInterface.h"
|
||||
#include "NetworkProtocol.h"
|
||||
|
||||
class C232NetworkCommIF : public CAbstractNetworkCommIF
|
||||
{
|
||||
public:
|
||||
C232NetworkCommIF();
|
||||
C232NetworkCommIF(CAbstractNetworkCommIF *DeviceHandle);
|
||||
~C232NetworkCommIF();
|
||||
|
||||
|
||||
virtual int NewFrameReceived(QByteArray Frame);
|
||||
|
||||
private:
|
||||
CNetworkProtocol *mNetworkProtocol;
|
||||
CAbstractNetworkCommIF *mDeviceHandle;
|
||||
};
|
||||
|
||||
#endif // _232NETWORKCOMMIF_H
|
||||
|
||||
10
Sources/AbstractNetworkInterface.h
Normal file
10
Sources/AbstractNetworkInterface.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef ABSTRACTNETWORKINTERFACE_H
|
||||
#define ABSTRACTNETWORKINTERFACE_H
|
||||
#include <QByteArray>
|
||||
|
||||
class CAbstractNetworkCommIF
|
||||
{
|
||||
public:
|
||||
virtual int NewFrameReceived(QByteArray Frame) = 0;
|
||||
};
|
||||
#endif // ABSTRACTNETWORKINTERFACE_H
|
||||
16
Sources/DeadboltDevice.cpp
Normal file
16
Sources/DeadboltDevice.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "DeadboltDevice.h"
|
||||
|
||||
CDeadboltDevice::CDeadboltDevice()
|
||||
{
|
||||
mNetworkCommInterface = new C232NetworkCommIF(this);
|
||||
}
|
||||
|
||||
CDeadboltDevice::~CDeadboltDevice()
|
||||
{
|
||||
delete mNetworkCommInterface;
|
||||
}
|
||||
|
||||
int CDeadboltDevice::NewFrameReceived(QByteArray Frame)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
20
Sources/DeadboltDevice.h
Normal file
20
Sources/DeadboltDevice.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef DEADBOLTDEVICE_H
|
||||
#define DEADBOLTDEVICE_H
|
||||
|
||||
#include "GlobalDefine.h"
|
||||
#include "232NetworkCommIF.h"
|
||||
//#include "AbstractNetworkInterface.h"
|
||||
|
||||
|
||||
class CDeadboltDevice: public CAbstractNetworkCommIF
|
||||
{
|
||||
public:
|
||||
CDeadboltDevice();
|
||||
~CDeadboltDevice();
|
||||
virtual int NewFrameReceived(QByteArray Frame);
|
||||
|
||||
|
||||
C232NetworkCommIF *mNetworkCommInterface;
|
||||
};
|
||||
|
||||
#endif // DEADBOLTDEVICE_H
|
||||
@ -3,8 +3,13 @@
|
||||
CMasterCtrl::CMasterCtrl()
|
||||
{
|
||||
qDebug("Creation...");
|
||||
mDeadBoltDevice = new CDeadboltDevice;
|
||||
}
|
||||
|
||||
CMasterCtrl::~CMasterCtrl()
|
||||
{
|
||||
delete mDeadBoltDevice;
|
||||
}
|
||||
void CMasterCtrl::Start()
|
||||
{
|
||||
qDebug("Started!");
|
||||
|
||||
@ -2,13 +2,16 @@
|
||||
#define MASTERCTRL_H
|
||||
|
||||
#include "GlobalDefine.h"
|
||||
#include "DeadboltDevice.h"
|
||||
|
||||
class CMasterCtrl
|
||||
{
|
||||
public:
|
||||
CMasterCtrl();
|
||||
~CMasterCtrl();
|
||||
|
||||
void Start(void);
|
||||
CDeadboltDevice *mDeadBoltDevice;
|
||||
};
|
||||
|
||||
#endif // MASTERCTRL_H
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
|
||||
|
||||
#include "NetworkProtocol.h"
|
||||
#include "QByteArray"
|
||||
|
||||
|
||||
|
||||
CNetworkProtocol::CNetworkProtocol()
|
||||
CNetworkProtocol::CNetworkProtocol(CAbstractNetworkCommIF *Parent)
|
||||
{
|
||||
mParentHandle = Parent;
|
||||
ResetRxStateMachine();
|
||||
|
||||
}
|
||||
@ -32,42 +33,75 @@ unsigned char CNetworkProtocol::CalcCRC(char *Buffer, int Size)
|
||||
return CRC;
|
||||
}
|
||||
|
||||
|
||||
int CNetworkProtocol::TxData(unsigned char MessageID,unsigned char Flags,unsigned char *Data,int Size, unsigned char Address,unsigned char ID)
|
||||
QByteArray CNetworkProtocol::GetTxPacket(unsigned char MessageID, unsigned char Flags, unsigned char *Data, int Size, unsigned char Address, unsigned char ID)
|
||||
{
|
||||
|
||||
int toto;
|
||||
char temp;
|
||||
int toto;
|
||||
char temp;
|
||||
char OutBuffer[MAX_MESSAGE_SIZE+10];
|
||||
|
||||
int FrameSize = Size + 9; //Add header data...
|
||||
int FrameSize = Size + 9; //Add header data...
|
||||
|
||||
OutBuffer[0] = (char)FRAME_HEADER; //header
|
||||
OutBuffer[1] = 1; //PC address
|
||||
OutBuffer[2] = ID_PC; //PC ID
|
||||
OutBuffer[3] = (char)ID; //destination ID
|
||||
OutBuffer[4] = (char)Address; //Destination Address
|
||||
OutBuffer[5] = (char)Flags;
|
||||
OutBuffer[6] = (char)MessageID; //Cmd
|
||||
toto = FrameSize & 0xFF00;
|
||||
temp = FrameSize >> 8;
|
||||
OutBuffer[0] = (char)FRAME_HEADER; //header
|
||||
OutBuffer[1] = 1; //MasterCtrl address
|
||||
OutBuffer[2] = ID_MASTER; //MasterCtrl ID
|
||||
OutBuffer[3] = (char)ID; //destination ID
|
||||
OutBuffer[4] = (char)Address; //Destination Address
|
||||
OutBuffer[5] = (char)Flags;
|
||||
OutBuffer[6] = (char)MessageID; //Cmd
|
||||
toto = FrameSize & 0xFF00;
|
||||
temp = FrameSize >> 8;
|
||||
OutBuffer[7] = ((FrameSize - 9) & 0xFF00) >> 8;
|
||||
OutBuffer[8] = (FrameSize - 9) & 0x00FF;
|
||||
|
||||
for(int i = 0; i < Size; i++)
|
||||
{
|
||||
temp = Data[i];
|
||||
OutBuffer[i+9] = temp;
|
||||
}
|
||||
for(int i = 0; i < Size; i++)
|
||||
{
|
||||
temp = Data[i];
|
||||
OutBuffer[i+9] = temp;
|
||||
}
|
||||
|
||||
OutBuffer[FrameSize] = CalcCRC(OutBuffer,FrameSize);
|
||||
OutBuffer[FrameSize] = CalcCRC(OutBuffer,FrameSize);
|
||||
|
||||
|
||||
// CSerialComm::instance()->WriteData(&OutBuffer[0],FrameSize+1);
|
||||
|
||||
return 0;
|
||||
return QByteArray(OutBuffer,FrameSize);
|
||||
}
|
||||
|
||||
//int CNetworkProtocol::TxData(unsigned char MessageID,unsigned char Flags,unsigned char *Data,int Size, unsigned char Address,unsigned char ID)
|
||||
//{
|
||||
|
||||
// int toto;
|
||||
// char temp;
|
||||
// char OutBuffer[MAX_MESSAGE_SIZE+10];
|
||||
|
||||
// int FrameSize = Size + 9; //Add header data...
|
||||
|
||||
// OutBuffer[0] = (char)FRAME_HEADER; //header
|
||||
// OutBuffer[1] = 1; //MasterCtrl address
|
||||
// OutBuffer[2] = ID_MASTER; //MasterCtrl ID
|
||||
// OutBuffer[3] = (char)ID; //destination ID
|
||||
// OutBuffer[4] = (char)Address; //Destination Address
|
||||
// OutBuffer[5] = (char)Flags;
|
||||
// OutBuffer[6] = (char)MessageID; //Cmd
|
||||
// toto = FrameSize & 0xFF00;
|
||||
// temp = FrameSize >> 8;
|
||||
// OutBuffer[7] = ((FrameSize - 9) & 0xFF00) >> 8;
|
||||
// OutBuffer[8] = (FrameSize - 9) & 0x00FF;
|
||||
|
||||
// for(int i = 0; i < Size; i++)
|
||||
// {
|
||||
// temp = Data[i];
|
||||
// OutBuffer[i+9] = temp;
|
||||
// }
|
||||
|
||||
// OutBuffer[FrameSize] = CalcCRC(OutBuffer,FrameSize);
|
||||
|
||||
|
||||
//// CSerialComm::instance()->WriteData(&OutBuffer[0],FrameSize+1);
|
||||
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
//void CNetworkProtocol::ReadPort(void)
|
||||
//{
|
||||
// int Size = 0;
|
||||
@ -218,6 +252,7 @@ void CNetworkProtocol::RxStateMachine(unsigned char Data)
|
||||
|
||||
//Data is OK... execute
|
||||
// ExecuteCommand();
|
||||
mParentHandle->NewFrameReceived(QByteArray(mRxData,RxSize+10));
|
||||
ResetRxStateMachine();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3,17 +3,21 @@
|
||||
|
||||
#include "GlobalDefine.h"
|
||||
#include "ProtocolDefs.h"
|
||||
#include "AbstractNetworkInterface.h"
|
||||
|
||||
class CNetworkProtocol
|
||||
{
|
||||
public:
|
||||
CNetworkProtocol();
|
||||
CNetworkProtocol(CAbstractNetworkCommIF *Parent);
|
||||
~CNetworkProtocol();
|
||||
CAbstractNetworkCommIF *mParentHandle;
|
||||
QByteArray GetTxPacket(unsigned char MessageID,unsigned char Flags,unsigned char *Data,int Size, unsigned char Address,unsigned char ID);
|
||||
|
||||
private:
|
||||
void ResetRxStateMachine();
|
||||
unsigned char CalcCRC(char *Buffer, int Size);
|
||||
int TxData(unsigned char MessageID,unsigned char Flags,unsigned char *Data,int Size, unsigned char Address,unsigned char ID);
|
||||
// int TxData(unsigned char MessageID,unsigned char Flags,unsigned char *Data,int Size, unsigned char Address,unsigned char ID);
|
||||
|
||||
void RxStateMachine(unsigned char Data);
|
||||
|
||||
//State Machine states
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication::setGraphicsSystem("raster");
|
||||
//QApplication::setGraphicsSystem("raster");
|
||||
//Qt Mainframe application instance.
|
||||
QApplication a(argc, argv);
|
||||
|
||||
|
||||
254
Sources/qextserialport/qextserialport.cpp
Normal file
254
Sources/qextserialport/qextserialport.cpp
Normal file
@ -0,0 +1,254 @@
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "qextserialport.h"
|
||||
|
||||
/*!
|
||||
Default constructor. Note that the name of the device used by a QextSerialPort constructed with
|
||||
this constructor will be determined by #defined constants, or lack thereof - the default behavior
|
||||
is the same as _TTY_LINUX_. Possible naming conventions and their associated constants are:
|
||||
|
||||
\verbatim
|
||||
|
||||
Constant Used By Naming Convention
|
||||
---------- ------------- ------------------------
|
||||
Q_OS_WIN Windows COM1, COM2
|
||||
_TTY_IRIX_ SGI/IRIX /dev/ttyf1, /dev/ttyf2
|
||||
_TTY_HPUX_ HP-UX /dev/tty1p0, /dev/tty2p0
|
||||
_TTY_SUN_ SunOS/Solaris /dev/ttya, /dev/ttyb
|
||||
_TTY_DIGITAL_ Digital UNIX /dev/tty01, /dev/tty02
|
||||
_TTY_FREEBSD_ FreeBSD /dev/ttyd0, /dev/ttyd1
|
||||
_TTY_OPENBSD_ OpenBSD /dev/tty00, /dev/tty01
|
||||
_TTY_LINUX_ Linux /dev/ttyS0, /dev/ttyS1
|
||||
<none> Linux /dev/ttyS0, /dev/ttyS1
|
||||
\endverbatim
|
||||
|
||||
This constructor assigns the device name to the name of the first port on the specified system.
|
||||
See the other constructors if you need to open a different port.
|
||||
*/
|
||||
QextSerialPort::QextSerialPort(QextSerialPort::QueryMode mode)
|
||||
: QIODevice()
|
||||
{
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
setPortName("COM1");
|
||||
|
||||
#elif defined(_TTY_IRIX_)
|
||||
setPortName("/dev/ttyf1");
|
||||
|
||||
#elif defined(_TTY_HPUX_)
|
||||
setPortName("/dev/tty1p0");
|
||||
|
||||
#elif defined(_TTY_SUN_)
|
||||
setPortName("/dev/ttya");
|
||||
|
||||
#elif defined(_TTY_DIGITAL_)
|
||||
setPortName("/dev/tty01");
|
||||
|
||||
#elif defined(_TTY_FREEBSD_)
|
||||
setPortName("/dev/ttyd1");
|
||||
|
||||
#elif defined(_TTY_OPENBSD_)
|
||||
setPortName("/dev/tty00");
|
||||
|
||||
#else
|
||||
setPortName("/dev/ttyS0");
|
||||
#endif
|
||||
|
||||
construct();
|
||||
setQueryMode(mode);
|
||||
platformSpecificInit();
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a serial port attached to the port specified by name.
|
||||
name is the name of the device, which is windowsystem-specific,
|
||||
e.g."COM1" or "/dev/ttyS0".
|
||||
*/
|
||||
QextSerialPort::QextSerialPort(const QString & name, QextSerialPort::QueryMode mode)
|
||||
: QIODevice()
|
||||
{
|
||||
construct();
|
||||
setQueryMode(mode);
|
||||
setPortName(name);
|
||||
platformSpecificInit();
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a port with default name and specified settings.
|
||||
*/
|
||||
QextSerialPort::QextSerialPort(const PortSettings& settings, QextSerialPort::QueryMode mode)
|
||||
: QIODevice()
|
||||
{
|
||||
construct();
|
||||
setBaudRate(settings.BaudRate);
|
||||
setDataBits(settings.DataBits);
|
||||
setParity(settings.Parity);
|
||||
setStopBits(settings.StopBits);
|
||||
setFlowControl(settings.FlowControl);
|
||||
setTimeout(settings.Timeout_Millisec);
|
||||
setQueryMode(mode);
|
||||
platformSpecificInit();
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a port with specified name and settings.
|
||||
*/
|
||||
QextSerialPort::QextSerialPort(const QString & name, const PortSettings& settings, QextSerialPort::QueryMode mode)
|
||||
: QIODevice()
|
||||
{
|
||||
construct();
|
||||
setPortName(name);
|
||||
setBaudRate(settings.BaudRate);
|
||||
setDataBits(settings.DataBits);
|
||||
setParity(settings.Parity);
|
||||
setStopBits(settings.StopBits);
|
||||
setFlowControl(settings.FlowControl);
|
||||
setTimeout(settings.Timeout_Millisec);
|
||||
setQueryMode(mode);
|
||||
platformSpecificInit();
|
||||
}
|
||||
|
||||
/*!
|
||||
Common constructor function for setting up default port settings.
|
||||
(115200 Baud, 8N1, Hardware flow control where supported, otherwise no flow control, and 0 ms timeout).
|
||||
*/
|
||||
void QextSerialPort::construct()
|
||||
{
|
||||
lastErr = E_NO_ERROR;
|
||||
Settings.BaudRate=BAUD115200;
|
||||
Settings.DataBits=DATA_8;
|
||||
Settings.Parity=PAR_NONE;
|
||||
Settings.StopBits=STOP_1;
|
||||
Settings.FlowControl=FLOW_HARDWARE;
|
||||
Settings.Timeout_Millisec=500;
|
||||
mutex = new QMutex( QMutex::Recursive );
|
||||
setOpenMode(QIODevice::NotOpen);
|
||||
}
|
||||
|
||||
void QextSerialPort::setQueryMode(QueryMode mechanism)
|
||||
{
|
||||
_queryMode = mechanism;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the name of the device associated with the object, e.g. "COM1", or "/dev/ttyS0".
|
||||
*/
|
||||
void QextSerialPort::setPortName(const QString & name)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
port = fullPortNameWin( name );
|
||||
#else
|
||||
port = name;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the name set by setPortName().
|
||||
*/
|
||||
QString QextSerialPort::portName() const
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
/*!
|
||||
Reads all available data from the device, and returns it as a QByteArray.
|
||||
This function has no way of reporting errors; returning an empty QByteArray()
|
||||
can mean either that no data was currently available for reading, or that an error occurred.
|
||||
*/
|
||||
QByteArray QextSerialPort::readAll()
|
||||
{
|
||||
int avail = this->bytesAvailable();
|
||||
return (avail > 0) ? this->read(avail) : QByteArray();
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the baud rate of the serial port. For a list of possible return values see
|
||||
the definition of the enum BaudRateType.
|
||||
*/
|
||||
BaudRateType QextSerialPort::baudRate(void) const
|
||||
{
|
||||
return Settings.BaudRate;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of data bits used by the port. For a list of possible values returned by
|
||||
this function, see the definition of the enum DataBitsType.
|
||||
*/
|
||||
DataBitsType QextSerialPort::dataBits() const
|
||||
{
|
||||
return Settings.DataBits;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the type of parity used by the port. For a list of possible values returned by
|
||||
this function, see the definition of the enum ParityType.
|
||||
*/
|
||||
ParityType QextSerialPort::parity() const
|
||||
{
|
||||
return Settings.Parity;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of stop bits used by the port. For a list of possible return values, see
|
||||
the definition of the enum StopBitsType.
|
||||
*/
|
||||
StopBitsType QextSerialPort::stopBits() const
|
||||
{
|
||||
return Settings.StopBits;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the type of flow control used by the port. For a list of possible values returned
|
||||
by this function, see the definition of the enum FlowType.
|
||||
*/
|
||||
FlowType QextSerialPort::flowControl() const
|
||||
{
|
||||
return Settings.FlowControl;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if device is sequential, otherwise returns false. Serial port is sequential device
|
||||
so this function always returns true. Check QIODevice::isSequential() documentation for more
|
||||
information.
|
||||
*/
|
||||
bool QextSerialPort::isSequential() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QString QextSerialPort::errorString()
|
||||
{
|
||||
switch(lastErr)
|
||||
{
|
||||
case E_NO_ERROR: return "No Error has occurred";
|
||||
case E_INVALID_FD: return "Invalid file descriptor (port was not opened correctly)";
|
||||
case E_NO_MEMORY: return "Unable to allocate memory tables (POSIX)";
|
||||
case E_CAUGHT_NON_BLOCKED_SIGNAL: return "Caught a non-blocked signal (POSIX)";
|
||||
case E_PORT_TIMEOUT: return "Operation timed out (POSIX)";
|
||||
case E_INVALID_DEVICE: return "The file opened by the port is not a valid device";
|
||||
case E_BREAK_CONDITION: return "The port detected a break condition";
|
||||
case E_FRAMING_ERROR: return "The port detected a framing error (usually caused by incorrect baud rate settings)";
|
||||
case E_IO_ERROR: return "There was an I/O error while communicating with the port";
|
||||
case E_BUFFER_OVERRUN: return "Character buffer overrun";
|
||||
case E_RECEIVE_OVERFLOW: return "Receive buffer overflow";
|
||||
case E_RECEIVE_PARITY_ERROR: return "The port detected a parity error in the received data";
|
||||
case E_TRANSMIT_OVERFLOW: return "Transmit buffer overflow";
|
||||
case E_READ_FAILED: return "General read operation failure";
|
||||
case E_WRITE_FAILED: return "General write operation failure";
|
||||
case E_FILE_NOT_FOUND: return "The "+this->portName()+" file doesn't exists";
|
||||
default: return QString("Unknown error: %1").arg(lastErr);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Standard destructor.
|
||||
*/
|
||||
QextSerialPort::~QextSerialPort()
|
||||
{
|
||||
if (isOpen()) {
|
||||
close();
|
||||
}
|
||||
platformSpecificDestruct();
|
||||
delete mutex;
|
||||
}
|
||||
333
Sources/qextserialport/qextserialport.h
Normal file
333
Sources/qextserialport/qextserialport.h
Normal file
@ -0,0 +1,333 @@
|
||||
|
||||
#ifndef _QEXTSERIALPORT_H_
|
||||
#define _QEXTSERIALPORT_H_
|
||||
|
||||
#include "qextserialport_global.h"
|
||||
|
||||
/*if all warning messages are turned off, flag portability warnings to be turned off as well*/
|
||||
#ifdef _TTY_NOWARN_
|
||||
#define _TTY_NOWARN_PORT_
|
||||
#endif
|
||||
|
||||
/*macros for warning and debug messages*/
|
||||
#ifdef _TTY_NOWARN_PORT_
|
||||
#define TTY_PORTABILITY_WARNING(s)
|
||||
#else
|
||||
#define TTY_PORTABILITY_WARNING(s) qWarning(s)
|
||||
#endif /*_TTY_NOWARN_PORT_*/
|
||||
#ifdef _TTY_NOWARN_
|
||||
#define TTY_WARNING(s)
|
||||
#else
|
||||
#define TTY_WARNING(s) qWarning(s)
|
||||
#endif /*_TTY_NOWARN_*/
|
||||
|
||||
|
||||
/*line status constants*/
|
||||
#define LS_CTS 0x01
|
||||
#define LS_DSR 0x02
|
||||
#define LS_DCD 0x04
|
||||
#define LS_RI 0x08
|
||||
#define LS_RTS 0x10
|
||||
#define LS_DTR 0x20
|
||||
#define LS_ST 0x40
|
||||
#define LS_SR 0x80
|
||||
|
||||
/*error constants*/
|
||||
#define E_NO_ERROR 0
|
||||
#define E_INVALID_FD 1
|
||||
#define E_NO_MEMORY 2
|
||||
#define E_CAUGHT_NON_BLOCKED_SIGNAL 3
|
||||
#define E_PORT_TIMEOUT 4
|
||||
#define E_INVALID_DEVICE 5
|
||||
#define E_BREAK_CONDITION 6
|
||||
#define E_FRAMING_ERROR 7
|
||||
#define E_IO_ERROR 8
|
||||
#define E_BUFFER_OVERRUN 9
|
||||
#define E_RECEIVE_OVERFLOW 10
|
||||
#define E_RECEIVE_PARITY_ERROR 11
|
||||
#define E_TRANSMIT_OVERFLOW 12
|
||||
#define E_READ_FAILED 13
|
||||
#define E_WRITE_FAILED 14
|
||||
#define E_FILE_NOT_FOUND 15
|
||||
|
||||
enum BaudRateType
|
||||
{
|
||||
BAUD50, //POSIX ONLY
|
||||
BAUD75, //POSIX ONLY
|
||||
BAUD110,
|
||||
BAUD134, //POSIX ONLY
|
||||
BAUD150, //POSIX ONLY
|
||||
BAUD200, //POSIX ONLY
|
||||
BAUD300,
|
||||
BAUD600,
|
||||
BAUD1200,
|
||||
BAUD1800, //POSIX ONLY
|
||||
BAUD2400,
|
||||
BAUD4800,
|
||||
BAUD9600,
|
||||
BAUD14400, //WINDOWS ONLY
|
||||
BAUD19200,
|
||||
BAUD38400,
|
||||
BAUD56000, //WINDOWS ONLY
|
||||
BAUD57600,
|
||||
BAUD76800, //POSIX ONLY
|
||||
BAUD115200,
|
||||
BAUD128000, //WINDOWS ONLY
|
||||
BAUD256000 //WINDOWS ONLY
|
||||
};
|
||||
|
||||
enum DataBitsType
|
||||
{
|
||||
DATA_5,
|
||||
DATA_6,
|
||||
DATA_7,
|
||||
DATA_8
|
||||
};
|
||||
|
||||
enum ParityType
|
||||
{
|
||||
PAR_NONE,
|
||||
PAR_ODD,
|
||||
PAR_EVEN,
|
||||
PAR_MARK, //WINDOWS ONLY
|
||||
PAR_SPACE
|
||||
};
|
||||
|
||||
enum StopBitsType
|
||||
{
|
||||
STOP_1,
|
||||
STOP_1_5, //WINDOWS ONLY
|
||||
STOP_2
|
||||
};
|
||||
|
||||
enum FlowType
|
||||
{
|
||||
FLOW_OFF,
|
||||
FLOW_HARDWARE,
|
||||
FLOW_XONXOFF
|
||||
};
|
||||
|
||||
/**
|
||||
* structure to contain port settings
|
||||
*/
|
||||
struct PortSettings
|
||||
{
|
||||
BaudRateType BaudRate;
|
||||
DataBitsType DataBits;
|
||||
ParityType Parity;
|
||||
StopBitsType StopBits;
|
||||
FlowType FlowControl;
|
||||
long Timeout_Millisec;
|
||||
};
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QMutex>
|
||||
#ifdef Q_OS_UNIX
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <QSocketNotifier>
|
||||
#elif (defined Q_OS_WIN)
|
||||
#include <windows.h>
|
||||
#include <QThread>
|
||||
#include <QReadWriteLock>
|
||||
#include <qwineventnotifier_p.h>
|
||||
#endif
|
||||
|
||||
/*!
|
||||
Encapsulates a serial port on both POSIX and Windows systems.
|
||||
|
||||
\note
|
||||
Be sure to check the full list of members, as QIODevice provides quite a lot of
|
||||
functionality for QextSerialPort.
|
||||
|
||||
\section Usage
|
||||
QextSerialPort offers both a polling and event driven API. Event driven is typically easier
|
||||
to use, since you never have to worry about checking for new data.
|
||||
|
||||
\b Example
|
||||
\code
|
||||
QextSerialPort* port = new QextSerialPort("COM1", QextSerialPort::EventDriven);
|
||||
connect(port, SIGNAL(readyRead()), myClass, SLOT(onDataAvailable()));
|
||||
port->open();
|
||||
|
||||
void MyClass::onDataAvailable() {
|
||||
int avail = port->bytesAvailable();
|
||||
if( avail > 0 ) {
|
||||
QByteArray usbdata;
|
||||
usbdata.resize(avail);
|
||||
int read = port->read(usbdata.data(), usbdata.size());
|
||||
if( read > 0 ) {
|
||||
processNewData(usbdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
\endcode
|
||||
|
||||
\section Compatibility
|
||||
The user will be notified of errors and possible portability conflicts at run-time
|
||||
by default - this behavior can be turned off by defining _TTY_NOWARN_
|
||||
(to turn off all warnings) or _TTY_NOWARN_PORT_ (to turn off portability warnings) in the project.
|
||||
|
||||
On Windows NT/2000/XP this class uses Win32 serial port functions by default. The user may
|
||||
select POSIX behavior under NT, 2000, or XP ONLY by defining Q_OS_UNIX in the project.
|
||||
No guarantees are made as to the quality of POSIX support under NT/2000 however.
|
||||
|
||||
\author Stefan Sander, Michal Policht, Brandon Fosdick, Liam Staskawicz
|
||||
*/
|
||||
class QEXTSERIALPORT_EXPORT QextSerialPort: public QIODevice
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum QueryMode {
|
||||
Polling,
|
||||
EventDriven
|
||||
};
|
||||
|
||||
QextSerialPort(QueryMode mode = EventDriven);
|
||||
QextSerialPort(const QString & name, QueryMode mode = EventDriven);
|
||||
QextSerialPort(PortSettings const& s, QueryMode mode = EventDriven);
|
||||
QextSerialPort(const QString & name, PortSettings const& s, QueryMode mode = EventDriven);
|
||||
~QextSerialPort();
|
||||
|
||||
void setPortName(const QString & name);
|
||||
QString portName() const;
|
||||
|
||||
/**!
|
||||
* Get query mode.
|
||||
* \return query mode.
|
||||
*/
|
||||
inline QueryMode queryMode() const { return _queryMode; }
|
||||
|
||||
/*!
|
||||
* Set desired serial communication handling style. You may choose from polling
|
||||
* or event driven approach. This function does nothing when port is open; to
|
||||
* apply changes port must be reopened.
|
||||
*
|
||||
* In event driven approach read() and write() functions are acting
|
||||
* asynchronously. They return immediately and the operation is performed in
|
||||
* the background, so they doesn't freeze the calling thread.
|
||||
* To determine when operation is finished, QextSerialPort runs separate thread
|
||||
* and monitors serial port events. Whenever the event occurs, adequate signal
|
||||
* is emitted.
|
||||
*
|
||||
* When polling is set, read() and write() are acting synchronously. Signals are
|
||||
* not working in this mode and some functions may not be available. The advantage
|
||||
* of polling is that it generates less overhead due to lack of signals emissions
|
||||
* and it doesn't start separate thread to monitor events.
|
||||
*
|
||||
* Generally event driven approach is more capable and friendly, although some
|
||||
* applications may need as low overhead as possible and then polling comes.
|
||||
*
|
||||
* \param mode query mode.
|
||||
*/
|
||||
void setQueryMode(QueryMode mode);
|
||||
|
||||
void setBaudRate(BaudRateType);
|
||||
BaudRateType baudRate() const;
|
||||
|
||||
void setDataBits(DataBitsType);
|
||||
DataBitsType dataBits() const;
|
||||
|
||||
void setParity(ParityType);
|
||||
ParityType parity() const;
|
||||
|
||||
void setStopBits(StopBitsType);
|
||||
StopBitsType stopBits() const;
|
||||
|
||||
void setFlowControl(FlowType);
|
||||
FlowType flowControl() const;
|
||||
|
||||
void setTimeout(long);
|
||||
|
||||
bool open(OpenMode mode);
|
||||
bool isSequential() const;
|
||||
void close();
|
||||
void flush();
|
||||
|
||||
qint64 size() const;
|
||||
qint64 bytesAvailable() const;
|
||||
QByteArray readAll();
|
||||
|
||||
void ungetChar(char c);
|
||||
|
||||
ulong lastError() const;
|
||||
void translateError(ulong error);
|
||||
|
||||
void setDtr(bool set=true);
|
||||
void setRts(bool set=true);
|
||||
ulong lineStatus();
|
||||
QString errorString();
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
virtual bool waitForReadyRead(int msecs); ///< @todo implement.
|
||||
virtual qint64 bytesToWrite() const;
|
||||
static QString fullPortNameWin(const QString & name);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
QMutex* mutex;
|
||||
QString port;
|
||||
PortSettings Settings;
|
||||
ulong lastErr;
|
||||
QueryMode _queryMode;
|
||||
|
||||
// platform specific members
|
||||
#ifdef Q_OS_UNIX
|
||||
int fd;
|
||||
QSocketNotifier *readNotifier;
|
||||
struct termios Posix_CommConfig;
|
||||
struct termios old_termios;
|
||||
struct timeval Posix_Timeout;
|
||||
struct timeval Posix_Copy_Timeout;
|
||||
#elif (defined Q_OS_WIN)
|
||||
HANDLE Win_Handle;
|
||||
OVERLAPPED overlap;
|
||||
COMMCONFIG Win_CommConfig;
|
||||
COMMTIMEOUTS Win_CommTimeouts;
|
||||
QWinEventNotifier *winEventNotifier;
|
||||
DWORD eventMask;
|
||||
QList<OVERLAPPED*> pendingWrites;
|
||||
QReadWriteLock* bytesToWriteLock;
|
||||
qint64 _bytesToWrite;
|
||||
#endif
|
||||
|
||||
void construct(); // common construction
|
||||
void platformSpecificDestruct();
|
||||
void platformSpecificInit();
|
||||
qint64 readData(char * data, qint64 maxSize);
|
||||
qint64 writeData(const char * data, qint64 maxSize);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
private slots:
|
||||
void onWinEvent(HANDLE h);
|
||||
#endif
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QextSerialPort)
|
||||
|
||||
signals:
|
||||
// /**
|
||||
// * This signal is emitted whenever port settings are updated.
|
||||
// * \param valid \p true if settings are valid, \p false otherwise.
|
||||
// *
|
||||
// * @todo implement.
|
||||
// */
|
||||
// // void validSettings(bool valid);
|
||||
|
||||
/*!
|
||||
* This signal is emitted whenever dsr line has changed its state. You may
|
||||
* use this signal to check if device is connected.
|
||||
* \param status \p true when DSR signal is on, \p false otherwise.
|
||||
*
|
||||
* \see lineStatus().
|
||||
*/
|
||||
void dsrChanged(bool status);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
18
Sources/qextserialport/qextserialport_global.h
Normal file
18
Sources/qextserialport/qextserialport_global.h
Normal file
@ -0,0 +1,18 @@
|
||||
|
||||
|
||||
#ifndef QEXTSERIALPORT_GLOBAL_H
|
||||
#define QEXTSERIALPORT_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifdef QEXTSERIALPORT_LIB
|
||||
# define QEXTSERIALPORT_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define QEXTSERIALPORT_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#undef QEXTSERIALPORT_EXPORT
|
||||
#define QEXTSERIALPORT_EXPORT
|
||||
|
||||
#endif // QEXTSERIALPORT_GLOBAL_H
|
||||
|
||||
94
Sources/qextserialport/qwineventnotifier_p.h
Normal file
94
Sources/qextserialport/qwineventnotifier_p.h
Normal file
@ -0,0 +1,94 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial Usage
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia 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.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QWINEVENTNOTIFIER_P_H
|
||||
#define QWINEVENTNOTIFIER_P_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
// -------------
|
||||
//
|
||||
// This file is not part of the Qt API. It exists for the convenience
|
||||
// of other Qt classes. This header file may change from version to
|
||||
// version without notice, or even be removed.
|
||||
//
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include "QtCore/qobject.h"
|
||||
#include "QtCore/qt_windows.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Q_CORE_EXPORT QWinEventNotifier : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DECLARE_PRIVATE(QObject)
|
||||
|
||||
public:
|
||||
explicit QWinEventNotifier(QObject *parent = 0);
|
||||
explicit QWinEventNotifier(HANDLE hEvent, QObject *parent = 0);
|
||||
~QWinEventNotifier();
|
||||
|
||||
void setHandle(HANDLE hEvent);
|
||||
HANDLE handle() const;
|
||||
|
||||
bool isEnabled() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setEnabled(bool enable);
|
||||
|
||||
Q_SIGNALS:
|
||||
void activated(HANDLE hEvent);
|
||||
|
||||
protected:
|
||||
bool event(QEvent * e);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QWinEventNotifier)
|
||||
|
||||
HANDLE handleToEvent;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QWINEVENTNOTIFIER_P_H
|
||||
868
Sources/qextserialport/win_qextserialport.cpp
Normal file
868
Sources/qextserialport/win_qextserialport.cpp
Normal file
@ -0,0 +1,868 @@
|
||||
|
||||
|
||||
#include <QMutexLocker>
|
||||
#include <QDebug>
|
||||
#include <QRegExp>
|
||||
#include "qextserialport.h"
|
||||
|
||||
void QextSerialPort::platformSpecificInit()
|
||||
{
|
||||
Win_Handle=INVALID_HANDLE_VALUE;
|
||||
ZeroMemory(&overlap, sizeof(OVERLAPPED));
|
||||
overlap.hEvent = CreateEvent(NULL, true, false, NULL);
|
||||
winEventNotifier = 0;
|
||||
bytesToWriteLock = new QReadWriteLock;
|
||||
_bytesToWrite = 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Standard destructor.
|
||||
*/
|
||||
void QextSerialPort::platformSpecificDestruct() {
|
||||
CloseHandle(overlap.hEvent);
|
||||
delete bytesToWriteLock;
|
||||
}
|
||||
|
||||
QString QextSerialPort::fullPortNameWin(const QString & name)
|
||||
{
|
||||
QRegExp rx("^COM(\\d+)");
|
||||
QString fullName(name);
|
||||
if(fullName.contains(rx)) {
|
||||
int portnum = rx.cap(1).toInt();
|
||||
if(portnum > 9) // COM ports greater than 9 need \\.\ prepended
|
||||
fullName.prepend("\\\\.\\");
|
||||
}
|
||||
return fullName;
|
||||
}
|
||||
|
||||
/*!
|
||||
Opens a serial port. Note that this function does not specify which device to open. If you need
|
||||
to open a device by name, see QextSerialPort::open(const char*). This function has no effect
|
||||
if the port associated with the class is already open. The port is also configured to the current
|
||||
settings, as stored in the Settings structure.
|
||||
*/
|
||||
bool QextSerialPort::open(OpenMode mode) {
|
||||
unsigned long confSize = sizeof(COMMCONFIG);
|
||||
Win_CommConfig.dwSize = confSize;
|
||||
DWORD dwFlagsAndAttributes = 0;
|
||||
if (queryMode() == QextSerialPort::EventDriven)
|
||||
dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED;
|
||||
|
||||
QMutexLocker lock(mutex);
|
||||
if (mode == QIODevice::NotOpen)
|
||||
return isOpen();
|
||||
if (!isOpen()) {
|
||||
/*open the port*/
|
||||
Win_Handle=CreateFileA(port.toAscii(), GENERIC_READ|GENERIC_WRITE,
|
||||
0, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);
|
||||
if (Win_Handle!=INVALID_HANDLE_VALUE) {
|
||||
QIODevice::open(mode);
|
||||
/*configure port settings*/
|
||||
GetCommConfig(Win_Handle, &Win_CommConfig, &confSize);
|
||||
GetCommState(Win_Handle, &(Win_CommConfig.dcb));
|
||||
|
||||
/*set up parameters*/
|
||||
Win_CommConfig.dcb.fBinary=TRUE;
|
||||
Win_CommConfig.dcb.fInX=FALSE;
|
||||
Win_CommConfig.dcb.fOutX=FALSE;
|
||||
Win_CommConfig.dcb.fAbortOnError=FALSE;
|
||||
Win_CommConfig.dcb.fNull=FALSE;
|
||||
setBaudRate(Settings.BaudRate);
|
||||
setDataBits(Settings.DataBits);
|
||||
setStopBits(Settings.StopBits);
|
||||
setParity(Settings.Parity);
|
||||
setFlowControl(Settings.FlowControl);
|
||||
setTimeout(Settings.Timeout_Millisec);
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
|
||||
//init event driven approach
|
||||
if (queryMode() == QextSerialPort::EventDriven) {
|
||||
Win_CommTimeouts.ReadIntervalTimeout = MAXDWORD;
|
||||
Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
Win_CommTimeouts.ReadTotalTimeoutConstant = 0;
|
||||
Win_CommTimeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
Win_CommTimeouts.WriteTotalTimeoutConstant = 0;
|
||||
SetCommTimeouts(Win_Handle, &Win_CommTimeouts);
|
||||
if (!SetCommMask( Win_Handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) {
|
||||
qWarning() << "failed to set Comm Mask. Error code:", GetLastError();
|
||||
return false;
|
||||
}
|
||||
winEventNotifier = new QWinEventNotifier(overlap.hEvent, this);
|
||||
connect(winEventNotifier, SIGNAL(activated(HANDLE)), this, SLOT(onWinEvent(HANDLE)));
|
||||
WaitCommEvent(Win_Handle, &eventMask, &overlap);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return isOpen();
|
||||
}
|
||||
|
||||
/*!
|
||||
Closes a serial port. This function has no effect if the serial port associated with the class
|
||||
is not currently open.
|
||||
*/
|
||||
void QextSerialPort::close()
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
flush();
|
||||
QIODevice::close(); // mark ourselves as closed
|
||||
CancelIo(Win_Handle);
|
||||
if (CloseHandle(Win_Handle))
|
||||
Win_Handle = INVALID_HANDLE_VALUE;
|
||||
if (winEventNotifier)
|
||||
winEventNotifier->deleteLater();
|
||||
|
||||
_bytesToWrite = 0;
|
||||
|
||||
foreach(OVERLAPPED* o, pendingWrites) {
|
||||
CloseHandle(o->hEvent);
|
||||
delete o;
|
||||
}
|
||||
pendingWrites.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Flushes all pending I/O to the serial port. This function has no effect if the serial port
|
||||
associated with the class is not currently open.
|
||||
*/
|
||||
void QextSerialPort::flush() {
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
FlushFileBuffers(Win_Handle);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
This function will return the number of bytes waiting in the receive queue of the serial port.
|
||||
It is included primarily to provide a complete QIODevice interface, and will not record errors
|
||||
in the lastErr member (because it is const). This function is also not thread-safe - in
|
||||
multithreading situations, use QextSerialPort::bytesAvailable() instead.
|
||||
*/
|
||||
qint64 QextSerialPort::size() const {
|
||||
int availBytes;
|
||||
COMSTAT Win_ComStat;
|
||||
DWORD Win_ErrorMask=0;
|
||||
ClearCommError(Win_Handle, &Win_ErrorMask, &Win_ComStat);
|
||||
availBytes = Win_ComStat.cbInQue;
|
||||
return (qint64)availBytes;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the number of bytes waiting in the port's receive queue. This function will return 0 if
|
||||
the port is not currently open, or -1 on error.
|
||||
*/
|
||||
qint64 QextSerialPort::bytesAvailable() const {
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
DWORD Errors;
|
||||
COMSTAT Status;
|
||||
if (ClearCommError(Win_Handle, &Errors, &Status)) {
|
||||
return Status.cbInQue + QIODevice::bytesAvailable();
|
||||
}
|
||||
return (qint64)-1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Translates a system-specific error code to a QextSerialPort error code. Used internally.
|
||||
*/
|
||||
void QextSerialPort::translateError(ulong error) {
|
||||
if (error&CE_BREAK) {
|
||||
lastErr=E_BREAK_CONDITION;
|
||||
}
|
||||
else if (error&CE_FRAME) {
|
||||
lastErr=E_FRAMING_ERROR;
|
||||
}
|
||||
else if (error&CE_IOE) {
|
||||
lastErr=E_IO_ERROR;
|
||||
}
|
||||
else if (error&CE_MODE) {
|
||||
lastErr=E_INVALID_FD;
|
||||
}
|
||||
else if (error&CE_OVERRUN) {
|
||||
lastErr=E_BUFFER_OVERRUN;
|
||||
}
|
||||
else if (error&CE_RXPARITY) {
|
||||
lastErr=E_RECEIVE_PARITY_ERROR;
|
||||
}
|
||||
else if (error&CE_RXOVER) {
|
||||
lastErr=E_RECEIVE_OVERFLOW;
|
||||
}
|
||||
else if (error&CE_TXFULL) {
|
||||
lastErr=E_TRANSMIT_OVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Reads a block of data from the serial port. This function will read at most maxlen bytes from
|
||||
the serial port and place them in the buffer pointed to by data. Return value is the number of
|
||||
bytes actually read, or -1 on error.
|
||||
|
||||
\warning before calling this function ensure that serial port associated with this class
|
||||
is currently open (use isOpen() function to check if port is open).
|
||||
*/
|
||||
qint64 QextSerialPort::readData(char *data, qint64 maxSize)
|
||||
{
|
||||
DWORD retVal;
|
||||
QMutexLocker lock(mutex);
|
||||
retVal = 0;
|
||||
if (queryMode() == QextSerialPort::EventDriven) {
|
||||
OVERLAPPED overlapRead;
|
||||
ZeroMemory(&overlapRead, sizeof(OVERLAPPED));
|
||||
if (!ReadFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, & overlapRead)) {
|
||||
if (GetLastError() == ERROR_IO_PENDING)
|
||||
GetOverlappedResult(Win_Handle, & overlapRead, & retVal, true);
|
||||
else {
|
||||
lastErr = E_READ_FAILED;
|
||||
retVal = (DWORD)-1;
|
||||
}
|
||||
}
|
||||
} else if (!ReadFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, NULL)) {
|
||||
lastErr = E_READ_FAILED;
|
||||
retVal = (DWORD)-1;
|
||||
}
|
||||
return (qint64)retVal;
|
||||
}
|
||||
|
||||
/*!
|
||||
Writes a block of data to the serial port. This function will write len bytes
|
||||
from the buffer pointed to by data to the serial port. Return value is the number
|
||||
of bytes actually written, or -1 on error.
|
||||
|
||||
\warning before calling this function ensure that serial port associated with this class
|
||||
is currently open (use isOpen() function to check if port is open).
|
||||
*/
|
||||
qint64 QextSerialPort::writeData(const char *data, qint64 maxSize)
|
||||
{
|
||||
QMutexLocker lock( mutex );
|
||||
DWORD retVal = 0;
|
||||
if (queryMode() == QextSerialPort::EventDriven) {
|
||||
OVERLAPPED* newOverlapWrite = new OVERLAPPED;
|
||||
ZeroMemory(newOverlapWrite, sizeof(OVERLAPPED));
|
||||
newOverlapWrite->hEvent = CreateEvent(NULL, true, false, NULL);
|
||||
if (WriteFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, newOverlapWrite)) {
|
||||
CloseHandle(newOverlapWrite->hEvent);
|
||||
delete newOverlapWrite;
|
||||
}
|
||||
else if (GetLastError() == ERROR_IO_PENDING) {
|
||||
// writing asynchronously...not an error
|
||||
QWriteLocker writelocker(bytesToWriteLock);
|
||||
_bytesToWrite += maxSize;
|
||||
pendingWrites.append(newOverlapWrite);
|
||||
}
|
||||
else {
|
||||
qDebug() << "serialport write error:" << GetLastError();
|
||||
lastErr = E_WRITE_FAILED;
|
||||
retVal = (DWORD)-1;
|
||||
if(!CancelIo(newOverlapWrite->hEvent))
|
||||
qDebug() << "serialport: couldn't cancel IO";
|
||||
if(!CloseHandle(newOverlapWrite->hEvent))
|
||||
qDebug() << "serialport: couldn't close OVERLAPPED handle";
|
||||
delete newOverlapWrite;
|
||||
}
|
||||
} else if (!WriteFile(Win_Handle, (void*)data, (DWORD)maxSize, & retVal, NULL)) {
|
||||
lastErr = E_WRITE_FAILED;
|
||||
retVal = (DWORD)-1;
|
||||
}
|
||||
return (qint64)retVal;
|
||||
}
|
||||
|
||||
/*!
|
||||
This function is included to implement the full QIODevice interface, and currently has no
|
||||
purpose within this class. This function is meaningless on an unbuffered device and currently
|
||||
only prints a warning message to that effect.
|
||||
*/
|
||||
void QextSerialPort::ungetChar(char c) {
|
||||
|
||||
/*meaningless on unbuffered sequential device - return error and print a warning*/
|
||||
TTY_WARNING("QextSerialPort: ungetChar() called on an unbuffered sequential device - operation is meaningless");
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the flow control used by the port. Possible values of flow are:
|
||||
\verbatim
|
||||
FLOW_OFF No flow control
|
||||
FLOW_HARDWARE Hardware (RTS/CTS) flow control
|
||||
FLOW_XONXOFF Software (XON/XOFF) flow control
|
||||
\endverbatim
|
||||
*/
|
||||
void QextSerialPort::setFlowControl(FlowType flow) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.FlowControl!=flow) {
|
||||
Settings.FlowControl=flow;
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch(flow) {
|
||||
|
||||
/*no flow control*/
|
||||
case FLOW_OFF:
|
||||
Win_CommConfig.dcb.fOutxCtsFlow=FALSE;
|
||||
Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_DISABLE;
|
||||
Win_CommConfig.dcb.fInX=FALSE;
|
||||
Win_CommConfig.dcb.fOutX=FALSE;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
break;
|
||||
|
||||
/*software (XON/XOFF) flow control*/
|
||||
case FLOW_XONXOFF:
|
||||
Win_CommConfig.dcb.fOutxCtsFlow=FALSE;
|
||||
Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_DISABLE;
|
||||
Win_CommConfig.dcb.fInX=TRUE;
|
||||
Win_CommConfig.dcb.fOutX=TRUE;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
break;
|
||||
|
||||
case FLOW_HARDWARE:
|
||||
Win_CommConfig.dcb.fOutxCtsFlow=TRUE;
|
||||
Win_CommConfig.dcb.fRtsControl=RTS_CONTROL_HANDSHAKE;
|
||||
Win_CommConfig.dcb.fInX=FALSE;
|
||||
Win_CommConfig.dcb.fOutX=FALSE;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the parity associated with the serial port. The possible values of parity are:
|
||||
\verbatim
|
||||
PAR_SPACE Space Parity
|
||||
PAR_MARK Mark Parity
|
||||
PAR_NONE No Parity
|
||||
PAR_EVEN Even Parity
|
||||
PAR_ODD Odd Parity
|
||||
\endverbatim
|
||||
*/
|
||||
void QextSerialPort::setParity(ParityType parity) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.Parity!=parity) {
|
||||
Settings.Parity=parity;
|
||||
}
|
||||
if (isOpen()) {
|
||||
Win_CommConfig.dcb.Parity=(unsigned char)parity;
|
||||
switch (parity) {
|
||||
|
||||
/*space parity*/
|
||||
case PAR_SPACE:
|
||||
if (Settings.DataBits==DATA_8) {
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: Space parity with 8 data bits is not supported by POSIX systems.");
|
||||
}
|
||||
Win_CommConfig.dcb.fParity=TRUE;
|
||||
break;
|
||||
|
||||
/*mark parity - WINDOWS ONLY*/
|
||||
case PAR_MARK:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: Mark parity is not supported by POSIX systems");
|
||||
Win_CommConfig.dcb.fParity=TRUE;
|
||||
break;
|
||||
|
||||
/*no parity*/
|
||||
case PAR_NONE:
|
||||
Win_CommConfig.dcb.fParity=FALSE;
|
||||
break;
|
||||
|
||||
/*even parity*/
|
||||
case PAR_EVEN:
|
||||
Win_CommConfig.dcb.fParity=TRUE;
|
||||
break;
|
||||
|
||||
/*odd parity*/
|
||||
case PAR_ODD:
|
||||
Win_CommConfig.dcb.fParity=TRUE;
|
||||
break;
|
||||
}
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the number of data bits used by the serial port. Possible values of dataBits are:
|
||||
\verbatim
|
||||
DATA_5 5 data bits
|
||||
DATA_6 6 data bits
|
||||
DATA_7 7 data bits
|
||||
DATA_8 8 data bits
|
||||
\endverbatim
|
||||
|
||||
\note
|
||||
This function is subject to the following restrictions:
|
||||
\par
|
||||
5 data bits cannot be used with 2 stop bits.
|
||||
\par
|
||||
1.5 stop bits can only be used with 5 data bits.
|
||||
\par
|
||||
8 data bits cannot be used with space parity on POSIX systems.
|
||||
*/
|
||||
void QextSerialPort::setDataBits(DataBitsType dataBits) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.DataBits!=dataBits) {
|
||||
if ((Settings.StopBits==STOP_2 && dataBits==DATA_5) ||
|
||||
(Settings.StopBits==STOP_1_5 && dataBits!=DATA_5)) {
|
||||
}
|
||||
else {
|
||||
Settings.DataBits=dataBits;
|
||||
}
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch(dataBits) {
|
||||
|
||||
/*5 data bits*/
|
||||
case DATA_5:
|
||||
if (Settings.StopBits==STOP_2) {
|
||||
TTY_WARNING("QextSerialPort: 5 Data bits cannot be used with 2 stop bits.");
|
||||
}
|
||||
else {
|
||||
Win_CommConfig.dcb.ByteSize=5;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
break;
|
||||
|
||||
/*6 data bits*/
|
||||
case DATA_6:
|
||||
if (Settings.StopBits==STOP_1_5) {
|
||||
TTY_WARNING("QextSerialPort: 6 Data bits cannot be used with 1.5 stop bits.");
|
||||
}
|
||||
else {
|
||||
Win_CommConfig.dcb.ByteSize=6;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
break;
|
||||
|
||||
/*7 data bits*/
|
||||
case DATA_7:
|
||||
if (Settings.StopBits==STOP_1_5) {
|
||||
TTY_WARNING("QextSerialPort: 7 Data bits cannot be used with 1.5 stop bits.");
|
||||
}
|
||||
else {
|
||||
Win_CommConfig.dcb.ByteSize=7;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
break;
|
||||
|
||||
/*8 data bits*/
|
||||
case DATA_8:
|
||||
if (Settings.StopBits==STOP_1_5) {
|
||||
TTY_WARNING("QextSerialPort: 8 Data bits cannot be used with 1.5 stop bits.");
|
||||
}
|
||||
else {
|
||||
Win_CommConfig.dcb.ByteSize=8;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the number of stop bits used by the serial port. Possible values of stopBits are:
|
||||
\verbatim
|
||||
STOP_1 1 stop bit
|
||||
STOP_1_5 1.5 stop bits
|
||||
STOP_2 2 stop bits
|
||||
\endverbatim
|
||||
|
||||
\note
|
||||
This function is subject to the following restrictions:
|
||||
\par
|
||||
2 stop bits cannot be used with 5 data bits.
|
||||
\par
|
||||
1.5 stop bits cannot be used with 6 or more data bits.
|
||||
\par
|
||||
POSIX does not support 1.5 stop bits.
|
||||
*/
|
||||
void QextSerialPort::setStopBits(StopBitsType stopBits) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.StopBits!=stopBits) {
|
||||
if ((Settings.DataBits==DATA_5 && stopBits==STOP_2) ||
|
||||
(stopBits==STOP_1_5 && Settings.DataBits!=DATA_5)) {
|
||||
}
|
||||
else {
|
||||
Settings.StopBits=stopBits;
|
||||
}
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch (stopBits) {
|
||||
|
||||
/*one stop bit*/
|
||||
case STOP_1:
|
||||
Win_CommConfig.dcb.StopBits=ONESTOPBIT;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
break;
|
||||
|
||||
/*1.5 stop bits*/
|
||||
case STOP_1_5:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: 1.5 stop bit operation is not supported by POSIX.");
|
||||
if (Settings.DataBits!=DATA_5) {
|
||||
TTY_WARNING("QextSerialPort: 1.5 stop bits can only be used with 5 data bits");
|
||||
}
|
||||
else {
|
||||
Win_CommConfig.dcb.StopBits=ONE5STOPBITS;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
break;
|
||||
|
||||
/*two stop bits*/
|
||||
case STOP_2:
|
||||
if (Settings.DataBits==DATA_5) {
|
||||
TTY_WARNING("QextSerialPort: 2 stop bits cannot be used with 5 data bits");
|
||||
}
|
||||
else {
|
||||
Win_CommConfig.dcb.StopBits=TWOSTOPBITS;
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the baud rate of the serial port. Note that not all rates are applicable on
|
||||
all platforms. The following table shows translations of the various baud rate
|
||||
constants on Windows(including NT/2000) and POSIX platforms. Speeds marked with an *
|
||||
are speeds that are usable on both Windows and POSIX.
|
||||
\verbatim
|
||||
|
||||
RATE Windows Speed POSIX Speed
|
||||
----------- ------------- -----------
|
||||
BAUD50 110 50
|
||||
BAUD75 110 75
|
||||
*BAUD110 110 110
|
||||
BAUD134 110 134.5
|
||||
BAUD150 110 150
|
||||
BAUD200 110 200
|
||||
*BAUD300 300 300
|
||||
*BAUD600 600 600
|
||||
*BAUD1200 1200 1200
|
||||
BAUD1800 1200 1800
|
||||
*BAUD2400 2400 2400
|
||||
*BAUD4800 4800 4800
|
||||
*BAUD9600 9600 9600
|
||||
BAUD14400 14400 9600
|
||||
*BAUD19200 19200 19200
|
||||
*BAUD38400 38400 38400
|
||||
BAUD56000 56000 38400
|
||||
*BAUD57600 57600 57600
|
||||
BAUD76800 57600 76800
|
||||
*BAUD115200 115200 115200
|
||||
BAUD128000 128000 115200
|
||||
BAUD256000 256000 115200
|
||||
\endverbatim
|
||||
*/
|
||||
void QextSerialPort::setBaudRate(BaudRateType baudRate) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (Settings.BaudRate!=baudRate) {
|
||||
switch (baudRate) {
|
||||
case BAUD50:
|
||||
case BAUD75:
|
||||
case BAUD134:
|
||||
case BAUD150:
|
||||
case BAUD200:
|
||||
Settings.BaudRate=BAUD110;
|
||||
break;
|
||||
|
||||
case BAUD1800:
|
||||
Settings.BaudRate=BAUD1200;
|
||||
break;
|
||||
|
||||
case BAUD76800:
|
||||
Settings.BaudRate=BAUD57600;
|
||||
break;
|
||||
|
||||
default:
|
||||
Settings.BaudRate=baudRate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isOpen()) {
|
||||
switch (baudRate) {
|
||||
|
||||
/*50 baud*/
|
||||
case BAUD50:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 50 baud operation. Switching to 110 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_110;
|
||||
break;
|
||||
|
||||
/*75 baud*/
|
||||
case BAUD75:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 75 baud operation. Switching to 110 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_110;
|
||||
break;
|
||||
|
||||
/*110 baud*/
|
||||
case BAUD110:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_110;
|
||||
break;
|
||||
|
||||
/*134.5 baud*/
|
||||
case BAUD134:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 134.5 baud operation. Switching to 110 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_110;
|
||||
break;
|
||||
|
||||
/*150 baud*/
|
||||
case BAUD150:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 150 baud operation. Switching to 110 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_110;
|
||||
break;
|
||||
|
||||
/*200 baud*/
|
||||
case BAUD200:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 200 baud operation. Switching to 110 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_110;
|
||||
break;
|
||||
|
||||
/*300 baud*/
|
||||
case BAUD300:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_300;
|
||||
break;
|
||||
|
||||
/*600 baud*/
|
||||
case BAUD600:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_600;
|
||||
break;
|
||||
|
||||
/*1200 baud*/
|
||||
case BAUD1200:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_1200;
|
||||
break;
|
||||
|
||||
/*1800 baud*/
|
||||
case BAUD1800:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 1800 baud operation. Switching to 1200 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_1200;
|
||||
break;
|
||||
|
||||
/*2400 baud*/
|
||||
case BAUD2400:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_2400;
|
||||
break;
|
||||
|
||||
/*4800 baud*/
|
||||
case BAUD4800:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_4800;
|
||||
break;
|
||||
|
||||
/*9600 baud*/
|
||||
case BAUD9600:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_9600;
|
||||
break;
|
||||
|
||||
/*14400 baud*/
|
||||
case BAUD14400:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: POSIX does not support 14400 baud operation.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_14400;
|
||||
break;
|
||||
|
||||
/*19200 baud*/
|
||||
case BAUD19200:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_19200;
|
||||
break;
|
||||
|
||||
/*38400 baud*/
|
||||
case BAUD38400:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_38400;
|
||||
break;
|
||||
|
||||
/*56000 baud*/
|
||||
case BAUD56000:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: POSIX does not support 56000 baud operation.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_56000;
|
||||
break;
|
||||
|
||||
/*57600 baud*/
|
||||
case BAUD57600:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_57600;
|
||||
break;
|
||||
|
||||
/*76800 baud*/
|
||||
case BAUD76800:
|
||||
TTY_WARNING("QextSerialPort: Windows does not support 76800 baud operation. Switching to 57600 baud.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_57600;
|
||||
break;
|
||||
|
||||
/*115200 baud*/
|
||||
case BAUD115200:
|
||||
Win_CommConfig.dcb.BaudRate=CBR_115200;
|
||||
break;
|
||||
|
||||
/*128000 baud*/
|
||||
case BAUD128000:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: POSIX does not support 128000 baud operation.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_128000;
|
||||
break;
|
||||
|
||||
/*256000 baud*/
|
||||
case BAUD256000:
|
||||
TTY_PORTABILITY_WARNING("QextSerialPort Portability Warning: POSIX does not support 256000 baud operation.");
|
||||
Win_CommConfig.dcb.BaudRate=CBR_256000;
|
||||
break;
|
||||
}
|
||||
SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets DTR line to the requested state (high by default). This function will have no effect if
|
||||
the port associated with the class is not currently open.
|
||||
*/
|
||||
void QextSerialPort::setDtr(bool set) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
if (set) {
|
||||
EscapeCommFunction(Win_Handle, SETDTR);
|
||||
}
|
||||
else {
|
||||
EscapeCommFunction(Win_Handle, CLRDTR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets RTS line to the requested state (high by default). This function will have no effect if
|
||||
the port associated with the class is not currently open.
|
||||
*/
|
||||
void QextSerialPort::setRts(bool set) {
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
if (set) {
|
||||
EscapeCommFunction(Win_Handle, SETRTS);
|
||||
}
|
||||
else {
|
||||
EscapeCommFunction(Win_Handle, CLRRTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the line status as stored by the port function. This function will retrieve the states
|
||||
of the following lines: DCD, CTS, DSR, and RI. On POSIX systems, the following additional lines
|
||||
can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD. The value returned is an unsigned
|
||||
long with specific bits indicating which lines are high. The following constants should be used
|
||||
to examine the states of individual lines:
|
||||
|
||||
\verbatim
|
||||
Mask Line
|
||||
------ ----
|
||||
LS_CTS CTS
|
||||
LS_DSR DSR
|
||||
LS_DCD DCD
|
||||
LS_RI RI
|
||||
\endverbatim
|
||||
|
||||
This function will return 0 if the port associated with the class is not currently open.
|
||||
*/
|
||||
ulong QextSerialPort::lineStatus(void) {
|
||||
unsigned long Status=0, Temp=0;
|
||||
QMutexLocker lock(mutex);
|
||||
if (isOpen()) {
|
||||
GetCommModemStatus(Win_Handle, &Temp);
|
||||
if (Temp&MS_CTS_ON) {
|
||||
Status|=LS_CTS;
|
||||
}
|
||||
if (Temp&MS_DSR_ON) {
|
||||
Status|=LS_DSR;
|
||||
}
|
||||
if (Temp&MS_RING_ON) {
|
||||
Status|=LS_RI;
|
||||
}
|
||||
if (Temp&MS_RLSD_ON) {
|
||||
Status|=LS_DCD;
|
||||
}
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
bool QextSerialPort::waitForReadyRead(int msecs)
|
||||
{
|
||||
//@todo implement
|
||||
return false;
|
||||
}
|
||||
|
||||
qint64 QextSerialPort::bytesToWrite() const
|
||||
{
|
||||
QReadLocker rl(bytesToWriteLock);
|
||||
return _bytesToWrite;
|
||||
}
|
||||
|
||||
/*
|
||||
Triggered when there's activity on our HANDLE.
|
||||
*/
|
||||
void QextSerialPort::onWinEvent(HANDLE h)
|
||||
{
|
||||
QMutexLocker lock(mutex);
|
||||
if(h == overlap.hEvent) {
|
||||
if (eventMask & EV_RXCHAR) {
|
||||
if (sender() != this && bytesAvailable() > 0)
|
||||
emit readyRead();
|
||||
}
|
||||
if (eventMask & EV_TXEMPTY) {
|
||||
/*
|
||||
A write completed. Run through the list of OVERLAPPED writes, and if
|
||||
they completed successfully, take them off the list and delete them.
|
||||
Otherwise, leave them on there so they can finish.
|
||||
*/
|
||||
qint64 totalBytesWritten = 0;
|
||||
QList<OVERLAPPED*> overlapsToDelete;
|
||||
foreach(OVERLAPPED* o, pendingWrites) {
|
||||
DWORD numBytes = 0;
|
||||
if (GetOverlappedResult(Win_Handle, o, & numBytes, false)) {
|
||||
overlapsToDelete.append(o);
|
||||
totalBytesWritten += numBytes;
|
||||
} else if( GetLastError() != ERROR_IO_INCOMPLETE ) {
|
||||
overlapsToDelete.append(o);
|
||||
qWarning() << "CommEvent overlapped write error:" << GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
if (sender() != this && totalBytesWritten > 0) {
|
||||
QWriteLocker writelocker(bytesToWriteLock);
|
||||
emit bytesWritten(totalBytesWritten);
|
||||
_bytesToWrite = 0;
|
||||
}
|
||||
|
||||
foreach(OVERLAPPED* o, overlapsToDelete) {
|
||||
OVERLAPPED *toDelete = pendingWrites.takeAt(pendingWrites.indexOf(o));
|
||||
CloseHandle(toDelete->hEvent);
|
||||
delete toDelete;
|
||||
}
|
||||
}
|
||||
if (eventMask & EV_DSR) {
|
||||
if (lineStatus() & LS_DSR)
|
||||
emit dsrChanged(true);
|
||||
else
|
||||
emit dsrChanged(false);
|
||||
}
|
||||
}
|
||||
WaitCommEvent(Win_Handle, &eventMask, &overlap);
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the read and write timeouts for the port to millisec milliseconds.
|
||||
Setting 0 indicates that timeouts are not used for read nor write operations;
|
||||
however read() and write() functions will still block. Set -1 to provide
|
||||
non-blocking behaviour (read() and write() will return immediately).
|
||||
|
||||
\note this function does nothing in event driven mode.
|
||||
*/
|
||||
void QextSerialPort::setTimeout(long millisec) {
|
||||
QMutexLocker lock(mutex);
|
||||
Settings.Timeout_Millisec = millisec;
|
||||
|
||||
if (millisec == -1) {
|
||||
Win_CommTimeouts.ReadIntervalTimeout = MAXDWORD;
|
||||
Win_CommTimeouts.ReadTotalTimeoutConstant = 0;
|
||||
} else {
|
||||
Win_CommTimeouts.ReadIntervalTimeout = millisec;
|
||||
Win_CommTimeouts.ReadTotalTimeoutConstant = millisec;
|
||||
}
|
||||
Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
Win_CommTimeouts.WriteTotalTimeoutMultiplier = millisec;
|
||||
Win_CommTimeouts.WriteTotalTimeoutConstant = 0;
|
||||
if (queryMode() != QextSerialPort::EventDriven)
|
||||
SetCommTimeouts(Win_Handle, &Win_CommTimeouts);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user