| /* | 
 |  * (C) Copyright 2000 | 
 |  * Murray Jensen <Murray.Jensen@csiro.au> | 
 |  * | 
 |  * See file CREDITS for list of people who contributed to this | 
 |  * project. | 
 |  * | 
 |  * 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 version 2 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; if not, write to the Free Software | 
 |  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 
 |  * MA 02111-1307 USA | 
 |  */ | 
 |  | 
 | #include <unistd.h> | 
 | #include <string.h> | 
 | #include <fcntl.h> | 
 | #include <sys/time.h> | 
 | #include "serial.h" | 
 |  | 
 | #if defined(__sun__)	 || \ | 
 |     defined(__OpenBSD__) || \ | 
 |     defined(__FreeBSD__) || \ | 
 |     defined(__NetBSD__)	 || \ | 
 |     defined(__APPLE__) | 
 | static struct termios tios = { BRKINT, 0, B115200|CS8|CREAD, 0, { 0 } }; | 
 | #else | 
 | static struct termios tios = { BRKINT, 0, B115200|CS8|CREAD, 0,   0   }; | 
 | #endif | 
 |  | 
 | static struct speedmap { | 
 |     char *str; | 
 |     speed_t val; | 
 | } speedmap[] = { | 
 |     { "50", B50 },		{ "75", B75 },		{ "110", B110 }, | 
 |     { "134", B134 },		{ "150", B150 },	{ "200", B200 }, | 
 |     { "300", B300 },		{ "600", B600 },	{ "1200", B1200 }, | 
 |     { "1800", B1800 },		{ "2400", B2400 },	{ "4800", B4800 }, | 
 |     { "9600", B9600 },		{ "19200", B19200 },	{ "38400", B38400 }, | 
 |     { "57600", B57600 }, | 
 | #ifdef	B76800 | 
 |     { "76800", B76800 }, | 
 | #endif | 
 |     { "115200", B115200 }, | 
 | #ifdef	B153600 | 
 |     { "153600", B153600 }, | 
 | #endif | 
 |     { "230400", B230400 }, | 
 | #ifdef	B307200 | 
 |     { "307200", B307200 }, | 
 | #endif | 
 | #ifdef B460800 | 
 |     { "460800", B460800 } | 
 | #endif | 
 | }; | 
 | static int nspeeds = sizeof speedmap / sizeof speedmap[0]; | 
 |  | 
 | speed_t | 
 | cvtspeed(char *str) | 
 | { | 
 |     struct speedmap *smp = speedmap, *esmp = &speedmap[nspeeds]; | 
 |  | 
 |     while (smp < esmp) { | 
 | 	if (strcmp(str, smp->str) == 0) | 
 | 	    return (smp->val); | 
 | 	smp++; | 
 |     } | 
 |     return B0; | 
 | } | 
 |  | 
 | int | 
 | serialopen(char *device, speed_t speed) | 
 | { | 
 |     int fd; | 
 |  | 
 |     if (cfsetospeed(&tios, speed) < 0) | 
 | 	return -1; | 
 |  | 
 |     if ((fd = open(device, O_RDWR)) < 0) | 
 | 	return -1; | 
 |  | 
 |     if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { | 
 | 	(void)close(fd); | 
 | 	return -1; | 
 |     } | 
 |  | 
 |     return fd; | 
 | } | 
 |  | 
 | int | 
 | serialreadchar(int fd, int timeout) | 
 | { | 
 |     fd_set fds; | 
 |     struct timeval tv; | 
 |     int n; | 
 |     char ch; | 
 |  | 
 |     tv.tv_sec = timeout; | 
 |     tv.tv_usec = 0; | 
 |  | 
 |     FD_ZERO(&fds); | 
 |     FD_SET(fd, &fds); | 
 |  | 
 |     /* this is a fucking horrible quick hack - fix this */ | 
 |  | 
 |     if ((n = select(fd + 1, &fds, 0, 0, &tv)) < 0) | 
 | 	return SERIAL_ERROR; | 
 |  | 
 |     if (n == 0) | 
 | 	return SERIAL_TIMEOUT; | 
 |  | 
 |     if ((n = read(fd, &ch, 1)) < 0) | 
 | 	return SERIAL_ERROR; | 
 |  | 
 |     if (n == 0) | 
 | 	return SERIAL_EOF; | 
 |  | 
 |     return ch; | 
 | } | 
 |  | 
 | int | 
 | serialwrite(int fd, char *buf, int len) | 
 | { | 
 |     int n; | 
 |  | 
 |     do { | 
 | 	n = write(fd, buf, len); | 
 | 	if (n < 0) | 
 | 	    return 1; | 
 | 	len -= n; | 
 | 	buf += n; | 
 |     } while (len > 0); | 
 |     return 0; | 
 | } | 
 |  | 
 | int | 
 | serialclose(int fd) | 
 | { | 
 |     return close(fd); | 
 | } |