/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include "tmextern.h" #define NTRY 5 /* * At this time, we only recognize certain speeds. * This table can be expanded if new patterns are found */ static struct autobaud { char *a_speed; char *a_pattern; /* first byte is length */ } autob2400[] = { #ifdef i386 /* * These are the bit patterns returned on x86 boxes */ "110", "\1\000", #else "110", "\3\000\000\000", #endif "1200", "\2\346\200", "2400", "\1\15", "4800", "\1\371", "4800", "\1\362", "9600", "\1\377", 0, 0 }; /* * auto_termio - set termio to allow autobaud * - the line is set to raw mode, with VMIN = 5, VTIME = 1 * - baud rate is set to 2400 */ int auto_termio(int fd) { struct termio termio; struct termios termios; if (ioctl(fd, TCGETS, &termios) == -1) { if (ioctl(fd, TCGETA, &termio) == -1) { log("auto_termio: ioctl TCGETA failed, fd = %d: %s", fd, strerror(errno)); return (-1); } termio.c_iflag = 0; termio.c_cflag &= ~(CBAUD|CSIZE|PARENB); termio.c_cflag |= CREAD|HUPCL|(CS8&CSIZE)|(B2400&CBAUD); termio.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK); termio.c_oflag = 0; termio.c_cc[VMIN] = 5; termio.c_cc[VTIME] = 1; if (ioctl(fd, TCSETAF, &termio) == -1) { log("auto_termio: ioctl TCSETAF failed, fd = %d: %s", fd, strerror(errno)); return (-1); } } else { termios.c_iflag &= 0xffff0000; termios.c_cflag &= ~(CSIZE|PARENB); termios.c_cflag |= CREAD|HUPCL|(CS8&CSIZE); termios.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK); termios.c_oflag &= 0xffff0000; termios.c_cc[VMIN] = 5; termios.c_cc[VTIME] = 1; (void) cfsetospeed(&termios, B2400); if (ioctl(fd, TCSETSF, &termios) == -1) { log("auto_termio: ioctl TCSETSF failed, fd = %d: %s", fd, strerror(errno)); return (-1); } } return (0); } /* * autobaud - determine the baudrate by reading data at 2400 baud rate * - the program is anticipating * - the bit pattern is matched again an autobaud table * - if a match is found, the matched speed is returned * - otherwise, NULL is returned */ char * autobaud(int fd, int timeout) { int i, k, count; static char buf[5]; char *cp = buf; struct autobaud *tp; struct sigaction sigact; #ifdef DEBUG debug("in autobaud"); #endif (void) auto_termio(fd); sigact.sa_flags = 0; sigact.sa_handler = SIG_IGN; (void) sigemptyset(&sigact.sa_mask); (void) sigaction(SIGINT, &sigact, NULL); count = NTRY; while (count--) { if (timeout) { sigact.sa_flags = 0; sigact.sa_handler = timedout; (void) sigemptyset(&sigact.sa_mask); (void) sigaction(SIGALRM, &sigact, NULL); (void) alarm((unsigned)timeout); } cp = &buf[1]; if (peek_ptr != NULL) { k = peek_ptr->len; (void) strncpy(cp, peek_ptr->buf, k); peek_ptr = NULL; } else if ((k = read(fd, cp, 5)) < 0) { fatal("autobaud: read failed: %s", strerror(errno)); } if (timeout) (void) alarm((unsigned)0); buf[0] = (char)k; for (tp = autob2400; tp->a_speed; tp++) { for (i = 0; ; i++) { if (buf[i] != tp->a_pattern[i]) break; if (i == buf[0]) { return (tp->a_speed); } } } flush_input(fd); } /* end while */ return (NULL); /* autobaud failed */ }