1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 #include <stdio.h> 34 #include <errno.h> 35 #include <fcntl.h> 36 #include <string.h> 37 #include <termio.h> 38 #include <unistd.h> 39 #include <signal.h> 40 #include <stdlib.h> 41 #include <sys/types.h> 42 #include <sys/stropts.h> 43 44 #include "tmextern.h" 45 46 #define NTRY 5 47 48 /* 49 * At this time, we only recognize certain speeds. 50 * This table can be expanded if new patterns are found 51 */ 52 static struct autobaud { 53 char *a_speed; 54 char *a_pattern; /* first byte is length */ 55 } autob2400[] = { 56 #ifdef i386 57 /* 58 * These are the bit patterns returned on x86 boxes 59 */ 60 "110", "\1\000", 61 #else 62 "110", "\3\000\000\000", 63 #endif 64 "1200", "\2\346\200", 65 "2400", "\1\15", 66 "4800", "\1\371", 67 "4800", "\1\362", 68 "9600", "\1\377", 69 0, 0 70 }; 71 72 extern struct strbuf *peek_ptr; 73 74 /* 75 * auto_termio - set termio to allow autobaud 76 * - the line is set to raw mode, with VMIN = 5, VTIME = 1 77 * - baud rate is set to 2400 78 */ 79 int 80 auto_termio(int fd) 81 { 82 struct termio termio; 83 struct termios termios; 84 85 if (ioctl(fd, TCGETS, &termios) == -1) { 86 if (ioctl(fd, TCGETA, &termio) == -1) { 87 log("auto_termio: ioctl TCGETA failed, fd = %d: %s", fd, 88 strerror(errno)); 89 return(-1); 90 } 91 termio.c_iflag = 0; 92 termio.c_cflag &= ~(CBAUD|CSIZE|PARENB); 93 termio.c_cflag |= CREAD|HUPCL|(CS8&CSIZE)|(B2400&CBAUD); 94 termio.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK); 95 termio.c_oflag = 0; 96 97 termio.c_cc[VMIN] = 5; 98 termio.c_cc[VTIME] = 1; 99 100 if (ioctl(fd, TCSETAF, &termio) == -1) { 101 log("auto_termio: ioctl TCSETAF failed, fd = %d: %s", 102 fd, strerror(errno)); 103 return(-1); 104 } 105 } else { 106 termios.c_iflag &= 0xffff0000; 107 termios.c_cflag &= ~(CSIZE|PARENB); 108 termios.c_cflag |= CREAD|HUPCL|(CS8&CSIZE); 109 termios.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK); 110 termios.c_oflag &= 0xffff0000; 111 112 termios.c_cc[VMIN] = 5; 113 termios.c_cc[VTIME] = 1; 114 cfsetospeed(&termios, B2400); 115 116 if (ioctl(fd, TCSETSF, &termios) == -1) { 117 log("auto_termio: ioctl TCSETSF failed, fd = %d: %s", 118 fd, strerror(errno)); 119 return(-1); 120 } 121 } 122 return(0); 123 } 124 125 /* 126 * autobaud - determine the baudrate by reading data at 2400 baud rate 127 * - the program is anticipating <CR> 128 * - the bit pattern is matched again an autobaud table 129 * - if a match is found, the matched speed is returned 130 * - otherwise, NULL is returned 131 */ 132 133 char * 134 autobaud(int fd, int timeout) 135 { 136 int i, k, count; 137 static char buf[5]; 138 register char *cp = buf; 139 struct autobaud *tp; 140 struct sigaction sigact; 141 extern void timedout(); 142 extern void flush_input(); 143 144 #ifdef DEBUG 145 debug("in autobaud"); 146 #endif 147 auto_termio(fd); 148 sigact.sa_flags = 0; 149 sigact.sa_handler = SIG_IGN; 150 (void)sigemptyset(&sigact.sa_mask); 151 (void)sigaction(SIGINT, &sigact, NULL); 152 count = NTRY; 153 while (count--) { 154 if (timeout) { 155 sigact.sa_flags = 0; 156 sigact.sa_handler = timedout; 157 (void)sigemptyset(&sigact.sa_mask); 158 (void)sigaction(SIGALRM, &sigact, NULL); 159 (void)alarm((unsigned)timeout); 160 } 161 cp = &buf[1]; 162 if ( peek_ptr ) { 163 strncpy(cp, peek_ptr->buf, k=peek_ptr->len); 164 peek_ptr = NULL; 165 } else if ((k=read(fd, cp, 5)) < 0) { 166 fatal("autobaud: read failed: %s", strerror(errno)); 167 } 168 if (timeout) 169 (void)alarm((unsigned)0); 170 buf[0] = (char)k; 171 for (tp = autob2400; tp->a_speed; tp++) { 172 for (i = 0;; i++) { 173 if (buf[i] != tp->a_pattern[i]) 174 break; 175 if (i == buf[0]) { 176 return(tp->a_speed); 177 } 178 } 179 } 180 flush_input(fd); 181 } /* end while */ 182 return(NULL); /* autobaud failed */ 183 } 184