diff --git a/src/comio/comio_nix.c b/src/comio/comio_nix.c index 73652818ce2bfb751c158191f085269ae0dc2ce2..5dd4accebee62e8f83a4e0c995b002939dddb146 100644 --- a/src/comio/comio_nix.c +++ b/src/comio/comio_nix.c @@ -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)); } BOOL comReadByte(COM_HANDLE handle, BYTE* ch) { - return(read(handle, ch, 1)==1); + return(read(handle, ch, 1)==1); } BOOL comPurgeInput(COM_HANDLE handle) { - return(tcflush(handle, TCIFLUSH)==0); + return(tcflush(handle, TCIFLUSH)==0); } BOOL comPurgeOutput(COM_HANDLE handle) { - return(tcflush(handle, TCOFLUSH)==0); + return(tcflush(handle, TCOFLUSH)==0); } BOOL comDrainOutput(COM_HANDLE handle) { - return(tcdrain(handle)==0); + return(tcdrain(handle)==0); }