]>
Commit | Line | Data |
---|---|---|
b52373a2 JG |
1 | /* Remote serial interface for OS's with termios, for GDB. |
2 | Copyright 1992 Free Software Foundation, Inc. | |
ae0ea72e SC |
3 | |
4 | This file is part of GDB. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2 of the License, or | |
9 | (at your option) any later version. | |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
18 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
19 | ||
20 | #include "defs.h" | |
ae0ea72e | 21 | #include <fcntl.h> |
ae0ea72e | 22 | #include <sys/time.h> |
a0f9783e | 23 | #include "serial.h" |
ae0ea72e | 24 | |
a0f9783e | 25 | static int desc = -1; |
ae0ea72e SC |
26 | |
27 | void | |
a0f9783e SG |
28 | serial_raw(fd, oldstate) |
29 | int fd; | |
30 | struct ttystate *oldstate; | |
ae0ea72e | 31 | { |
a0f9783e SG |
32 | struct termios termios; |
33 | ||
34 | oldstate->flags = fcntl(fd, F_GETFL, 0); | |
35 | ||
36 | fcntl(fd, F_SETFL, oldstate->flags|FNDELAY); | |
37 | ||
38 | if (tcgetattr(fd, &termios)) | |
39 | { | |
40 | fprintf(stderr, "tcgetattr failed: %s\n", safe_strerror(errno)); | |
41 | } | |
42 | ||
43 | oldstate->termios = termios; | |
44 | ||
45 | termios.c_iflag = 0; | |
46 | termios.c_oflag = 0; | |
47 | termios.c_lflag = 0; | |
48 | termios.c_cc[VMIN] = 0; | |
49 | termios.c_cc[VTIME] = 0; | |
50 | ||
51 | if (tcsetattr(fd, TCSANOW, &termios)) | |
52 | { | |
53 | fprintf(stderr, "tcsetattr failed: %s\n", safe_strerror(errno)); | |
54 | } | |
ae0ea72e SC |
55 | } |
56 | ||
ae0ea72e | 57 | void |
a0f9783e SG |
58 | serial_restore(fd, oldstate) |
59 | int fd; | |
60 | struct ttystate *oldstate; | |
ae0ea72e | 61 | { |
a0f9783e | 62 | fcntl(fd, F_SETFL, oldstate->flags); |
ae0ea72e | 63 | |
a0f9783e | 64 | tcsetattr(fd, TCSANOW, &oldstate->termios); |
ae0ea72e SC |
65 | } |
66 | ||
a0f9783e SG |
67 | static struct ttystate oldstate; |
68 | ||
69 | static fd_set readfds; | |
70 | ||
ae0ea72e | 71 | int |
a0f9783e | 72 | serial_open(name) |
ed3f6049 | 73 | const char *name; |
ae0ea72e SC |
74 | { |
75 | struct termios termios; | |
76 | ||
77 | desc = open (name, O_RDWR); | |
78 | if (desc < 0) | |
a0f9783e | 79 | error("Open of %s failed: %s", name, safe_strerror(errno)); |
ae0ea72e | 80 | |
a0f9783e | 81 | serial_raw(desc, &oldstate); |
ae0ea72e | 82 | |
a0f9783e | 83 | /* Setup constant stuff for select */ |
ae0ea72e | 84 | |
a0f9783e | 85 | FD_ZERO(&readfds); |
ae0ea72e | 86 | |
a0f9783e | 87 | return desc; |
ae0ea72e SC |
88 | } |
89 | ||
a0f9783e SG |
90 | /* Read a character with user-specified timeout. TIMEOUT is number of seconds |
91 | to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns | |
92 | char if successful. Returns -2 if timeout expired, EOF if line dropped | |
93 | dead, or -3 for any other error (see errno in that case). */ | |
94 | ||
ae0ea72e | 95 | int |
a0f9783e SG |
96 | serial_readchar(timeout) |
97 | int timeout; | |
ae0ea72e | 98 | { |
a0f9783e SG |
99 | static unsigned char buf[BUFSIZ]; |
100 | static unsigned char *bufp; | |
101 | static int bufcnt = 0; | |
102 | int numfds; | |
ae0ea72e SC |
103 | struct timeval tv; |
104 | ||
a0f9783e SG |
105 | if (bufcnt-- > 0) |
106 | return *bufp++; | |
ae0ea72e SC |
107 | |
108 | tv.tv_sec = timeout; | |
109 | tv.tv_usec = 0; | |
110 | ||
a0f9783e | 111 | FD_SET(desc, &readfds); |
ae0ea72e | 112 | |
a0f9783e SG |
113 | if (timeout >= 0) |
114 | numfds = select(desc+1, &readfds, 0, 0, &tv); | |
115 | else | |
116 | numfds = select(desc+1, &readfds, 0, 0, 0); | |
ae0ea72e | 117 | |
a0f9783e SG |
118 | if (numfds <= 0) |
119 | if (numfds == 0) | |
120 | return -2; /* Timeout */ | |
121 | else | |
122 | return -3; /* Got an error from select */ | |
123 | ||
124 | bufcnt = read(desc, buf, BUFSIZ); | |
ae0ea72e | 125 | |
a0f9783e SG |
126 | if (bufcnt <= 0) |
127 | if (bufcnt == 0) | |
128 | return EOF; /* 0 chars means end of file */ | |
129 | else | |
130 | return -3; /* Got an error from read */ | |
ae0ea72e | 131 | |
a0f9783e SG |
132 | bufcnt--; |
133 | bufp = buf; | |
134 | return *bufp++; | |
ae0ea72e SC |
135 | } |
136 | ||
137 | /* Translate baud rates from integers to damn B_codes. Unix should | |
138 | have outgrown this crap years ago, but even POSIX wouldn't buck it. */ | |
139 | ||
a0f9783e SG |
140 | static struct |
141 | { | |
142 | int rate; | |
143 | int code; | |
144 | } baudtab[] = { | |
145 | {50, B50}, | |
146 | {75, B75}, | |
147 | {110, B110}, | |
148 | {134, B134}, | |
149 | {150, B150}, | |
150 | {200, B200}, | |
151 | {300, B300}, | |
152 | {600, B600}, | |
153 | {1200, B1200}, | |
154 | {1800, B1800}, | |
155 | {2400, B2400}, | |
156 | {4800, B4800}, | |
157 | {9600, B9600}, | |
158 | {19200, B19200}, | |
159 | {38400, B38400}, | |
160 | {-1, -1}, | |
ae0ea72e SC |
161 | }; |
162 | ||
163 | static int | |
a0f9783e SG |
164 | rate_to_code(rate) |
165 | int rate; | |
ae0ea72e SC |
166 | { |
167 | int i; | |
a0f9783e | 168 | |
ae0ea72e | 169 | for (i = 0; baudtab[i].rate != -1; i++) |
ae0ea72e | 170 | if (rate == baudtab[i].rate) |
a0f9783e SG |
171 | return baudtab[i].code; |
172 | ||
ae0ea72e SC |
173 | return -1; |
174 | } | |
175 | ||
a0f9783e SG |
176 | int |
177 | serial_setbaudrate(rate) | |
b52373a2 | 178 | int rate; |
ae0ea72e SC |
179 | { |
180 | struct termios termios; | |
181 | ||
a0f9783e SG |
182 | if (tcgetattr(desc, &termios)) |
183 | error("tcgetattr failed: %s\n", safe_strerror(errno)); | |
ae0ea72e | 184 | |
a0f9783e SG |
185 | cfsetospeed(&termios, rate_to_code(rate)); |
186 | cfsetispeed(&termios, rate_to_code(rate)); | |
ae0ea72e | 187 | |
a0f9783e SG |
188 | if (tcsetattr(desc, TCSANOW, &termios)) |
189 | error("tcsetattr failed: %s\n", safe_strerror(errno)); | |
ae0ea72e SC |
190 | |
191 | return 1; | |
192 | } | |
193 | ||
194 | int | |
a0f9783e | 195 | serial_write(str, len) |
ed3f6049 | 196 | const char *str; |
a0f9783e | 197 | int len; |
ae0ea72e | 198 | { |
a0f9783e SG |
199 | int cc; |
200 | ||
201 | while (len > 0) | |
202 | { | |
203 | cc = write(desc, str, len); | |
204 | ||
205 | if (cc < 0) | |
206 | return 0; | |
207 | len -= cc; | |
208 | str += cc; | |
209 | } | |
210 | return 1; | |
ae0ea72e SC |
211 | } |
212 | ||
a0f9783e SG |
213 | void |
214 | serial_close() | |
ae0ea72e | 215 | { |
a0f9783e SG |
216 | if (desc < 0) |
217 | return; | |
ae0ea72e | 218 | |
402dca80 | 219 | serial_restore(desc, &oldstate); |
ae0ea72e | 220 | |
a0f9783e SG |
221 | close(desc); |
222 | desc = -1; | |
ae0ea72e | 223 | } |