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 #include <stdio.h> 31 #include <errno.h> 32 #include <fcntl.h> 33 #include <string.h> 34 #include <termio.h> 35 #include <unistd.h> 36 #include <signal.h> 37 #include <stdlib.h> 38 #include <sys/types.h> 39 #include <sys/stropts.h> 40 41 #include "tmextern.h" 42 43 #define NTRY 5 44 45 /* 46 * At this time, we only recognize certain speeds. 47 * This table can be expanded if new patterns are found 48 */ 49 static struct autobaud { 50 char *a_speed; 51 char *a_pattern; /* first byte is length */ 52 } autob2400[] = { 53 #ifdef i386 54 /* 55 * These are the bit patterns returned on x86 boxes 56 */ 57 "110", "\1\000", 58 #else 59 "110", "\3\000\000\000", 60 #endif 61 "1200", "\2\346\200", 62 "2400", "\1\15", 63 "4800", "\1\371", 64 "4800", "\1\362", 65 "9600", "\1\377", 66 0, 0 67 }; 68 69 /* 70 * auto_termio - set termio to allow autobaud 71 * - the line is set to raw mode, with VMIN = 5, VTIME = 1 72 * - baud rate is set to 2400 73 */ 74 int 75 auto_termio(int fd) 76 { 77 struct termio termio; 78 struct termios termios; 79 80 if (ioctl(fd, TCGETS, &termios) == -1) { 81 if (ioctl(fd, TCGETA, &termio) == -1) { 82 log("auto_termio: ioctl TCGETA failed, fd = %d: %s", fd, 83 strerror(errno)); 84 return (-1); 85 } 86 termio.c_iflag = 0; 87 termio.c_cflag &= ~(CBAUD|CSIZE|PARENB); 88 termio.c_cflag |= CREAD|HUPCL|(CS8&CSIZE)|(B2400&CBAUD); 89 termio.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK); 90 termio.c_oflag = 0; 91 92 termio.c_cc[VMIN] = 5; 93 termio.c_cc[VTIME] = 1; 94 95 if (ioctl(fd, TCSETAF, &termio) == -1) { 96 log("auto_termio: ioctl TCSETAF failed, fd = %d: %s", 97 fd, strerror(errno)); 98 return (-1); 99 } 100 } else { 101 termios.c_iflag &= 0xffff0000; 102 termios.c_cflag &= ~(CSIZE|PARENB); 103 termios.c_cflag |= CREAD|HUPCL|(CS8&CSIZE); 104 termios.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK); 105 termios.c_oflag &= 0xffff0000; 106 107 termios.c_cc[VMIN] = 5; 108 termios.c_cc[VTIME] = 1; 109 (void) cfsetospeed(&termios, B2400); 110 111 if (ioctl(fd, TCSETSF, &termios) == -1) { 112 log("auto_termio: ioctl TCSETSF failed, fd = %d: %s", 113 fd, strerror(errno)); 114 return (-1); 115 } 116 } 117 return (0); 118 } 119 120 /* 121 * autobaud - determine the baudrate by reading data at 2400 baud rate 122 * - the program is anticipating <CR> 123 * - the bit pattern is matched again an autobaud table 124 * - if a match is found, the matched speed is returned 125 * - otherwise, NULL is returned 126 */ 127 128 char * 129 autobaud(int fd, int timeout) 130 { 131 int i, k, count; 132 static char buf[5]; 133 char *cp = buf; 134 struct autobaud *tp; 135 struct sigaction sigact; 136 137 #ifdef DEBUG 138 debug("in autobaud"); 139 #endif 140 (void) auto_termio(fd); 141 sigact.sa_flags = 0; 142 sigact.sa_handler = SIG_IGN; 143 (void) sigemptyset(&sigact.sa_mask); 144 (void) sigaction(SIGINT, &sigact, NULL); 145 count = NTRY; 146 while (count--) { 147 if (timeout) { 148 sigact.sa_flags = 0; 149 sigact.sa_handler = timedout; 150 (void) sigemptyset(&sigact.sa_mask); 151 (void) sigaction(SIGALRM, &sigact, NULL); 152 (void) alarm((unsigned)timeout); 153 } 154 cp = &buf[1]; 155 if (peek_ptr != NULL) { 156 k = peek_ptr->len; 157 (void) strncpy(cp, peek_ptr->buf, k); 158 peek_ptr = NULL; 159 } else if ((k = read(fd, cp, 5)) < 0) { 160 fatal("autobaud: read failed: %s", strerror(errno)); 161 } 162 if (timeout) 163 (void) alarm((unsigned)0); 164 buf[0] = (char)k; 165 for (tp = autob2400; tp->a_speed; tp++) { 166 for (i = 0; ; i++) { 167 if (buf[i] != tp->a_pattern[i]) 168 break; 169 if (i == buf[0]) { 170 return (tp->a_speed); 171 } 172 } 173 } 174 flush_input(fd); 175 } /* end while */ 176 return (NULL); /* autobaud failed */ 177 } 178