278 lines
6.2 KiB
C++
278 lines
6.2 KiB
C++
/****************************************************************************
|
|
** 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 <QtCore/QReadWriteLock>
|
|
#ifdef Q_OS_UNIX
|
|
# include <termios.h>
|
|
#elif (defined Q_OS_WIN)
|
|
# include <QtCore/qt_windows.h>
|
|
#endif
|
|
#include <stdlib.h>
|
|
|
|
// 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 < len + 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<char *>(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<char *>(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 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 currentTermios;
|
|
struct termios oldTermios;
|
|
#elif (defined Q_OS_WIN)
|
|
HANDLE handle;
|
|
OVERLAPPED overlap;
|
|
COMMCONFIG commConfig;
|
|
COMMTIMEOUTS commTimeouts;
|
|
QWinEventNotifier *winEventNotifier;
|
|
DWORD eventMask;
|
|
QList<OVERLAPPED *> pendingWrites;
|
|
QReadWriteLock *bytesToWriteLock;
|
|
#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_
|