diff options
-rw-r--r-- | examples/EMPTYFILE | 0 | ||||
-rw-r--r-- | include/serialport.h | 8 | ||||
-rw-r--r-- | qserialdevice.pro | 6 | ||||
-rw-r--r-- | src/serialport.cpp | 6 | ||||
-rw-r--r-- | src/serialport_p.h | 168 | ||||
-rw-r--r-- | src/serialport_p_win.cpp | 431 | ||||
-rw-r--r-- | src/serialport_p_win.h | 26 | ||||
-rw-r--r-- | src/serialportinfo.cpp | 11 | ||||
-rw-r--r-- | src/serialportinfo_p.h | 10 | ||||
-rw-r--r-- | src/serialportinfo_p_win.cpp | 16 | ||||
-rw-r--r-- | src/src.pri | 30 | ||||
-rw-r--r-- | tests/EMPTYFILE | 0 |
12 files changed, 591 insertions, 121 deletions
diff --git a/examples/EMPTYFILE b/examples/EMPTYFILE new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/examples/EMPTYFILE diff --git a/include/serialport.h b/include/serialport.h index f2f1963..e3ca603 100644 --- a/include/serialport.h +++ b/include/serialport.h @@ -20,7 +20,7 @@ class SerialPortInfo; class SerialPortPrivate; -class QSERIALDEVICE_EXPORT SerialPort : public QIODevice +class SERIALPORT_EXPORT SerialPort : public QIODevice { Q_OBJECT @@ -145,10 +145,10 @@ public: bool setFlowControl(FlowControl flow); FlowControl flowControl() const; - void setDataInterval(int usecs); + bool setDataInterval(int usecs); int dataInterval() const; - void setReadTimeout(int msecs); + bool setReadTimeout(int msecs); int readTimeout() const; bool dtr() const; @@ -159,7 +159,7 @@ public: bool flush(); virtual bool reset(); - void setDataErrorPolicy(DataErrorPolicy policy = IgnorePolicy); + bool setDataErrorPolicy(DataErrorPolicy policy = IgnorePolicy); DataErrorPolicy dataErrorPolicy() const; PortError error() const; diff --git a/qserialdevice.pro b/qserialdevice.pro index 04dcfc2..f0a9cb0 100644 --- a/qserialdevice.pro +++ b/qserialdevice.pro @@ -4,10 +4,14 @@ QT -= gui OBJECTS_DIR = build/obj MOC_DIR = build/moc -win32:DEFINES += QSERIALDEVICE_SHARED +win32:DEFINES += SERIALPORT_BUILD SERIALPORT_SHARED INCLUDEPATH += src include +HEADERS += \ + include/serialport.h \ + include/serialportinfo.h + include(src/src.pri) CONFIG(debug, debug|release) { diff --git a/src/serialport.cpp b/src/serialport.cpp index 73f6928..0e31631 100644 --- a/src/serialport.cpp +++ b/src/serialport.cpp @@ -113,7 +113,7 @@ SerialPort::FlowControl SerialPort::flowControl() const } -void SerialPort::setDataInterval(int usecs) +bool SerialPort::setDataInterval(int usecs) { } @@ -123,7 +123,7 @@ int SerialPort::dataInterval() const } -void SerialPort::setReadTimeout(int msecs) +bool SerialPort::setReadTimeout(int msecs) { } @@ -158,7 +158,7 @@ bool SerialPort::reset() } -void SerialPort::setDataErrorPolicy(DataErrorPolicy policy) +bool SerialPort::setDataErrorPolicy(DataErrorPolicy policy) { } diff --git a/src/serialport_p.h b/src/serialport_p.h index 786e901..00ba929 100644 --- a/src/serialport_p.h +++ b/src/serialport_p.h @@ -11,143 +11,175 @@ class SerialPortPrivate { public: SerialPortPrivate() - : mInRate(SerialPort::UnknownRate) - , mOutRate(SerialPort::UnknownRate) - , mDataBits(SerialPort::UnknownDataBits) - , mParity(SerialPort::UnknownParity) - , mStopBits(SerialPort::UnknownStopBits) - , mFlow(SerialPort::UnknownFlowControl) - , mDataInterval(0) - , mReadTimeout(0) - , mPolicy(SerialPort::IgnorePolicy) - , mError(SerialPort::NoError) + : m_inRate(SerialPort::UnknownRate) + , m_outRate(SerialPort::UnknownRate) + , m_dataBits(SerialPort::UnknownDataBits) + , m_parity(SerialPort::UnknownParity) + , m_stopBits(SerialPort::UnknownStopBits) + , m_flow(SerialPort::UnknownFlowControl) + , m_dataInterval(0) + , m_readTimeout(0) + , m_policy(SerialPort::IgnorePolicy) + , m_portError(SerialPort::NoError) + , m_oldSettingsIsSaved(false) {} - void setPort(const QString &port) { mPort = port; } - const QString& port() const { return mPort; } + SerialPortPrivate(const QString &port) + : m_inRate(SerialPort::UnknownRate) + , m_outRate(SerialPort::UnknownRate) + , m_dataBits(SerialPort::UnknownDataBits) + , m_parity(SerialPort::UnknownParity) + , m_stopBits(SerialPort::UnknownStopBits) + , m_flow(SerialPort::UnknownFlowControl) + , m_dataInterval(0) + , m_readTimeout(0) + , m_policy(SerialPort::IgnorePolicy) + , m_portError(SerialPort::NoError) + , m_oldSettingsIsSaved(false) + { - virtual bool open(QIODevice::OpenMode mode) = 0; - virtual void close() = 0; + } + + void setPort(const QString &port) { m_systemLocation = nativeToSystemLocation(port); } + QString port() const { return nativeFromSystemLocation(m_systemLocation); } + + virtual bool open(QIODevice::OpenMode mode) {} + virtual void close() {} bool setRate(qint32 rate, SerialPort::Directions dir) { if (setNativeRate(rate, dir)) { - mRate = rate; + if (SerialPort::Input & dir) + m_inRate = rate; + if (SerialPort::Output & dir) + m_outRate = rate; return true; } return false; } qint32 rate(SerialPort::Directions dir) const { - if (dir & Input) - return (dir & Output) ? ((mInRate + mOutRate)/2) : mInRate; - return mOutRate; + if (SerialPort::AllDirections == dir) + return (m_inRate == m_outRate) ? (m_inRate) : SerialPort::UnknownRate; + return (SerialPort::Input & dir) ? (m_inRate) : (m_outRate); } + bool setDataBits(SerialPort::DataBits dataBits) { if (setNativeDataBits(dataBits)) { - mDataBits = dataBits; + m_dataBits = dataBits; return true; } return false; } - SerialPort::DataBits dataBits() const { return mDataBits; } + SerialPort::DataBits dataBits() const { return m_dataBits; } bool setParity(SerialPort::Parity parity) { if (setNativeParity(parity)) { - mParity = parity; + m_parity = parity; return true; } return false; } - SerialPort::Parity parity() const { return mParity; } + SerialPort::Parity parity() const { return m_parity; } bool setStopBits(SerialPort::StopBits stopBits) { if (setNativeStopBits(stopBits)) { - mStopBits = stopBits; + m_stopBits = stopBits; return true; } return false; } - SerialPort::StopBits stopBits() const { return mStopBits; } + SerialPort::StopBits stopBits() const { return m_stopBits; } bool setFlowControl(SerialPort::FlowControl flow) { if (setNativeFlowControl(flow)) { - mFlow = flow; + m_flow = flow; return true; } return false; } - SerialPort::FlowControl flowControl() const { return mFlow; } + SerialPort::FlowControl flowControl() const { return m_flow; } - void setDataInterval(int usecs) { + bool setDataInterval(int usecs) { if (setNativeDataInterval(usecs)) { - mDataInterval = usecs; + m_dataInterval = usecs; return true; } return false; } - int dataInterval() const { return mDataInterval; } + int dataInterval() const { return m_dataInterval; } - void setReadTimeout(int msecs) { + bool setReadTimeout(int msecs) { if (setNativeReadTimeout(msecs)) { - mReadTimeout = msecs; + m_readTimeout = msecs; return true; } return false; } - int readTimeout() const { return mReadTimeout; } + int readTimeout() const { return m_readTimeout; } - virtual bool dtr() const = 0; - virtual bool rts() const = 0; + virtual bool dtr() const {} + virtual bool rts() const {} - virtual SerialPort::Lines lines() const = 0; + virtual SerialPort::Lines lines() const {} - virtual bool flush() = 0; - virtual bool reset() = 0; + virtual bool flush() {} + virtual bool reset() {} - void setDataErrorPolicy(SerialPort::DataErrorPolicy policy) { + bool setDataErrorPolicy(SerialPort::DataErrorPolicy policy) { if (setNativeDataErrorPolicy(policy)) { - mPolicy = policy; + m_policy = policy; return true; } return false; } - SerialPort::DataErrorPolicy dataErrorPolicy() const { return mPolicy; } + SerialPort::DataErrorPolicy dataErrorPolicy() const { return m_policy; } + + SerialPort::PortError error() const { return m_portError; } + void unsetError() { m_portError = SerialPort::NoError; } - SerialPort::PortError error() const { return mError; } - void unsetError() { mError = SerialPort::NoError; } + void setError(SerialPort::PortError error) { m_portError = error; } - void setError(SerialPort::PortError error) { mError = error; } + virtual qint64 bytesAvailable() const {} - virtual qint64 bytesAvailable() const = 0; + virtual qint64 read(char *data, qint64 len) {} + virtual qint64 write(const char *data, qint64 len) {} + virtual bool waitForReadOrWrite(int timeout, + bool checkRead, bool checkWrite, + bool *selectForRead, bool *selectForWrite) {} - virtual qint64 read(char *data, qint64 len) = 0; - virtual qint64 write(const char *data, qint64 len) = 0; - virtual bool waitForReadyRead(int msec) = 0; - virtual bool waitForBytesWritten(int msec) = 0; protected: //General (for any OS) private parameters - QString mPort; - qint32 mInRate; - qint32 mOutRate; - SerialPort::DataBits mDataBits; - SerialPort::Parity mParity; - SerialPort::StopBits mStopBits; - SerialPort::FlowControl mFlow; - int mDataInterval; - int mReadTimeout; - SerialPort::DataErrorPolicy mPolicy; - SerialPort::PortError mError; - - virtual bool setNativeRate(int rate, SerialPort::Directions dir) = 0; - virtual bool setNativeDataBits(SerialPort::DataBits dataBits) = 0; - virtual bool setNativeParity(SerialPort::Parity parity) = 0; - virtual bool setNativeStopBits(SerialPort::StopBits stopBits) = 0; - virtual bool setNativeFlowControl(SerialPort::FlowControl flowControl) = 0; - virtual bool setNativeDataErrorPolicy(SerialPort::DataErrorPolicy policy) = 0; + QString m_systemLocation; + qint32 m_inRate; + qint32 m_outRate; + SerialPort::DataBits m_dataBits; + SerialPort::Parity m_parity; + SerialPort::StopBits m_stopBits; + SerialPort::FlowControl m_flow; + int m_dataInterval; + int m_readTimeout; + SerialPort::DataErrorPolicy m_policy; + SerialPort::PortError m_portError; + + bool m_oldSettingsIsSaved; + + virtual QString nativeToSystemLocation(const QString &port) const {} + virtual QString nativeFromSystemLocation(const QString &location) const {} + + virtual bool setNativeRate(qint32 rate, SerialPort::Directions dir) {} + virtual bool setNativeDataBits(SerialPort::DataBits dataBits) {} + virtual bool setNativeParity(SerialPort::Parity parity) {} + virtual bool setNativeStopBits(SerialPort::StopBits stopBits) {} + virtual bool setNativeFlowControl(SerialPort::FlowControl flowControl) {} + + virtual bool setNativeDataInterval(int usecs) {} + virtual bool setNativeReadTimeout(int msecs) {} + + virtual bool setNativeDataErrorPolicy(SerialPort::DataErrorPolicy policy) {} virtual void detectDefaultSettings() {} - virtual bool saveOldsettings() = 0; - virtual bool restoreOldsettings() = 0; + virtual bool saveOldsettings() {} + virtual bool restoreOldsettings() {} }; #endif // SERIALPORT_P_H diff --git a/src/serialport_p_win.cpp b/src/serialport_p_win.cpp index a236cad..96fbb5a 100644 --- a/src/serialport_p_win.cpp +++ b/src/serialport_p_win.cpp @@ -4,12 +4,43 @@ #include "serialport_p_win.h" +#include <QtCore/QRegExp> + +#ifndef Q_CC_MSVC +# include <ddk/ntddser.h> +#else +#ifndef IOCTL_SERIAL_GET_DTRRTS +#define IOCTL_SERIAL_GET_DTRRTS \ + CTL_CODE (FILE_DEVICE_SERIAL_PORT, 30, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif //Q_CC_MSVC + +#ifndef SERIAL_DTR_STATE +# define SERIAL_DTR_STATE 0x00000001 +#endif + +#ifndef SERIAL_RTS_STATE +# define SERIAL_RTS_STATE 0x00000002 +#endif + +#endif + /* Public */ SerialPortPrivateWin::SerialPortPrivateWin() : SerialPortPrivate() + , m_descriptor(INVALID_HANDLE_VALUE) { + size_t size = sizeof(DCB); + ::memset((void *)(&m_currDCB), 0, size); + ::memset((void *)(&m_oldDCB), 0, size); + size = sizeof(COMMTIMEOUTS); + ::memset((void *)(&m_currCommTimeouts), 0, size); + ::memset((void *)(&m_oldCommTimeouts), 0, size); + size = sizeof(OVERLAPPED); + ::memset((void *)(&m_ovRead), 0, size); + ::memset((void *)(&m_ovWrite), 0, size); + ::memset((void *)(&m_ovSelect), 0, size); } SerialPortPrivateWin::~SerialPortPrivateWin() @@ -18,27 +49,122 @@ SerialPortPrivateWin::~SerialPortPrivateWin() bool SerialPortPrivateWin::open(QIODevice::OpenMode mode) { - + DWORD access = 0; + DWORD sharing = 0; + bool rxflag = false; + bool txflag = false; + + if (QIODevice::ReadOnly & mode) { + access |= GENERIC_READ; //sharing = FILE_SHARE_READ; + rxflag = true; + } + if (QIODevice::WriteOnly & mode) { + access |= GENERIC_WRITE; //sharing = FILE_SHARE_WRITE; + txflag = true; + } + + QByteArray nativeFilePath = QByteArray((const char *)m_systemLocation.utf16(), m_systemLocation.size() * 2 + 1); + m_descriptor = ::CreateFile((const wchar_t*)nativeFilePath.constData(), + access, + sharing, + 0, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + 0); + + if (INVALID_HANDLE_VALUE == m_descriptor) { + // + return false; + } + + if (!saveOldsettings()) { + // + return false; + } + + // prepareOtherOptions(); + + if (!updateDcb()) { + // + return false; + } + + // Prepare timeouts. + /* + prepareCommTimeouts(SerialPortPrivateWin::ReadIntervalTimeout, MAXWORD); + prepareCommTimeouts(SerialPortPrivateWin::ReadTotalTimeoutMultiplier, 0); + prepareCommTimeouts(SerialPortPrivateWin::ReadTotalTimeoutConstant, 0); + prepareCommTimeouts(SerialPortPrivateWin::WriteTotalTimeoutMultiplier, 0); + prepareCommTimeouts(SerialPortPrivateWin::WriteTotalTimeoutConstant, 0); + */ + + if (!updateCommTimeouts()) { + // + return false; + } + + // Disable autocalculate total read interval. + //this->isAutoCalcReadTimeoutConstant = false; + + if (!createEvents(rxflag, txflag)) { + // + return false; + } + + detectDefaultSettings(); + return true; } void SerialPortPrivateWin::close() { - + restoreOldsettings(); + ::CancelIo(m_descriptor); + ::CloseHandle(m_descriptor); + closeEvents(); + m_descriptor = INVALID_HANDLE_VALUE; } bool SerialPortPrivateWin::dtr() const { - + return (SerialPort::Dtr && lines()); } bool SerialPortPrivateWin::rts() const { - + return (SerialPort::Rts && lines()); } SerialPort::Lines SerialPortPrivateWin::lines() const { - + DWORD modemStat = 0; + SerialPort::Lines result = 0; + + if (0 == ::GetCommModemStatus(m_descriptor, &modemStat)) { + // Print error? + return result; + } + + if (modemStat & MS_CTS_ON) + result |= SerialPort::Cts; + if (modemStat & MS_DSR_ON) + result |= SerialPort::Dsr; + if (modemStat & MS_RING_ON) + result |= SerialPort::Ri; + if (modemStat & MS_RLSD_ON) + result |= SerialPort::Dcd; + + DWORD bytesReturned = 0; + if (::DeviceIoControl(m_descriptor, IOCTL_SERIAL_GET_DTRRTS, 0, 0, + &modemStat, sizeof(DWORD), + &bytesReturned, 0)) { + + if (modemStat & SERIAL_DTR_STATE) + result |= SerialPort::Dtr; + if (modemStat & SERIAL_RTS_STATE) + result |= SerialPort::Rts; + } + + return result; } bool SerialPortPrivateWin::flush() @@ -63,7 +189,42 @@ qint64 SerialPortPrivateWin::read(char *data, qint64 len) qint64 SerialPortPrivateWin::write(const char *data, qint64 len) { - + //if (!clear_overlapped(&m_ovWrite)) + // return qint64(-1); + + DWORD writeBytes = 0; + bool sucessResult = false; + + if (::WriteFile(m_descriptor, (LPCVOID)data, (DWORD)len, &writeBytes, &m_ovWrite)) + sucessResult = true; + else { + if (ERROR_IO_PENDING == ::GetLastError()) { + //not to loop the function, instead of setting INFINITE put 5000 milliseconds wait! + switch (::WaitForSingleObject(m_ovWrite.hEvent, 5000)) { + case WAIT_OBJECT_0: { + if (::GetOverlappedResult(m_descriptor, &m_ovWrite, &writeBytes, false)) + sucessResult = true; + else { + // Print error? + ; + } + } + break;//WAIT_OBJECT_0 + default: + //Print error ? + ; + }//switch (rc) + } + else { +#if defined (NATIVESERIALENGINE_WIN_DEBUG) + qDebug() << "Windows: NativeSerialEnginePrivate::nativeWrite(const char *data, qint64 len) \n" + " -> function: ::GetLastError() returned: " << rc << ". Error! \n"; +#endif + ; + } + } + + return (sucessResult) ? quint64(writeBytes) : qint64(-1); } bool SerialPortPrivateWin::waitForReadyRead(int msec) @@ -76,73 +237,297 @@ bool SerialPortPrivateWin::waitForBytesWritten(int msec) } -// protected +/* Protected */ -bool SerialPortPrivateWin::setNativeRate(qint32 rate, SerialPort::Directions dir) +static const QString defaultPathPrefix = "\\\\.\\"; + +QString SerialPortPrivateWin::nativeToSystemLocation(const QString &port) const { + QString result; + if (!port.contains(defaultPathPrefix)) + result.append(defaultPathPrefix); + result.append(port); + return result; +} +QString SerialPortPrivateWin::nativeFromSystemLocation(const QString &location) const +{ + QString result = location; + if (result.contains(defaultPathPrefix)) + result.remove(defaultPathPrefix); + return result; } -bool SerialPortPrivateWin::setNativeDataBits(SerialPort::DataBits dataBits) +bool SerialPortPrivateWin::setNativeRate(qint32 rate, SerialPort::Directions dir) { + if ((SerialPort::UnknownRate == rate) + || (SerialPort::AllDirections != dir)) { + return false; + } + m_currDCB.BaudRate = DWORD(rate); + return (updateDcb()); +} +bool SerialPortPrivateWin::setNativeDataBits(SerialPort::DataBits dataBits) +{ + if (SerialPort::UnknownDataBits == dataBits) + return false; + + if ((SerialPort::Data5 == dataBits) + && (SerialPort::TwoStop == m_stopBits)) { + // + return false; + } + if ((SerialPort::Data6 == dataBits) + && (SerialPort::OneAndHalfStop == m_stopBits)) { + // + return false; + } + if ((SerialPort::Data7 == dataBits) + && (SerialPort::OneAndHalfStop == m_stopBits)) { + // + return false; + } + if ((SerialPort::Data8 == dataBits) + && (SerialPort::OneAndHalfStop == m_stopBits)) { + // + return false; + } + m_currDCB.ByteSize = BYTE(dataBits); + return (updateDcb()); } bool SerialPortPrivateWin::setNativeParity(SerialPort::Parity parity) { - + if (SerialPort::UnknownParity == parity) + return false; + + m_currDCB.fParity = true; + switch (parity) { + case SerialPort::NoParity: { + m_currDCB.Parity = NOPARITY; + m_currDCB.fParity = false; + } + break; + case SerialPort::SpaceParity: m_currDCB.Parity = SPACEPARITY; break; + case SerialPort::MarkParity: m_currDCB.Parity = MARKPARITY; break; + case SerialPort::EvenParity: m_currDCB.Parity = EVENPARITY; break; + case SerialPort::OddParity: m_currDCB.Parity = ODDPARITY; break; + default: return false; + } + return (updateDcb()); } bool SerialPortPrivateWin::setNativeStopBits(SerialPort::StopBits stopBits) { - + if (SerialPort::UnknownStopBits == stopBits) + return false; + + if ((SerialPort::Data5 == m_dataBits) + && (SerialPort::TwoStop == m_stopBits)) { + return false; + } + if ((SerialPort::Data6 == m_dataBits) + && (SerialPort::OneAndHalfStop == m_stopBits)) { + return false; + } + if ((SerialPort::Data7 == m_dataBits) + && (SerialPort::OneAndHalfStop == m_stopBits)) { + return false; + } + if ((SerialPort::Data8 == m_dataBits) + && (SerialPort::OneAndHalfStop == m_stopBits)) { + return false; + } + + switch (stopBits) { + case SerialPort::OneStop: m_currDCB.StopBits = ONESTOPBIT; break; + case SerialPort::OneAndHalfStop: m_currDCB.StopBits = ONE5STOPBITS; break; + case SerialPort::TwoStop: m_currDCB.StopBits = TWOSTOPBITS; break; + default: return false; + } + return (updateDcb()); } bool SerialPortPrivateWin::setNativeFlowControl(SerialPort::FlowControl flow) { - + if (SerialPort::UnknownFlowControl == flow) + return false; + + switch (flow) { + case SerialPort::NoFlowControl: { + m_currDCB.fOutxCtsFlow = false; + m_currDCB.fRtsControl = RTS_CONTROL_DISABLE; + m_currDCB.fInX = m_currDCB.fOutX = false; + } + break; + case SerialPort::SoftwareControl: { + m_currDCB.fOutxCtsFlow = false; + m_currDCB.fRtsControl = RTS_CONTROL_DISABLE; + m_currDCB.fInX = m_currDCB.fOutX = true; + } + break; + case SerialPort::HardwareControl: { + m_currDCB.fOutxCtsFlow = true; + m_currDCB.fRtsControl = RTS_CONTROL_HANDSHAKE; + m_currDCB.fInX = m_currDCB.fOutX = false; + } + break; + default: return false; + } + return (updateDcb()); } -void SerialPortPrivateWin::setNativeDataInterval(int usecs) +bool SerialPortPrivateWin::setNativeDataInterval(int usecs) { } -void SerialPortPrivateWin::setNativeReadTimeout(int msecs) +bool SerialPortPrivateWin::setNativeReadTimeout(int msecs) { } -void SerialPortPrivateWin::setNativeDataErrorPolicy(SerialPort::DataErrorPolicy policy) +bool SerialPortPrivateWin::setNativeDataErrorPolicy(SerialPort::DataErrorPolicy policy) { } +bool SerialPortPrivateWin::waitForReadOrWrite(int timeout, + bool checkRead, bool checkWrite, + bool *selectForRead, bool *selectForWrite) +{ + if (checkRead && (bytesAvailable() > 0)) { + *selectForRead = true; + return 1; + } + + //if (!clear_overlapped(&m_ovSelect)) + // return int(-1); + + DWORD oldEventMask = 0; + DWORD currEventMask = 0; + + if (checkRead) + currEventMask |= EV_RXCHAR; + if (checkWrite) + currEventMask |= EV_TXEMPTY; + + //save old mask + if (0 == ::GetCommMask(m_descriptor, &oldEventMask)) { + //Print error? + return -1; + } + + if (currEventMask != (oldEventMask & currEventMask)) { + currEventMask |= oldEventMask; + //set mask + if(0 == ::SetCommMask(m_descriptor, currEventMask)) { + //Print error? + return -1; + } + } + + currEventMask = 0; + bool selectResult = false; + + if (::WaitCommEvent(m_descriptor, &currEventMask, &m_ovSelect)) + selectResult = true; + else { + if (ERROR_IO_PENDING == ::GetLastError()) { + DWORD bytesTransferred = 0; + switch (::WaitForSingleObject(m_ovSelect.hEvent, (timeout < 0) ? 0 : timeout)) { + case WAIT_OBJECT_0: { + if (::GetOverlappedResult(m_descriptor, &m_ovSelect, &bytesTransferred, false)) + selectResult = true; + else { + //Print error? + ; + } + } + break; + case WAIT_TIMEOUT: + //Print error? + ; + break; + default: + //Print error? + ; + } + } + else { + //Print error? + ; + } + } + + if (selectResult) { + *selectForRead = (currEventMask & EV_RXCHAR) + && (checkRead) + && (bytesAvailable()); + *selectForWrite = (currEventMask & EV_TXEMPTY) && (checkWrite); + } + ::SetCommMask(m_descriptor, oldEventMask); //rerair old mask + return int(selectResult); +} + void SerialPortPrivateWin::detectDefaultSettings() { } +// Used only in method SerialPortPrivateWin::open(SerialPort::OpenMode mode). bool SerialPortPrivateWin::saveOldsettings() { - + DWORD confSize = sizeof(DCB); + if (0 == ::GetCommState(m_descriptor, &m_oldDCB)) + return false; + ::memcpy((void *)(&m_currDCB), (const void *)(&m_oldDCB), confSize); + + confSize = sizeof(COMMTIMEOUTS); + if (0 == ::GetCommTimeouts(m_descriptor, &m_oldCommTimeouts)) + return false; + ::memcpy((void *)(&m_currCommTimeouts), (const void *)(&m_oldCommTimeouts), confSize); + + m_oldSettingsIsSaved = true; + return true; } +// Used only in method SerialPortPrivateWin::close(). bool SerialPortPrivateWin::restoreOldsettings() { - + bool restoreResult = true; + if (m_oldSettingsIsSaved) { + m_oldSettingsIsSaved = false; + if (0 != ::GetCommState(m_descriptor, &m_oldDCB)) + restoreResult = false; + if (0 == ::SetCommTimeouts(m_descriptor, &m_oldCommTimeouts)) + restoreResult = false; + } + return restoreResult; } /* Private */ bool SerialPortPrivateWin::createEvents(bool rx, bool tx) { + if (rx) { m_ovRead.hEvent = ::CreateEvent(0, false, false, 0); } + if (tx) { m_ovWrite.hEvent = ::CreateEvent(0, false, false, 0); } + m_ovSelect.hEvent = ::CreateEvent(0, false, false, 0); + return ((rx && (0 == m_ovRead.hEvent)) + || (tx && (0 == m_ovWrite.hEvent)) + || (0 == m_ovSelect.hEvent)) ? false : true; } -bool SerialPortPrivateWin::closeEvents() const +void SerialPortPrivateWin::closeEvents() const { - + if (m_ovRead.hEvent) + ::CloseHandle(m_ovRead.hEvent); + if (m_ovWrite.hEvent) + ::CloseHandle(m_ovWrite.hEvent); + if (m_ovSelect.hEvent) + ::CloseHandle(m_ovSelect.hEvent); } void SerialPortPrivateWin::recalcTotalReadTimeoutConstant() @@ -155,14 +540,14 @@ void SerialPortPrivateWin::prepareCommTimeouts(CommTimeouts cto, DWORD msecs) } -bool SerialPortPrivateWin::updateDcb() +inline bool SerialPortPrivateWin::updateDcb() { - + return (0 != ::SetCommState(m_descriptor, &m_currDCB)); } -bool SerialPortPrivateWin::updateCommTimeouts() +inline bool SerialPortPrivateWin::updateCommTimeouts() { - + return (0 != ::SetCommTimeouts(m_descriptor, &m_currCommTimeouts)); } diff --git a/src/serialport_p_win.h b/src/serialport_p_win.h index 1712fba..9618e73 100644 --- a/src/serialport_p_win.h +++ b/src/serialport_p_win.h @@ -32,15 +32,23 @@ public: virtual qint64 read(char *data, qint64 len); virtual qint64 write(const char *data, qint64 len); - virtual bool waitForReadyRead(int msec); - virtual bool waitForBytesWritten(int msec); + virtual bool waitForReadOrWrite(int timeout, + bool checkRead, bool checkWrite, + bool *selectForRead, bool *selectForWrite); protected: + virtual QString nativeToSystemLocation(const QString &port) const; + virtual QString nativeFromSystemLocation(const QString &location) const; + virtual bool setNativeRate(int rate, SerialPort::Directions dir); virtual bool setNativeDataBits(SerialPort::DataBits dataBits); virtual bool setNativeParity(SerialPort::Parity parity); virtual bool setNativeStopBits(SerialPort::StopBits stopBits); virtual bool setNativeFlowControl(SerialPort::FlowControl flowControl); + + virtual bool setNativeDataInterval(int usecs); + virtual bool setNativeReadTimeout(int msecs); + virtual bool setNativeDataErrorPolicy(SerialPort::DataErrorPolicy policy); virtual void detectDefaultSettings(); @@ -55,14 +63,16 @@ private: WriteTotalTimeoutConstant }; - DCB mDCB, mOldDCB; - COMMTIMEOUTS mCommTimeouts, mOldCommTimeouts; - OVERLAPPED mOvRead; - OVERLAPPED mOvWrite; - OVERLAPPED mOvSelect; + DCB m_currDCB, m_oldDCB; + COMMTIMEOUTS m_currCommTimeouts, m_oldCommTimeouts; + OVERLAPPED m_ovRead; + OVERLAPPED m_ovWrite; + OVERLAPPED m_ovSelect; + + HANDLE m_descriptor; bool createEvents(bool rx, bool tx); - bool closeEvents() const; + void closeEvents() const; void recalcTotalReadTimeoutConstant(); void prepareCommTimeouts(CommTimeouts cto, DWORD msecs); bool updateDcb(); diff --git a/src/serialportinfo.cpp b/src/serialportinfo.cpp index 8e1ed73..4ef35c0 100644 --- a/src/serialportinfo.cpp +++ b/src/serialportinfo.cpp @@ -12,8 +12,8 @@ SerialPortInfo::SerialPortInfo() : d_ptr(0) {} -SerialPortInfo(const QString &port) - : d_ptr(new SerialPortInfoPrivate(port) +SerialPortInfo::SerialPortInfo(const QString &port) + : d_ptr(new SerialPortInfoPrivate(port)) {} SerialPortInfo::SerialPortInfo(const SerialPortInfo &other) @@ -21,7 +21,7 @@ SerialPortInfo::SerialPortInfo(const SerialPortInfo &other) {} SerialPortInfo::SerialPortInfo(const SerialPort &port) - : d_ptr(new SerialPortInfoPrivate(port.portName()) + : d_ptr(new SerialPortInfoPrivate(port.portName())) {} SerialPortInfo::~SerialPortInfo() @@ -78,10 +78,11 @@ bool SerialPortInfo::isBusy() const bool SerialPortInfo::isValid() const { Q_D(const SerialPortInfo); + /* if (d != 0) return SerialPort(d->portName).open(); - return false; + */ } QList<int> SerialPortInfo::standardRates() const @@ -89,7 +90,7 @@ QList<int> SerialPortInfo::standardRates() const QList<int> ret; Q_D(const SerialPortInfo); if (d != 0) { - + // } return ret; } diff --git a/src/serialportinfo_p.h b/src/serialportinfo_p.h index 39fd1cd..3f0dbc6 100644 --- a/src/serialportinfo_p.h +++ b/src/serialportinfo_p.h @@ -4,11 +4,21 @@ #ifndef SERIALPORTINFO_P_H #define SERIALPORTINFO_P_H +#include <QtCore/QString> +#include "serialportinfo.h" + class SerialPortInfoPrivate { public: + SerialPortInfoPrivate(const QString &port); + + QString portName; + QString device; + QString description; + QString manufacturer; + bool isBusy() const; }; #endif // SERIALPORTINFO_P_H diff --git a/src/serialportinfo_p_win.cpp b/src/serialportinfo_p_win.cpp index 03408a1..fb0799b 100644 --- a/src/serialportinfo_p_win.cpp +++ b/src/serialportinfo_p_win.cpp @@ -1,3 +1,17 @@ /* License... -*/
\ No newline at end of file +*/ + +#include "serialportinfo_p.h" + + + +SerialPortInfoPrivate::SerialPortInfoPrivate(const QString &port) +{ + +} + +bool SerialPortInfoPrivate::isBusy() const +{ + +} diff --git a/src/src.pri b/src/src.pri index 3c1cb75..51698d6 100644 --- a/src/src.pri +++ b/src/src.pri @@ -1,14 +1,28 @@ -HEADERS += include/serialport.h \ - src/abstractserialport_p.h \ - src/serialport_p.h \ - src/qserialdevice_global.h \ - +HEADERS += \ + serialport_p.h \ + serialportinfo_p.h -SOURCES += src/serialport.cpp +SOURCES += \ + src/serialport.cpp \ + src/serialportinfo.cpp win32 { - SOURCES += src/serialport_p_win.cpp + HEADERS += \ + serialport_p_win.h + SOURCES += \ + src/serialport_p_win.cpp \ + src/serialportinfo_p_win.cpp } unix { - SOURCES += src/serialport_p_unix.cpp + HEADERS += \ + serialport_p_unix.h + SOURCES += \ + src/serialport_p_unix.cpp + + macx { + SOURCES += src/serialportinfo_p_mac.cpp + } + !macx { + SOURCES += src/serialportinfo_p_unix.cpp + } } diff --git a/tests/EMPTYFILE b/tests/EMPTYFILE new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/EMPTYFILE |