|
@@ -9,6 +9,9 @@
|
|
|
#include <ctype.h>
|
|
|
#include <sys/file.h>
|
|
|
#include <dirent.h>
|
|
|
+#include <linux/serial.h>
|
|
|
+#include <sys/ioctl.h>
|
|
|
+#include <asm-generic/ioctls.h>
|
|
|
#include "gfaserial.h"
|
|
|
|
|
|
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
|
@@ -22,10 +25,12 @@ typedef struct _GFA_SERIAL_DEVICE
|
|
|
int fd;
|
|
|
bool bFdLocked;
|
|
|
bool bAttrSet;
|
|
|
+ bool bRS485Set;
|
|
|
char *pszDeviceName;
|
|
|
GFA_SER_CFG_PARAMS cfg;
|
|
|
struct termios tty;
|
|
|
struct termios ttySave;
|
|
|
+ struct serial_rs485 rs485Save;
|
|
|
struct timeval tvRX;
|
|
|
struct timeval tvTX;
|
|
|
struct timeval tvEcho;
|
|
@@ -79,7 +84,7 @@ static int _GetDeviceAccess(const char *pszDev)
|
|
|
const char *pszRp;
|
|
|
const struct dirent *pde, *pde2;
|
|
|
char szDir[512], szPath[512], szRealPath[512];
|
|
|
-
|
|
|
+
|
|
|
if((pd = opendir("/proc")))
|
|
|
{
|
|
|
while((pde = readdir(pd)))
|
|
@@ -107,8 +112,8 @@ static int _GetDeviceAccess(const char *pszDev)
|
|
|
|
|
|
closedir(pd2);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -184,6 +189,50 @@ static bool _ReadEcho(HGFADEVICE hSer, const void *pData, size_t nWritten)
|
|
|
return (nRead == (ssize_t)nWritten);
|
|
|
}
|
|
|
|
|
|
+#if 0
|
|
|
+static void _SetRTS(LPGFA_SERIAL_DEVICE psd, bool bOn)
|
|
|
+{
|
|
|
+ int flags = 0;
|
|
|
+ ioctl(psd->fd, TIOCMGET, &flags);
|
|
|
+ if(bOn)
|
|
|
+ flags |= TIOCM_RTS;
|
|
|
+ else
|
|
|
+ flags &= ~TIOCM_RTS;
|
|
|
+ ioctl(psd->fd, TIOCMSET, &flags);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+static int _SetRS485(LPGFA_SERIAL_DEVICE psd, bool bSet)
|
|
|
+{
|
|
|
+ int nRet;
|
|
|
+ struct serial_rs485 rs485;
|
|
|
+
|
|
|
+ if(bSet)
|
|
|
+ {
|
|
|
+ if(psd->bRS485Set)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if((nRet = ioctl(psd->fd, TIOCGRS485, &psd->rs485Save)) < 0)
|
|
|
+ return nRet;
|
|
|
+
|
|
|
+ memset(&rs485, 0, sizeof(rs485));
|
|
|
+ rs485.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;
|
|
|
+ if(!psd->cfg.bHandleTxEcho)
|
|
|
+ rs485.flags |= SER_RS485_RX_DURING_TX;
|
|
|
+ rs485.delay_rts_after_send = 0;
|
|
|
+ rs485.delay_rts_before_send = 0;
|
|
|
+ rs485.udelay_before_enable_tx = 10;
|
|
|
+ psd->bRS485Set = true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ memcpy(&rs485, &psd->rs485Save, sizeof(rs485));
|
|
|
+ psd->bRS485Set = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ioctl(psd->fd, TIOCSRS485, &rs485);
|
|
|
+}
|
|
|
+
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
@@ -196,14 +245,14 @@ HGFADEVICE GfaSerialOpen(const char *pszDeviceName, LPCGFA_SER_CFG_PARAMS pscp,
|
|
|
LPGFA_SERIAL_DEVICE psd = malloc(sizeof(GFA_SERIAL_DEVICE));
|
|
|
memset(psd, 0, sizeof(GFA_SERIAL_DEVICE));
|
|
|
psd->fd = -1;
|
|
|
-
|
|
|
+
|
|
|
if((nDevAcc = _GetDeviceAccess(pszDeviceName)) > 0)
|
|
|
{
|
|
|
GfaSerialClose(psd);
|
|
|
errno = EBUSY;
|
|
|
return NULL;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
// Open the device
|
|
|
|
|
@@ -217,7 +266,7 @@ HGFADEVICE GfaSerialOpen(const char *pszDeviceName, LPCGFA_SER_CFG_PARAMS pscp,
|
|
|
GfaSerialClose(psd);
|
|
|
return NULL;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
// Lock device descriptor exclusive
|
|
|
|
|
@@ -226,9 +275,9 @@ HGFADEVICE GfaSerialOpen(const char *pszDeviceName, LPCGFA_SER_CFG_PARAMS pscp,
|
|
|
GfaSerialClose(psd);
|
|
|
return NULL;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
psd->bFdLocked = true;
|
|
|
-
|
|
|
+
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
// Get current config and save it for restore on close
|
|
|
|
|
@@ -237,7 +286,7 @@ HGFADEVICE GfaSerialOpen(const char *pszDeviceName, LPCGFA_SER_CFG_PARAMS pscp,
|
|
|
GfaSerialClose(psd);
|
|
|
return NULL;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
// Set new config
|
|
|
|
|
@@ -249,6 +298,19 @@ HGFADEVICE GfaSerialOpen(const char *pszDeviceName, LPCGFA_SER_CFG_PARAMS pscp,
|
|
|
|
|
|
psd->bAttrSet = true;
|
|
|
|
|
|
+ /////////////////////////////////////////////////////////////////////
|
|
|
+ // Set RS485 mode, if enabled
|
|
|
+
|
|
|
+ if(psd->cfg.bIsRS485)
|
|
|
+ {
|
|
|
+ if(_SetRS485(psd, true) < 0)
|
|
|
+ {
|
|
|
+ GfaSerialClose(psd);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ psd->cfg.bHandleTxEcho = false; // now handled by RS485 driver
|
|
|
+ }
|
|
|
+
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
// Set deault timeouts.
|
|
|
|
|
@@ -276,6 +338,8 @@ void GfaSerialClose(HGFADEVICE hSer)
|
|
|
LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
|
|
|
if(psd->fd >= 0)
|
|
|
{
|
|
|
+ if(psd->cfg.bIsRS485)
|
|
|
+ _SetRS485(psd, false);
|
|
|
if(psd->bAttrSet)
|
|
|
tcsetattr(psd->fd, TCSAFLUSH, &psd->ttySave);
|
|
|
if(psd->bFdLocked)
|
|
@@ -468,6 +532,8 @@ int GfaSerialSetConfig(HGFADEVICE hSer, LPCGFA_SER_CFG_PARAMS pscp, size_t nSize
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
|
// set configuration
|
|
|
|
|
|
+ tcflush(psd->fd, TCIOFLUSH);
|
|
|
+
|
|
|
if((nRet = tcsetattr(psd->fd, TCSANOW/*TCSAFLUSH*/, &psd->tty)) == 0)
|
|
|
memcpy(&psd->cfg, pscp, sizeof(GFA_SER_CFG_PARAMS));
|
|
|
return nRet;
|
|
@@ -563,6 +629,7 @@ ssize_t GfaSerialPurgeRXBuffer(HGFADEVICE hSer)
|
|
|
uint8_t b[256];
|
|
|
ssize_t nRet = 0, nRx;
|
|
|
LPGFA_SERIAL_DEVICE psd = (LPGFA_SERIAL_DEVICE)hSer;
|
|
|
+ tcflush(psd->fd, TCIFLUSH);
|
|
|
GfaSerialSetTimeouts(hSer, &psd->tvPurge, NULL);
|
|
|
|
|
|
while((nRx = GfaSerialReceive(hSer, b, sizeof(b))) > 0)
|
|
@@ -641,7 +708,9 @@ ssize_t GfaSerialTransmit(HGFADEVICE hSer, const void *pData, size_t nCbToWrite)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
+// _SetRTS(psd, true);
|
|
|
nRet = write(psd->fd, pszData, nCbToWrite - nWritten);
|
|
|
+// _SetRTS(psd, false);
|
|
|
|
|
|
if(nRet < 0)
|
|
|
return -1;
|