/*- * Copyright (c) 1997 Causality Limited. * All rights reserved. * * This code was written by Mark Brinicombe * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Causality Limited. * 4. The name of Causality Limited may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* Modified by Deborah A. Wallach (kerr@pa.dec.com) 12/22/97 */ /*#define _POSIX_SOURCE 1*/ #include #include #include #include #include #include #include #include #include /* * Set the baudrate */ int serial_setbaudrate(int fd, int baudrate) { struct termios serial_tio; tcgetattr(fd, &serial_tio); switch(baudrate) { case 115200: cfsetispeed(&serial_tio, B115200); cfsetospeed(&serial_tio, B115200); break ; case 57600: cfsetispeed(&serial_tio, B57600); cfsetospeed(&serial_tio, B57600); break ; case 38400: cfsetispeed(&serial_tio, B38400); cfsetospeed(&serial_tio, B38400); break ; case 19200: cfsetispeed(&serial_tio, B19200); cfsetospeed(&serial_tio, B19200); break ; case 9600: cfsetispeed(&serial_tio, B9600); cfsetospeed(&serial_tio, B9600); break ; default: fprintf(stderr, "Invalid baudrate %d\n", baudrate); return(EINVAL); } tcflush(fd, TCIFLUSH); tcsetattr(fd, TCSANOW, &serial_tio); return(0); } /* * Setup of the communication port. Hope it will work */ int serial_set_tty(int fd, char *options) { struct termios serial_tio; int baudrate; int databits; char parity; int stopbits; int loop; if (sscanf(options, "%d %d%c%d", &baudrate, &databits, &parity, &stopbits) != 4) { fprintf(stderr, "Invalid serial options - %s\n", options); return(EINVAL); } switch (databits) { case 6: databits = CS6; break; case 7: databits = CS7; break; case 8: databits = CS8; break; default: fprintf(stderr, "Invalid data bits %d\n", databits); return(EINVAL); break; } switch (parity) { case 'N': parity = IGNPAR; break; default: fprintf(stderr, "Invalid parity %c\n", parity); return(EINVAL); break; } switch (stopbits) { case 1: stopbits = 0; break; case 2: stopbits = CSTOPB; break; default: fprintf(stderr, "Invalid stopbits %d\n", stopbits); return(EINVAL); break; } /* get the terminal attributes */ if (tcgetattr(fd, &serial_tio) != 0) { fprintf(stderr, "Couldn't get terminal attributes\n"); return(EINVAL); } serial_tio.c_cc[VMIN] = 32; /* wake up after 32 chars */ serial_tio.c_cc[VTIME] = 1; /* wake up 0.1 seconds after 1st char */ serial_tio.c_iflag &= ~(BRKINT /* Ignore break */ | IGNPAR | PARMRK | /* Ignore parity */ INPCK | /* Ignore parity */ ISTRIP | /* Don't mask */ INLCR | IGNCR | ICRNL /* No or */ | IXON); /* Ignore STOP char */ serial_tio.c_iflag |= IGNBRK | IXOFF ; serial_tio.c_oflag &= ~(OPOST); /* No output flags */ serial_tio.c_lflag &= ~( /* No local flags. In */ ECHO|ECHOE|ECHOK|ECHONL| /* particular, no echo */ ICANON | /* no canonical input */ /* processing, */ ISIG | /* no signals, */ NOFLSH | /* no queue flush, */ TOSTOP); /* and no job control. */ serial_tio.c_cflag &= ( /* Clear out old bits */ CSIZE | /* Character size */ CSTOPB | /* 2 Stop bits */ HUPCL | /* Hangup on last close*/ PARENB); /* Parity */ serial_tio.c_cflag |= CLOCAL | CREAD | databits | stopbits ; tcsetattr(fd, TCSANOW, &serial_tio); /* set up the baud rate in struct termios serial_tio */ return (serial_setbaudrate(fd, baudrate)) ; } int serial_open(char *name, char *options) { int fd; fd = open(name, O_RDWR | O_NOCTTY); if (fd == -1) { fprintf(stderr, "Unable to open %s\n", name); return(-1); } if (serial_set_tty(fd, options)) return(-1); return(fd); } int serial_close(int fd) { close(fd); return(0); } int serial_putc(int fd, int byte) { unsigned char data; data = byte; return(write(fd, &data, 1)); } int serial_puts(int fd, int count, char *buf) { int status ; status = write(fd, buf, count) ; if (status == count) tcdrain(fd) ; return(status); } int serial_getc(int fd) { unsigned char data; if (read(fd, &data, 1) == 1) return(data); return(-1); } #if 0 int serial_getc_timeout(int fd, int timeout) { fd_set fdset; int fdsetsize; struct timeval timeval; int ready; fdsetsize = getdtablesize(); if (fdsetsize > FD_SETSIZE) fdsetsize = FD_SETSIZE; FD_ZERO(&fdset); FD_SET(fd, &fdset); timeval.tv_sec = timeout; timeval.tv_usec = 0; ready = select(fdsetsize, &fdset, NULL, NULL, &timeval); return(serial_getc(fd)); } #endif int serial_gets(int fd, unsigned char *buf, int count) { int saw = 0; saw = read(fd, buf, count); return(saw); } int f_serial_gets(int fd, unsigned char *buf, int count) { static FILE *file = 0; int saw = 0; if(!file) { file = fdopen(fd, O_RDWR | O_NOCTTY); if (!file) { fprintf(stderr, "fdopen failed\n"); exit(0); } } saw = fread(buf, count, count, file); return(saw); } /* /* Because the sa1100-eval board does not do flow control, the * host side ends up occasionally losing the later parts of some * acknowledgement packets from the angel. Since there are just * acknowledgements anyway, we pretend to have received the entire * packet when this happens. */ int serial_gets_timeout(int fd, unsigned char *buf, int count, int timeout) { int fdsetsize; struct timeval timeval; int ready; fd_set fdset; fdsetsize = getdtablesize(); if (fdsetsize > FD_SETSIZE) fdsetsize = FD_SETSIZE; FD_ZERO(&fdset); FD_SET(fd, &fdset); timeval.tv_sec = timeout; timeval.tv_usec = 0; while(1) { ready = select(fdsetsize, &fdset, NULL, NULL, &timeval); if(ready) { return(serial_gets(fd, buf, count)); } else { putchar('*'); /* hack! XXX */ buf[0] = 0x1d; return(1); } } }