Commit b569f302 authored by deuce's avatar deuce
Browse files

Cleanup and update Get/SetFlowControl functions for *nix.

parent dccfd996
......@@ -5,227 +5,241 @@
/* $Id$ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* See the GNU Lesser General Public License for more details: lgpl.txt or *
* http://www.fsf.org/copyleft/lesser.html *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to mods@synchro.net *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* See the GNU Lesser General Public License for more details: lgpl.txt or *
* http://www.fsf.org/copyleft/lesser.html *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to mods@synchro.net *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include <sys/ioctl.h>
#include <sys/file.h>
#include <fcntl.h> // O_NONBLOCK
#include <fcntl.h> // O_NONBLOCK
#include "comio.h"
#include "genwrap.h"
#if defined(CCTS_OFLOW) && defined(CRTS_IFLOW)
#define CTSRTS_FLOW_CFLAGS (CCTS_OFLOW | CRTS_IFLOW)
#elif defined(CRTSCTS)
#define CTSRTS_FLOW_CFLAGS (CRTSCTS)
#else
#error No way to control CTS/RTS flow control
#endif
#if defined(IXON) && defined (IXOFF)
#define XONXOFF_FLOW_IFLAGS (IXON | IXOFF)
#else
#error No way to control XON/XOFF flow control
#endif
#ifdef SPEED_MACROS_ONLY
#define SUPPORTED_SPEED(x) \
if (speed <= (x)) \
return B##x
if (speed <= (x)) \
return B##x
speed_t rate_to_macro(unsigned long speed)
{
// Standard values
SUPPORTED_SPEED(0);
SUPPORTED_SPEED(50);
SUPPORTED_SPEED(75);
SUPPORTED_SPEED(110);
SUPPORTED_SPEED(134);
SUPPORTED_SPEED(150);
SUPPORTED_SPEED(200);
SUPPORTED_SPEED(300);
SUPPORTED_SPEED(600);
SUPPORTED_SPEED(1200);
SUPPORTED_SPEED(1800);
SUPPORTED_SPEED(2400);
SUPPORTED_SPEED(4800);
SUPPORTED_SPEED(9600);
SUPPORTED_SPEED(19200);
SUPPORTED_SPEED(38400);
// Non-POSIX
// Standard values
SUPPORTED_SPEED(0);
SUPPORTED_SPEED(50);
SUPPORTED_SPEED(75);
SUPPORTED_SPEED(110);
SUPPORTED_SPEED(134);
SUPPORTED_SPEED(150);
SUPPORTED_SPEED(200);
SUPPORTED_SPEED(300);
SUPPORTED_SPEED(600);
SUPPORTED_SPEED(1200);
SUPPORTED_SPEED(1800);
SUPPORTED_SPEED(2400);
SUPPORTED_SPEED(4800);
SUPPORTED_SPEED(9600);
SUPPORTED_SPEED(19200);
SUPPORTED_SPEED(38400);
// Non-POSIX
#ifdef B57600
SUPPORTED_SPEED(57600);
SUPPORTED_SPEED(57600);
#endif
#ifdef B115200
SUPPORTED_SPEED(115200);
SUPPORTED_SPEED(115200);
#endif
#ifdef B230400
SUPPORTED_SPEED(230400);
SUPPORTED_SPEED(230400);
#endif
#ifdef B460800
SUPPORTED_SPEED(460800);
SUPPORTED_SPEED(460800);
#endif
#ifdef B500000
SUPPORTED_SPEED(500000);
SUPPORTED_SPEED(500000);
#endif
#ifdef B576000
SUPPORTED_SPEED(576000);
SUPPORTED_SPEED(576000);
#endif
#ifdef B921600
SUPPORTED_SPEED(921600);
SUPPORTED_SPEED(921600);
#endif
#ifdef B1000000
SUPPORTED_SPEED(1000000);
SUPPORTED_SPEED(1000000);
#endif
#ifdef B1152000
SUPPORTED_SPEED(1152000);
SUPPORTED_SPEED(1152000);
#endif
#ifdef B1500000
SUPPORTED_SPEED(1500000);
SUPPORTED_SPEED(1500000);
#endif
#ifdef B2000000
SUPPORTED_SPEED(2000000);
SUPPORTED_SPEED(2000000);
#endif
#ifdef B2500000
SUPPORTED_SPEED(2500000);
SUPPORTED_SPEED(2500000);
#endif
#ifdef B3000000
SUPPORTED_SPEED(3000000);
SUPPORTED_SPEED(3000000);
#endif
#ifdef B3500000
SUPPORTED_SPEED(3500000);
SUPPORTED_SPEED(3500000);
#endif
#ifdef B4000000
SUPPORTED_SPEED(4000000);
SUPPORTED_SPEED(4000000);
#endif
return B0;
return B0;
}
#undef SUPPORTED_SPEED
#define SUPPORTED_SPEED(x) \
if (speed == B##x) \
return x;
if (speed == B##x) \
return x;
unsigned long macro_to_rate(speed_t speed)
{
// Standard values
SUPPORTED_SPEED(0);
SUPPORTED_SPEED(50);
SUPPORTED_SPEED(75);
SUPPORTED_SPEED(110);
SUPPORTED_SPEED(134);
SUPPORTED_SPEED(150);
SUPPORTED_SPEED(200);
SUPPORTED_SPEED(300);
SUPPORTED_SPEED(600);
SUPPORTED_SPEED(1200);
SUPPORTED_SPEED(1800);
SUPPORTED_SPEED(2400);
SUPPORTED_SPEED(4800);
SUPPORTED_SPEED(9600);
SUPPORTED_SPEED(19200);
SUPPORTED_SPEED(38400);
// Non-POSIX
// Standard values
SUPPORTED_SPEED(0);
SUPPORTED_SPEED(50);
SUPPORTED_SPEED(75);
SUPPORTED_SPEED(110);
SUPPORTED_SPEED(134);
SUPPORTED_SPEED(150);
SUPPORTED_SPEED(200);
SUPPORTED_SPEED(300);
SUPPORTED_SPEED(600);
SUPPORTED_SPEED(1200);
SUPPORTED_SPEED(1800);
SUPPORTED_SPEED(2400);
SUPPORTED_SPEED(4800);
SUPPORTED_SPEED(9600);
SUPPORTED_SPEED(19200);
SUPPORTED_SPEED(38400);
// Non-POSIX
#ifdef B57600
SUPPORTED_SPEED(57600);
SUPPORTED_SPEED(57600);
#endif
#ifdef B115200
SUPPORTED_SPEED(115200);
SUPPORTED_SPEED(115200);
#endif
#ifdef B230400
SUPPORTED_SPEED(230400);
SUPPORTED_SPEED(230400);
#endif
#ifdef B460800
SUPPORTED_SPEED(460800);
SUPPORTED_SPEED(460800);
#endif
#ifdef B500000
SUPPORTED_SPEED(500000);
SUPPORTED_SPEED(500000);
#endif
#ifdef B576000
SUPPORTED_SPEED(576000);
SUPPORTED_SPEED(576000);
#endif
#ifdef B921600
SUPPORTED_SPEED(921600);
SUPPORTED_SPEED(921600);
#endif
#ifdef B1000000
SUPPORTED_SPEED(1000000);
SUPPORTED_SPEED(1000000);
#endif
#ifdef B1152000
SUPPORTED_SPEED(1152000);
SUPPORTED_SPEED(1152000);
#endif
#ifdef B1500000
SUPPORTED_SPEED(1500000);
SUPPORTED_SPEED(1500000);
#endif
#ifdef B2000000
SUPPORTED_SPEED(2000000);
SUPPORTED_SPEED(2000000);
#endif
#ifdef B2500000
SUPPORTED_SPEED(2500000);
SUPPORTED_SPEED(2500000);
#endif
#ifdef B3000000
SUPPORTED_SPEED(3000000);
SUPPORTED_SPEED(3000000);
#endif
#ifdef B3500000
SUPPORTED_SPEED(3500000);
SUPPORTED_SPEED(3500000);
#endif
#ifdef B4000000
SUPPORTED_SPEED(4000000);
SUPPORTED_SPEED(4000000);
#endif
return 0;
return 0;
}
#undef SUPPORTED_SPEED
#else
#define rate_to_macro(x) (x)
#define macro_to_rate(x) (x)
#define rate_to_macro(x) (x)
#define macro_to_rate(x) (x)
#endif
char* comVersion(char* str, size_t len)
{
char revision[16];
char revision[16];
sscanf("$Revision$", "%*s %s", revision);
sscanf("$Revision$", "%*s %s", revision);
safe_snprintf(str,len,"Synchronet Communications I/O Library for "PLATFORM_DESC" v%s", revision);
return str;
safe_snprintf(str,len,"Synchronet Communications I/O Library for "PLATFORM_DESC" v%s", revision);
return str;
}
COM_HANDLE comOpen(const char* device)
{
COM_HANDLE handle;
struct termios t;
if((handle=open(device, O_NONBLOCK|O_RDWR))==COM_HANDLE_INVALID)
return COM_HANDLE_INVALID;
if(tcgetattr(handle, &t)==-1) {
close(handle);
return COM_HANDLE_INVALID;
}
t.c_iflag = (
IGNBRK /* ignore BREAK condition */
| IGNPAR /* ignore (discard) parity errors */
);
t.c_oflag = 0; /* No output processing */
t.c_cflag = (
CS8 /* 8 bits */
| CREAD /* enable receiver */
COM_HANDLE handle;
struct termios t;
if((handle=open(device, O_NONBLOCK|O_RDWR))==COM_HANDLE_INVALID)
return COM_HANDLE_INVALID;
if(tcgetattr(handle, &t)==-1) {
close(handle);
return COM_HANDLE_INVALID;
}
t.c_iflag = (
IGNBRK /* ignore BREAK condition */
| IGNPAR /* ignore (discard) parity errors */
);
t.c_oflag = 0; /* No output processing */
t.c_cflag = (
CS8 /* 8 bits */
| CREAD /* enable receiver */
/*
Fun snippet from the FreeBSD manpage:
......@@ -234,174 +248,140 @@ Fun snippet from the FreeBSD manpage:
pretty silly and if it were not part of the termios specification it
would be omitted.
*/
| HUPCL /* hang up on last close */
| CLOCAL /* ignore modem status lines */
/* The next two are pretty much never used */
#ifdef CCTX_OFLOW
| CCTS_OFLOW /* CTS flow control of output */
#endif
#ifdef CRTSCTS
| CRTSCTS /* same as CCTS_OFLOW */
#endif
#ifdef CRTS_IFLOW
| CRTS_IFLOW /* RTS flow control of input */
#endif
);
t.c_lflag = 0; /* No local modes */
if(tcsetattr(handle, TCSANOW, &t)==-1) {
close(handle);
return COM_HANDLE_INVALID;
}
return handle;
| HUPCL /* hang up on last close */
| CLOCAL /* ignore modem status lines */
| CTSRTS_FLOW_CFLAGS
);
t.c_lflag = 0; /* No local modes */
if(tcsetattr(handle, TCSANOW, &t)==-1) {
close(handle);
return COM_HANDLE_INVALID;
}
return handle;
}
BOOL comClose(COM_HANDLE handle)
{
return (!close(handle));
return (!close(handle));
}
long comGetBaudRate(COM_HANDLE handle)
{
struct termios t;
speed_t in;
speed_t out;
if(tcgetattr(handle, &t))
return COM_ERROR;
/*
* We actually have TWO speeds available...
* return the biggest one
*/
in = macro_to_rate(cfgetispeed(&t));
out = macro_to_rate(cfgetospeed(&t));
return ((long)(in>out?in:out));
struct termios t;
speed_t in;
speed_t out;
if(tcgetattr(handle, &t))
return COM_ERROR;
/*
* We actually have TWO speeds available...
* return the biggest one
*/
in = macro_to_rate(cfgetispeed(&t));
out = macro_to_rate(cfgetospeed(&t));
return ((long)(in>out?in:out));
}
BOOL comSetBaudRate(COM_HANDLE handle, unsigned long rate)
{
struct termios t;
struct termios t;
if(tcgetattr(handle, &t))
return FALSE;
if(tcgetattr(handle, &t))
return FALSE;
cfsetispeed(&t, rate_to_macro(rate));
cfsetospeed(&t, rate_to_macro(rate));
if(tcsetattr(handle, TCSANOW, &t)==-1)
return FALSE;
cfsetispeed(&t, rate_to_macro(rate));
cfsetospeed(&t, rate_to_macro(rate));
if(tcsetattr(handle, TCSANOW, &t)==-1)
return FALSE;
return TRUE;
return TRUE;
}
BOOL comGetTxFlowControl(COM_HANDLE handle)
int comGetFlowControl(COM_HANDLE handle)
{
BOOL ret = FALSE;
struct termios t;
int ret = 0;
struct termios t;
if(tcgetattr(handle, &t)==-1)
return FALSE;
if(tcgetattr(handle, &t)==-1)
return FALSE;
ret = (t.c_cflag & (0
/* The next two are pretty much never used */
#ifdef CCTX_OFLOW
| CCTS_OFLOW /* CTS flow control of output */
#endif
#ifdef CRTSCTS
| CRTSCTS /* same as CCTS_OFLOW */
#endif
#ifdef CRTS_IFLOW
| CRTS_IFLOW /* RTS flow control of input */
#endif
)) ? TRUE : FALSE;
if ((t.c_cflag & CTSRTS_FLOW_CFLAGS) == CTSRTS_FLOW_CFLAGS)
ret |= COM_FLOW_CONTROL_RTS_CTS;
if ((t.c_iflag & XONXOFF_FLOW_IFLAGS) == XONXOFF_FLOW_IFLAGS)
ret |= COM_FLOW_CONTROL_XON_OFF;
return ret;
return ret;
}
BOOL comSetTxFlowControl(COM_HANDLE handle, BOOL enable)
BOOL comSetFlowControl(COM_HANDLE handle, int modes)
{
struct termios t;
if(tcgetattr(handle, &t)==-1)
return FALSE;
if (enable) {
t.c_cflag |= (0
/* The next two are pretty much never used */
#ifdef CCTX_OFLOW
| CCTS_OFLOW /* CTS flow control of output */
#endif
#ifdef CRTSCTS
| CRTSCTS /* same as CCTS_OFLOW */
#endif
#ifdef CRTS_IFLOW
| CRTS_IFLOW /* RTS flow control of input */
#endif
);
}
else {
t.c_cflag &= ~(0
/* The next two are pretty much never used */
#ifdef CCTX_OFLOW
| CCTS_OFLOW /* CTS flow control of output */
#endif
#ifdef CRTSCTS
| CRTSCTS /* same as CCTS_OFLOW */
#endif
#ifdef CRTS_IFLOW
| CRTS_IFLOW /* RTS flow control of input */
#endif
);
}
if(tcsetattr(handle, TCSANOW, &t)==-1)
return FALSE;
return TRUE;
struct termios t;
if(tcgetattr(handle, &t)==-1)
return FALSE;
if (modes & COM_FLOW_CONTROL_RTS_CTS)
t.c_cflag |= CTSRTS_FLOW_CFLAGS;
else
t.c_cflag &= ~CTSRTS_FLOW_CFLAGS;
if (modes & COM_FLOW_CONTROL_XON_OFF)
t.c_iflag |= XONXOFF_FLOW_IFLAGS;
else
t.c_iflag &= ~XONXOFF_FLOW_IFLAGS;
if(tcsetattr(handle, TCSANOW, &t)==-1)
return FALSE;
return TRUE;
}
int comGetModemStatus(COM_HANDLE handle)
{
int status;
int status;
if(ioctl(handle, TIOCMGET, &status)==-1)
return COM_ERROR;
if(ioctl(handle, TIOCMGET, &status)==-1)
return COM_ERROR;
return status;
return status;
}
static BOOL comSetFlags(COM_HANDLE handle, int flags, BOOL set)
{
int cmd = set ? TIOCMBIS : TIOCMBIC;
int cmd = set ? TIOCMBIS : TIOCMBIC;
return ioctl(handle, cmd, &flags);
return ioctl(handle, cmd, &flags);
}
BOOL comRaiseDTR(COM_HANDLE handle)
{
return comSetFlags(handle, TIOCM_DTR, TRUE);
return comSetFlags(handle, TIOCM_DTR, TRUE);
}
BOOL comLowerDTR(COM_HANDLE handle)
{
return comSetFlags(handle, TIOCM_DTR, FALSE);
return comSetFlags(handle, TIOCM_DTR, FALSE);
}
BOOL comRaiseRTS(COM_HANDLE handle)
{
return comSetFlags(handle, TIOCM_RTS, TRUE);
return comSetFlags(handle, TIOCM_RTS, TRUE);
}
BOOL comLowerRTS(COM_HANDLE handle)
{
return comSetFlags(handle, TIOCM_RTS, FALSE);
return comSetFlags(handle, TIOCM_RTS, FALSE);
}
BOOL comWriteByte(COM_HANDLE handle, BYTE ch)
{
return(write(handle, &ch, 1)==1);
return(write(handle, &ch, 1)==1);
}
int comWriteBuf(COM_HANDLE handle, const BYTE* buf, size_t buflen)
{
return write(handle, buf, buflen);
return write(handle, buf, buflen);
}
/*
......@@ -409,25 +389,25 @@ int comWriteBuf(COM_HANDLE handle, const BYTE* buf, size_t buflen)
*/
int comWriteString(COM_HANDLE handle, const char* str)
{
return comWriteBuf(handle, (BYTE*)str, strlen(str));
return comWriteBuf(handle, (BYTE*)str, strlen(str));