1009 lines
18 KiB
C++
1009 lines
18 KiB
C++
//=========================================================================//
|
|
// //
|
|
// PonyProg - Serial Device Programmer //
|
|
// //
|
|
// Copyright (C) 1997-2019 Claudio Lanconelli //
|
|
// //
|
|
// http://ponyprog.sourceforge.net //
|
|
// //
|
|
//-------------------------------------------------------------------------//
|
|
// //
|
|
// This program is free software; you can redistribute it and/or //
|
|
// modify it under the terms of the GNU General Public License //
|
|
// as published by the Free Software Foundation; either version2 of //
|
|
// the License, or (at your option) any later version. //
|
|
// //
|
|
// This program is distributed in the hope that it will be useful, //
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //
|
|
// General Public License for more details. //
|
|
// //
|
|
// You should have received a copy of the GNU General Public License //
|
|
// along with this program (see LICENSE); if not, write to the //
|
|
// Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. //
|
|
// //
|
|
//=========================================================================//
|
|
|
|
// #include <stdio.h>
|
|
#include <QtCore>
|
|
#include <QDebug>
|
|
#include <QString>
|
|
|
|
#include "e2profil.h"
|
|
#include "rs232int.h"
|
|
#include "errcode.h"
|
|
|
|
#ifdef Q_OS_LINUX
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/time.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <termios.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
#define INVALID_HANDLE_VALUE -1
|
|
#endif
|
|
|
|
RS232Interface::RS232Interface()
|
|
{
|
|
qDebug() << "RS232Interface::RS232Interface()";
|
|
|
|
// profile = prof;
|
|
|
|
//COM default settings
|
|
actual_speed = 9600;
|
|
actual_parity = 'N';
|
|
actual_bits = 8;
|
|
actual_stops = 1;
|
|
actual_flowcontrol = 0; //No flow control by default
|
|
|
|
//NO timeouts by default
|
|
read_total_timeout = 0;
|
|
read_interval_timeout = 0;
|
|
|
|
wait_endTX_mode = false;
|
|
|
|
#ifdef Q_OS_WIN32
|
|
hCom = INVALID_HANDLE_VALUE;
|
|
#elif defined(Q_OS_LINUX)
|
|
fd = INVALID_HANDLE_VALUE;
|
|
#endif
|
|
|
|
//By default com_no == 0, so don't open any serial port if the constructor is called with zero paramameters
|
|
// OpenSerial(com_no);
|
|
|
|
qDebug() << "RS232Interface::RS232Interface() O";
|
|
}
|
|
|
|
RS232Interface::~RS232Interface()
|
|
{
|
|
qDebug() << "RS232Interface::~RS232Interface()";
|
|
|
|
CloseSerial();
|
|
}
|
|
|
|
|
|
#ifdef Q_OS_LINUX
|
|
static int fd_clear_flag(int fd, int flags);
|
|
#endif
|
|
|
|
int RS232Interface::OpenSerial(int no)
|
|
{
|
|
int ret_val = E2ERR_OPENFAILED;
|
|
QString devname;
|
|
|
|
if (no >= 0 && no < 32)
|
|
{
|
|
#ifdef Q_OS_WIN32
|
|
no++; //linux call ttyS0 --> COM1, ttyS1 --> COM2, etc..
|
|
#endif
|
|
devname = E2Profile::GetCOMDevName() + QString::number(no);
|
|
|
|
ret_val = OpenSerial(devname);
|
|
}
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
int RS232Interface::OpenSerial(QString devname)
|
|
{
|
|
qDebug() << "RS232Interface::OpenSerial(" << devname << ") I";
|
|
|
|
int ret_val = E2ERR_OPENFAILED;
|
|
|
|
m_devname = devname;
|
|
|
|
#ifdef Q_OS_WIN32
|
|
hCom = CreateFile((LPCWSTR)m_devname.utf16(),
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
0, /* comm devices must be opened w/exclusive-access */
|
|
NULL, /* no security attrs */
|
|
OPEN_EXISTING, /* comm devices must use OPEN_EXISTING */
|
|
0, /* not overlapped I/O */
|
|
NULL /* hTemplate must be NULL for comm devices */
|
|
);
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
GetCommState(hCom, &old_dcb);
|
|
GetCommTimeouts(hCom, &old_timeout);
|
|
GetCommMask(hCom, &old_mask);
|
|
|
|
if (wait_endTX_mode)
|
|
{
|
|
SetCommMask(hCom, EV_TXEMPTY);
|
|
}
|
|
else
|
|
{
|
|
SetCommMask(hCom, 0);
|
|
}
|
|
|
|
SetSerialTimeouts();
|
|
SetSerialParams();
|
|
|
|
ret_val = OK;
|
|
}
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
fd = INVALID_HANDLE_VALUE;
|
|
|
|
qDebug() << "RS232Interface::OpenSerial() now open the device " << m_devname;
|
|
|
|
fd = open(m_devname.toLatin1().constData(), O_RDWR | O_NONBLOCK | O_EXCL);
|
|
|
|
qDebug() << "RS232Interface::OpenSerial open result = " << fd;
|
|
|
|
if (fd < 0)
|
|
{
|
|
qDebug() << "RS232Interface::OpenSerial can't open the device " << devname;
|
|
return ret_val;
|
|
}
|
|
|
|
// Check for the needed IOCTLS
|
|
#if defined(TIOCSBRK) && defined(TIOCCBRK) //check if available for compilation
|
|
|
|
// Check if available during runtime
|
|
if ((ioctl(fd, TIOCSBRK, 0) == -1) || (ioctl(fd, TIOCCBRK, 0) == -1))
|
|
{
|
|
qDebug() << "RS232Interface::OpenPort IOCTL not available";
|
|
close(fd);
|
|
fd = INVALID_HANDLE_VALUE;
|
|
return ret_val;
|
|
}
|
|
#else
|
|
close(fd);
|
|
fd = INVALID_HANDLE_VALUE;
|
|
return ret_val;
|
|
#endif /*TIOCSBRK*/
|
|
|
|
/* open sets RTS and DTR, reset it */
|
|
#if defined(TIOCMGET) && defined(TIOCMSET) //check if available for compilation
|
|
int flags;
|
|
|
|
if (ioctl(fd, TIOCMGET, &flags) == -1)
|
|
{
|
|
qDebug() << "RS232Interface::OpenPort IOCTL not available";
|
|
close(fd);
|
|
fd = INVALID_HANDLE_VALUE;
|
|
return ret_val;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~(TIOCM_RTS | TIOCM_DTR);
|
|
|
|
if (ioctl(fd, TIOCMSET, &flags) == -1)
|
|
{
|
|
qDebug() << "RS232Interface::OpenPort IOCTL not available";
|
|
close(fd);
|
|
fd = INVALID_HANDLE_VALUE;
|
|
return ret_val;
|
|
}
|
|
}
|
|
#endif /*TIOCMGET */
|
|
|
|
qDebug() << "RS232Interface::OpenPort GETATTR";
|
|
|
|
if (tcgetattr(fd, &old_termios) == -1)
|
|
{
|
|
qDebug() << "RS232Interface::OpenPort GETATTR failed";
|
|
|
|
close(fd);
|
|
fd = INVALID_HANDLE_VALUE;
|
|
return ret_val;
|
|
}
|
|
|
|
qDebug() << "RS232Interface::OpenPort SetTimeouts && Params";
|
|
|
|
if (SetSerialTimeouts() != OK)
|
|
{
|
|
qDebug() << "RS232Interface::OpenPort SetSerialTimeouts() failed";
|
|
close(fd);
|
|
fd = INVALID_HANDLE_VALUE;
|
|
}
|
|
else if (SetSerialParams() != OK)
|
|
{
|
|
qDebug() << "RS232Interface::OpenPort SetSerialParams() failed";
|
|
close(fd);
|
|
fd = INVALID_HANDLE_VALUE;
|
|
}
|
|
else
|
|
{
|
|
fd_clear_flag(fd, O_NONBLOCK); //Restore to blocking mode
|
|
ret_val = OK;
|
|
}
|
|
#endif /*Q_OS_LINUX*/
|
|
|
|
qDebug() << "RS232Interface::OpenSerial() = " << ret_val << " O";
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
|
|
void RS232Interface::CloseSerial()
|
|
{
|
|
qDebug() << "RS232Interface::CloseSerial()";
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
// SetCommState(hCom, &old_dcb); //This can raise the RTS line, so invalidating the PowerOff
|
|
SetCommTimeouts(hCom, &old_timeout);
|
|
SetCommMask(hCom, old_mask);
|
|
PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);
|
|
|
|
CloseHandle(hCom);
|
|
hCom = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
if (fd != INVALID_HANDLE_VALUE)
|
|
{
|
|
// tcsetattr(fd, TCSAFLUSH, &old_termios); //This can raise the RTS line, so invalidating the PowerOff
|
|
close(fd);
|
|
fd = INVALID_HANDLE_VALUE;
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
int RS232Interface::SetSerialBreak(int state)
|
|
{
|
|
int result = E2ERR_OPENFAILED;
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (state)
|
|
{
|
|
SetCommBreak(hCom);
|
|
}
|
|
else
|
|
{
|
|
ClearCommBreak(hCom);
|
|
}
|
|
|
|
result = OK;
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
#if defined(TIOCSBRK) && defined(TIOCCBRK) //check if available for compilation
|
|
|
|
if (state)
|
|
{
|
|
result = ioctl(fd, TIOCSBRK, 0);
|
|
}
|
|
else
|
|
{
|
|
result = ioctl(fd, TIOCCBRK, 0);
|
|
}
|
|
|
|
#else
|
|
qDebug() << "RS232Interface::SetSerialBreak Can't get IOCTL";
|
|
#endif
|
|
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
void RS232Interface::SetSerialEventMask(long mask)
|
|
{
|
|
#ifdef Q_OS_WIN32
|
|
if (hCom != INVALID_HANDLE_VALUE )
|
|
SetCommMask(hCom, mask);
|
|
#endif
|
|
}
|
|
**/
|
|
|
|
void RS232Interface::SerialFlushRx()
|
|
{
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
PurgeComm(hCom, PURGE_RXCLEAR);
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
if (fd != INVALID_HANDLE_VALUE)
|
|
{
|
|
tcflush(fd, TCIFLUSH);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
void RS232Interface::SerialFlushTx()
|
|
{
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
PurgeComm(hCom, PURGE_TXCLEAR);
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
if (fd != INVALID_HANDLE_VALUE)
|
|
{
|
|
tcflush(fd, TCOFLUSH);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
void RS232Interface::WaitForTxEmpty()
|
|
{
|
|
#ifdef Q_OS_WIN32
|
|
DWORD evento;
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
do
|
|
{
|
|
WaitCommEvent(hCom, &evento, NULL);
|
|
}
|
|
while (!(evento & EV_TXEMPTY));
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
if (fd != INVALID_HANDLE_VALUE)
|
|
{
|
|
tcdrain(fd);
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
long RS232Interface::ReadSerial(uint8_t *buffer, long len)
|
|
{
|
|
long retval = E2ERR_OPENFAILED;
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
DWORD nread;
|
|
|
|
if (ReadFile(hCom, buffer, len, &nread, NULL))
|
|
{
|
|
retval = nread;
|
|
}
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
if (fd != INVALID_HANDLE_VALUE)
|
|
{
|
|
long nread, nleft;
|
|
uint8_t *ptr;
|
|
|
|
nleft = len;
|
|
ptr = buffer;
|
|
|
|
/* Wait up to N seconds. */
|
|
struct timeval tv;
|
|
|
|
tv.tv_sec = read_total_timeout / 1000;
|
|
tv.tv_usec = (read_total_timeout % 1000) * 1000;
|
|
|
|
while (nleft > 0)
|
|
{
|
|
fd_set rfds;
|
|
int rval;
|
|
|
|
/* Watch file fd to see when it has input. */
|
|
FD_ZERO(&rfds);
|
|
FD_SET(fd, &rfds);
|
|
|
|
rval = select(fd + 1, &rfds, NULL, NULL, &tv);
|
|
|
|
if (rval < 0) //Error
|
|
{
|
|
nleft = -1;
|
|
break;
|
|
}
|
|
else if (rval == 0) //Timeout
|
|
{
|
|
nleft = -1;
|
|
retval = E2P_TIMEOUT;
|
|
break;
|
|
}
|
|
else //Ok
|
|
{
|
|
nread = read(fd, ptr, nleft);
|
|
|
|
if (nread < 0)
|
|
{
|
|
nleft = -1;
|
|
break; //Error
|
|
}
|
|
}
|
|
|
|
nleft -= nread;
|
|
ptr += nread;
|
|
}
|
|
|
|
if (nleft >= 0)
|
|
{
|
|
retval = (len - nleft);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
return retval;
|
|
}
|
|
|
|
long RS232Interface::WriteSerial(uint8_t *buffer, long len)
|
|
{
|
|
long retval = E2ERR_OPENFAILED;
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
DWORD nwrite;
|
|
|
|
if (WriteFile(hCom, buffer, len, &nwrite, NULL))
|
|
{
|
|
retval = nwrite;
|
|
}
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
if (fd != INVALID_HANDLE_VALUE)
|
|
{
|
|
long nleft;
|
|
uint8_t *ptr;
|
|
|
|
ptr = buffer;
|
|
nleft = len;
|
|
|
|
while (nleft > 0)
|
|
{
|
|
long nwritten = write(fd, ptr, nleft);
|
|
|
|
if (nwritten <= 0)
|
|
{
|
|
return retval; //return error
|
|
}
|
|
|
|
nleft -= nwritten;
|
|
ptr += nwritten;
|
|
}
|
|
|
|
retval = len;
|
|
}
|
|
|
|
#endif
|
|
|
|
if (wait_endTX_mode)
|
|
{
|
|
WaitForTxEmpty();
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
// -1 ---> Not Change
|
|
int RS232Interface::SetSerialParams(long speed, int bits, int parity, int stops, int flow_control)
|
|
{
|
|
int result = E2ERR_OPENFAILED;
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (speed >= 300 && speed <= 115200)
|
|
{
|
|
actual_speed = speed;
|
|
}
|
|
|
|
if (bits >= 1 && bits <= 16)
|
|
{
|
|
actual_bits = bits;
|
|
}
|
|
|
|
if (parity == 'N' || parity == 'E' || parity == 'O')
|
|
{
|
|
actual_parity = parity;
|
|
}
|
|
|
|
if (stops >= 1 && stops <= 2)
|
|
{
|
|
actual_stops = stops;
|
|
}
|
|
|
|
if (flow_control >= 0 && flow_control <= 2)
|
|
{
|
|
actual_flowcontrol = flow_control;
|
|
}
|
|
|
|
QString dcb_str;
|
|
DCB com_dcb;
|
|
|
|
if (GetCommState(hCom, &com_dcb))
|
|
{
|
|
dcb_str.sprintf("baud=%ld parity=%c data=%d stop=%d", actual_speed, actual_parity, actual_bits, actual_stops);
|
|
// dcb_str[255] = '\0';
|
|
|
|
if (BuildCommDCB((LPCWSTR)dcb_str.utf16(), &com_dcb))
|
|
{
|
|
if (actual_flowcontrol == 0)
|
|
{
|
|
com_dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
|
com_dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
|
}
|
|
|
|
if (SetCommState(hCom, &com_dcb))
|
|
{
|
|
result = OK;
|
|
}
|
|
else
|
|
{
|
|
result = GetLastError();
|
|
}
|
|
|
|
PurgeComm(hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);
|
|
}
|
|
}
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
if (fd != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (speed >= 300 && speed <= 115200)
|
|
{
|
|
actual_speed = speed;
|
|
}
|
|
|
|
if (bits >= 1 && bits <= 16)
|
|
{
|
|
actual_bits = bits;
|
|
}
|
|
|
|
if (parity == 'N' || parity == 'E' || parity == 'O')
|
|
{
|
|
actual_parity = parity;
|
|
}
|
|
|
|
if (stops >= 1 && stops <= 2)
|
|
{
|
|
actual_stops = stops;
|
|
}
|
|
|
|
if (flow_control >= 0 && flow_control <= 2)
|
|
{
|
|
actual_flowcontrol = flow_control;
|
|
}
|
|
|
|
struct termios termios;
|
|
|
|
if (tcgetattr(fd, &termios) != 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
cfmakeraw(&termios);
|
|
termios.c_cflag |= CLOCAL; //Disable modem status line check
|
|
|
|
//Flow control
|
|
if (actual_flowcontrol == 0)
|
|
{
|
|
termios.c_cflag &= ~CRTSCTS; //Disable hardware flow control
|
|
termios.c_iflag &= ~(IXON | IXOFF); //Disable software flow control
|
|
}
|
|
else if (actual_flowcontrol == 1)
|
|
{
|
|
termios.c_cflag |= CRTSCTS;
|
|
termios.c_iflag &= ~(IXON | IXOFF);
|
|
}
|
|
else
|
|
{
|
|
termios.c_cflag &= ~CRTSCTS;
|
|
termios.c_iflag |= (IXON | IXOFF);
|
|
}
|
|
|
|
//Set size of bits
|
|
termios.c_cflag &= ~CSIZE;
|
|
|
|
if (actual_bits <= 5)
|
|
{
|
|
termios.c_cflag |= CS5;
|
|
}
|
|
else if (actual_bits == 6)
|
|
{
|
|
termios.c_cflag |= CS6;
|
|
}
|
|
else if (actual_bits == 7)
|
|
{
|
|
termios.c_cflag |= CS7;
|
|
}
|
|
else
|
|
{
|
|
termios.c_cflag |= CS8;
|
|
}
|
|
|
|
//Set stop bits
|
|
if (actual_stops == 2)
|
|
{
|
|
termios.c_cflag |= CSTOPB;
|
|
}
|
|
else
|
|
{
|
|
termios.c_cflag &= ~CSTOPB;
|
|
}
|
|
|
|
//Set parity bit
|
|
if (actual_parity == 'N')
|
|
{
|
|
termios.c_cflag &= ~PARENB;
|
|
}
|
|
else if (actual_parity == 'E')
|
|
{
|
|
termios.c_cflag |= PARENB;
|
|
termios.c_cflag &= ~PARODD;
|
|
}
|
|
else
|
|
{
|
|
//'O'
|
|
termios.c_cflag |= (PARENB | PARODD);
|
|
}
|
|
|
|
//Set speed
|
|
speed_t baudrate;
|
|
|
|
switch (speed)
|
|
{
|
|
case 300:
|
|
baudrate = B300;
|
|
break;
|
|
|
|
case 600:
|
|
baudrate = B600;
|
|
break;
|
|
|
|
case 1200:
|
|
baudrate = B1200;
|
|
break;
|
|
|
|
case 2400:
|
|
baudrate = B2400;
|
|
break;
|
|
|
|
case 4800:
|
|
baudrate = B4800;
|
|
break;
|
|
|
|
case 9600:
|
|
baudrate = B9600;
|
|
break;
|
|
|
|
case 19200:
|
|
baudrate = B19200;
|
|
break;
|
|
|
|
case 38400:
|
|
baudrate = B38400;
|
|
break;
|
|
|
|
case 57600:
|
|
baudrate = B57600;
|
|
break;
|
|
|
|
case 115200:
|
|
baudrate = B115200;
|
|
break;
|
|
|
|
case 230400:
|
|
baudrate = B230400;
|
|
break;
|
|
|
|
default:
|
|
baudrate = B9600;
|
|
break;
|
|
}
|
|
|
|
cfsetispeed(&termios, baudrate);
|
|
cfsetospeed(&termios, baudrate);
|
|
|
|
termios.c_cc[VMIN] = 1;
|
|
termios.c_cc[VTIME] = 0;
|
|
|
|
if (tcsetattr(fd, TCSANOW, &termios) == 0)
|
|
{
|
|
result = OK;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
//At the moment the while_read (interval timeout) is not used with Linux
|
|
int RS232Interface::SetSerialTimeouts(long init_read, long while_read)
|
|
{
|
|
long result = E2ERR_OPENFAILED;
|
|
|
|
if (while_read >= 0)
|
|
{
|
|
read_interval_timeout = while_read;
|
|
}
|
|
|
|
if (init_read >= 0)
|
|
{
|
|
read_total_timeout = init_read;
|
|
}
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
COMMTIMEOUTS new_timeout;
|
|
|
|
// new_timeout = old_timeout;
|
|
|
|
/*
|
|
* Set to asynchronous mode: the read operation is to
|
|
* return immediately with the characters that have
|
|
* already been received, even if no characters have
|
|
* been received.
|
|
*
|
|
* ReadIntervalTimeout = MAXDWORD;
|
|
* ReadTotalTimeoutMultiplier = 0;
|
|
* ReadTotalTimeoutConstant = 0;
|
|
*/
|
|
|
|
/*
|
|
* Windows 95: Set to UNIX read() syscall behaviour
|
|
*
|
|
* ReadIntervalTimeout = MAXDWORD;
|
|
* readTotalTimeoutMultiplier = MAXDWORD;
|
|
* ReadTotalTimeoutConstant = X (X > 0 && X < MAXDWORD)
|
|
*/
|
|
|
|
new_timeout.ReadIntervalTimeout = read_interval_timeout;
|
|
new_timeout.ReadTotalTimeoutMultiplier = 0;
|
|
new_timeout.ReadTotalTimeoutConstant = read_total_timeout;
|
|
|
|
//Disable write timeouts
|
|
new_timeout.WriteTotalTimeoutMultiplier = 0;
|
|
new_timeout.WriteTotalTimeoutConstant = 0;
|
|
|
|
if (SetCommTimeouts(hCom, &new_timeout))
|
|
{
|
|
result = OK;
|
|
}
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
result = OK;
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
int RS232Interface::SetSerialDTR(int dtr)
|
|
{
|
|
int result = E2ERR_OPENFAILED;
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (EscapeCommFunction(hCom, dtr ? SETDTR : CLRDTR))
|
|
{
|
|
result = OK;
|
|
}
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
int flags;
|
|
|
|
ioctl(fd, TIOCMGET, &flags);
|
|
|
|
if (dtr)
|
|
{
|
|
flags |= TIOCM_DTR;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~TIOCM_DTR;
|
|
}
|
|
|
|
result = ioctl(fd, TIOCMSET, &flags);
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
int RS232Interface::SetSerialRTS(int rts)
|
|
{
|
|
int result = E2ERR_OPENFAILED;
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (EscapeCommFunction(hCom, rts ? SETRTS : CLRRTS))
|
|
{
|
|
result = OK;
|
|
}
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
int flags;
|
|
|
|
ioctl(fd, TIOCMGET, &flags);
|
|
|
|
if (rts)
|
|
{
|
|
flags |= TIOCM_RTS;
|
|
}
|
|
else
|
|
{
|
|
flags &= ~TIOCM_RTS;
|
|
}
|
|
|
|
result = ioctl(fd, TIOCMSET, &flags);
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
int RS232Interface::SetSerialRTSDTR(int state)
|
|
{
|
|
int result = E2ERR_OPENFAILED;
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
if (state)
|
|
{
|
|
EscapeCommFunction(hCom, SETRTS);
|
|
EscapeCommFunction(hCom, SETDTR);
|
|
}
|
|
else
|
|
{
|
|
EscapeCommFunction(hCom, CLRRTS);
|
|
EscapeCommFunction(hCom, CLRDTR);
|
|
}
|
|
|
|
result = OK;
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
int flags;
|
|
ioctl(fd, TIOCMGET, &flags);
|
|
|
|
if (state)
|
|
{
|
|
flags |= (TIOCM_RTS | TIOCM_DTR);
|
|
}
|
|
else
|
|
{
|
|
flags &= ~(TIOCM_RTS | TIOCM_DTR);
|
|
}
|
|
|
|
result = ioctl(fd, TIOCMSET, &flags);
|
|
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
int RS232Interface::GetSerialDSR() const
|
|
{
|
|
int result = E2ERR_OPENFAILED;
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
DWORD status;
|
|
|
|
if (GetCommModemStatus(hCom, &status))
|
|
{
|
|
result = (status & MS_DSR_ON);
|
|
}
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
int flags;
|
|
|
|
if (ioctl(fd, TIOCMGET, &flags) != -1)
|
|
{
|
|
result = (flags & TIOCM_DSR);
|
|
}
|
|
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
int RS232Interface::GetSerialCTS() const
|
|
{
|
|
int result = E2ERR_OPENFAILED;
|
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
if (hCom != INVALID_HANDLE_VALUE)
|
|
{
|
|
DWORD status;
|
|
|
|
if (GetCommModemStatus(hCom, &status))
|
|
{
|
|
result = (status & MS_CTS_ON);
|
|
}
|
|
}
|
|
|
|
#elif defined(Q_OS_LINUX)
|
|
|
|
int flags;
|
|
|
|
if (ioctl(fd, TIOCMGET, &flags) != -1)
|
|
{
|
|
result = (flags & TIOCM_CTS);
|
|
}
|
|
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
#ifdef Q_OS_LINUX
|
|
static int fd_clear_flag(int fd, int flags)
|
|
{
|
|
int val;
|
|
|
|
if ((val = fcntl(fd, F_GETFL, 0)) < 0)
|
|
{
|
|
return val;
|
|
}
|
|
|
|
val &= ~flags;
|
|
|
|
if (fcntl(fd, F_SETFL, val) < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|