/**************************************************************************** ** Copyright (c) 2000-2003 Wayne Roth ** Copyright (c) 2004-2007 Stefan Sander ** Copyright (c) 2007 Michal Policht ** Copyright (c) 2008 Brandon Fosdick ** Copyright (c) 2009-2010 Liam Staskawicz ** Copyright (c) 2011 Debao Zhang ** All right reserved. ** Web: http://code.google.com/p/qextserialport/ ** ** Permission is hereby granted, free of charge, to any person obtaining ** a copy of this software and associated documentation files (the ** "Software"), to deal in the Software without restriction, including ** without limitation the rights to use, copy, modify, merge, publish, ** distribute, sublicense, and/or sell copies of the Software, and to ** permit persons to whom the Software is furnished to do so, subject to ** the following conditions: ** ** The above copyright notice and this permission notice shall be ** included in all copies or substantial portions of the Software. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ** LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION ** OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ** WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ** ****************************************************************************/ #ifndef _QEXTSERIALPORT_P_H_ #define _QEXTSERIALPORT_P_H_ // // W A R N I N G // ------------- // // This file is not part of the QESP API. It exists for the convenience // of other QESP classes. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include "qextserialport.h" #include #ifdef Q_OS_UNIX # include #elif (defined Q_OS_WIN) # include #endif #include // This is QextSerialPort's read buffer, needed by posix system. // ref: QRingBuffer & QIODevicePrivateLinearBuffer class QextReadBuffer { public: inline QextReadBuffer(size_t growth=4096) : len(0), first(0), buf(0), capacity(0), basicBlockSize(growth) { } ~QextReadBuffer() { delete [] buf; } inline void clear() { first = buf; len = 0; } inline int size() const { return len; } inline bool isEmpty() const { return len == 0; } inline int read(char* target, int size) { int r = qMin(size, len); if (r == 1) { *target = *first; --len; ++first; } else { memcpy(target, first, r); len -= r; first += r; } return r; } inline char* reserve(size_t size) { if ((first - buf) + len + size > capacity) { size_t newCapacity = qMax(capacity, basicBlockSize); while (newCapacity < size) newCapacity *= 2; if (newCapacity > capacity) { // allocate more space char* newBuf = new char[newCapacity]; memmove(newBuf, first, len); delete [] buf; buf = newBuf; capacity = newCapacity; } else { // shift any existing data to make space memmove(buf, first, len); } first = buf; } char* writePtr = first + len; len += (int)size; return writePtr; } inline void chop(int size) { if (size >= len) { clear(); } else { len -= size; } } inline void squeeze() { if (first != buf) { memmove(buf, first, len); first = buf; } size_t newCapacity = basicBlockSize; while (newCapacity < size_t(len)) newCapacity *= 2; if (newCapacity < capacity) { char * tmp = static_cast(realloc(buf, newCapacity)); if (tmp) { buf = tmp; capacity = newCapacity; } } } inline QByteArray readAll() { char* f = first; int l = len; clear(); return QByteArray(f, l); } inline int readLine(char* target, int size) { int r = qMin(size, len); char* eol = static_cast(memchr(first, '\n', r)); if (eol) r = 1+(eol-first); memcpy(target, first, r); len -= r; first += r; return int(r); } inline bool canReadLine() const { return memchr(first, '\n', len); } private: int len; char* first; char* buf; size_t capacity; size_t basicBlockSize; }; class QextWinEventNotifier; class QWinEventNotifier; class QReadWriteLock; class QSocketNotifier; class QextSerialPortPrivate { Q_DECLARE_PUBLIC(QextSerialPort) public: QextSerialPortPrivate(QextSerialPort * q); ~QextSerialPortPrivate(); enum DirtyFlagEnum { DFE_BaudRate = 0x0001, DFE_Parity = 0x0002, DFE_StopBits = 0x0004, DFE_DataBits = 0x0008, DFE_Flow = 0x0010, DFE_TimeOut = 0x0100, DFE_ALL = 0x0fff, DFE_Settings_Mask = 0x00ff //without TimeOut }; mutable QReadWriteLock lock; QString port; PortSettings Settings; QextReadBuffer readBuffer; int settingsDirtyFlags; ulong lastErr; QextSerialPort::QueryMode _queryMode; // platform specific members #ifdef Q_OS_UNIX int fd; QSocketNotifier *readNotifier; struct termios Posix_CommConfig; struct termios old_termios; #elif (defined Q_OS_WIN) HANDLE Win_Handle; OVERLAPPED overlap; COMMCONFIG Win_CommConfig; COMMTIMEOUTS Win_CommTimeouts; # ifndef QESP_NO_QT4_PRIVATE QWinEventNotifier *winEventNotifier; # else QextWinEventNotifier *winEventNotifier; # endif DWORD eventMask; QList pendingWrites; QReadWriteLock* bytesToWriteLock; qint64 _bytesToWrite; #endif /*fill PortSettings*/ void setBaudRate(BaudRateType baudRate, bool update=true); void setDataBits(DataBitsType dataBits, bool update=true); void setParity(ParityType parity, bool update=true); void setStopBits(StopBitsType stopbits, bool update=true); void setFlowControl(FlowType flow, bool update=true); void setTimeout(long millisec, bool update=true); void setPortSettings(const PortSettings& settings, bool update=true); void platformSpecificDestruct(); void platformSpecificInit(); void translateError(ulong error); void updatePortSettings(); qint64 readData_sys(char * data, qint64 maxSize); qint64 writeData_sys(const char * data, qint64 maxSize); void setDtr_sys(bool set=true); void setRts_sys(bool set=true); bool open_sys(QIODevice::OpenMode mode); bool close_sys(); bool flush_sys(); ulong lineStatus_sys(); qint64 bytesAvailable_sys() const; #ifdef Q_OS_WIN void _q_onWinEvent(HANDLE h); #endif void _q_canRead(); QextSerialPort * q_ptr; }; #endif //_QEXTSERIALPORT_P_H_