]>
Commit | Line | Data |
---|---|---|
1 | /* Serial interface for local (hardwired) serial ports on Un*x like systems | |
2 | ||
3 | Copyright (C) 1992-2021 Free Software Foundation, Inc. | |
4 | ||
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "defs.h" | |
21 | #include "serial.h" | |
22 | #include "ser-base.h" | |
23 | #include "ser-unix.h" | |
24 | ||
25 | #include <fcntl.h> | |
26 | #include <sys/types.h> | |
27 | #include "terminal.h" | |
28 | #include <sys/socket.h> | |
29 | #include "gdbsupport/gdb_sys_time.h" | |
30 | ||
31 | #include "gdbsupport/gdb_select.h" | |
32 | #include "gdbcmd.h" | |
33 | #include "gdbsupport/filestuff.h" | |
34 | #include <termios.h> | |
35 | #include "gdbsupport/scoped_ignore_sigttou.h" | |
36 | ||
37 | struct hardwire_ttystate | |
38 | { | |
39 | struct termios termios; | |
40 | }; | |
41 | ||
42 | #ifdef CRTSCTS | |
43 | /* Boolean to explicitly enable or disable h/w flow control. */ | |
44 | static bool serial_hwflow; | |
45 | static void | |
46 | show_serial_hwflow (struct ui_file *file, int from_tty, | |
47 | struct cmd_list_element *c, const char *value) | |
48 | { | |
49 | fprintf_filtered (file, _("Hardware flow control is %s.\n"), value); | |
50 | } | |
51 | #endif | |
52 | ||
53 | static int hardwire_open (struct serial *scb, const char *name); | |
54 | static void hardwire_raw (struct serial *scb); | |
55 | static int rate_to_code (int rate); | |
56 | static int hardwire_setbaudrate (struct serial *scb, int rate); | |
57 | static int hardwire_setparity (struct serial *scb, int parity); | |
58 | static void hardwire_close (struct serial *scb); | |
59 | static int get_tty_state (struct serial *scb, | |
60 | struct hardwire_ttystate * state); | |
61 | static int set_tty_state (struct serial *scb, | |
62 | struct hardwire_ttystate * state); | |
63 | static serial_ttystate hardwire_get_tty_state (struct serial *scb); | |
64 | static int hardwire_set_tty_state (struct serial *scb, serial_ttystate state); | |
65 | static void hardwire_print_tty_state (struct serial *, serial_ttystate, | |
66 | struct ui_file *); | |
67 | static int hardwire_drain_output (struct serial *); | |
68 | static int hardwire_flush_output (struct serial *); | |
69 | static int hardwire_flush_input (struct serial *); | |
70 | static int hardwire_send_break (struct serial *); | |
71 | static int hardwire_setstopbits (struct serial *, int); | |
72 | ||
73 | /* Open up a real live device for serial I/O. */ | |
74 | ||
75 | static int | |
76 | hardwire_open (struct serial *scb, const char *name) | |
77 | { | |
78 | scb->fd = gdb_open_cloexec (name, O_RDWR, 0); | |
79 | if (scb->fd < 0) | |
80 | return -1; | |
81 | ||
82 | return 0; | |
83 | } | |
84 | ||
85 | static int | |
86 | get_tty_state (struct serial *scb, struct hardwire_ttystate *state) | |
87 | { | |
88 | if (tcgetattr (scb->fd, &state->termios) < 0) | |
89 | return -1; | |
90 | ||
91 | return 0; | |
92 | } | |
93 | ||
94 | static int | |
95 | set_tty_state (struct serial *scb, struct hardwire_ttystate *state) | |
96 | { | |
97 | if (tcsetattr (scb->fd, TCSANOW, &state->termios) < 0) | |
98 | return -1; | |
99 | ||
100 | return 0; | |
101 | } | |
102 | ||
103 | static serial_ttystate | |
104 | hardwire_get_tty_state (struct serial *scb) | |
105 | { | |
106 | struct hardwire_ttystate *state = XNEW (struct hardwire_ttystate); | |
107 | ||
108 | if (get_tty_state (scb, state)) | |
109 | { | |
110 | xfree (state); | |
111 | return NULL; | |
112 | } | |
113 | ||
114 | return (serial_ttystate) state; | |
115 | } | |
116 | ||
117 | static serial_ttystate | |
118 | hardwire_copy_tty_state (struct serial *scb, serial_ttystate ttystate) | |
119 | { | |
120 | struct hardwire_ttystate *state = XNEW (struct hardwire_ttystate); | |
121 | ||
122 | *state = *(struct hardwire_ttystate *) ttystate; | |
123 | ||
124 | return (serial_ttystate) state; | |
125 | } | |
126 | ||
127 | static int | |
128 | hardwire_set_tty_state (struct serial *scb, serial_ttystate ttystate) | |
129 | { | |
130 | struct hardwire_ttystate *state; | |
131 | ||
132 | state = (struct hardwire_ttystate *) ttystate; | |
133 | ||
134 | return set_tty_state (scb, state); | |
135 | } | |
136 | ||
137 | static void | |
138 | hardwire_print_tty_state (struct serial *scb, | |
139 | serial_ttystate ttystate, | |
140 | struct ui_file *stream) | |
141 | { | |
142 | struct hardwire_ttystate *state = (struct hardwire_ttystate *) ttystate; | |
143 | int i; | |
144 | ||
145 | fprintf_filtered (stream, "c_iflag = 0x%x, c_oflag = 0x%x,\n", | |
146 | (int) state->termios.c_iflag, | |
147 | (int) state->termios.c_oflag); | |
148 | fprintf_filtered (stream, "c_cflag = 0x%x, c_lflag = 0x%x\n", | |
149 | (int) state->termios.c_cflag, | |
150 | (int) state->termios.c_lflag); | |
151 | #if 0 | |
152 | /* This not in POSIX, and is not really documented by those systems | |
153 | which have it (at least not Sun). */ | |
154 | fprintf_filtered (stream, "c_line = 0x%x.\n", state->termios.c_line); | |
155 | #endif | |
156 | fprintf_filtered (stream, "c_cc: "); | |
157 | for (i = 0; i < NCCS; i += 1) | |
158 | fprintf_filtered (stream, "0x%x ", state->termios.c_cc[i]); | |
159 | fprintf_filtered (stream, "\n"); | |
160 | } | |
161 | ||
162 | /* Wait for the output to drain away, as opposed to flushing | |
163 | (discarding) it. */ | |
164 | ||
165 | static int | |
166 | hardwire_drain_output (struct serial *scb) | |
167 | { | |
168 | /* Ignore SIGTTOU which may occur during the drain. */ | |
169 | scoped_ignore_sigttou ignore_sigttou; | |
170 | ||
171 | return tcdrain (scb->fd); | |
172 | } | |
173 | ||
174 | static int | |
175 | hardwire_flush_output (struct serial *scb) | |
176 | { | |
177 | return tcflush (scb->fd, TCOFLUSH); | |
178 | } | |
179 | ||
180 | static int | |
181 | hardwire_flush_input (struct serial *scb) | |
182 | { | |
183 | ser_base_flush_input (scb); | |
184 | ||
185 | return tcflush (scb->fd, TCIFLUSH); | |
186 | } | |
187 | ||
188 | static int | |
189 | hardwire_send_break (struct serial *scb) | |
190 | { | |
191 | return tcsendbreak (scb->fd, 0); | |
192 | } | |
193 | ||
194 | static void | |
195 | hardwire_raw (struct serial *scb) | |
196 | { | |
197 | struct hardwire_ttystate state; | |
198 | ||
199 | if (get_tty_state (scb, &state)) | |
200 | fprintf_unfiltered (gdb_stderr, "get_tty_state failed: %s\n", | |
201 | safe_strerror (errno)); | |
202 | ||
203 | state.termios.c_iflag = 0; | |
204 | state.termios.c_oflag = 0; | |
205 | state.termios.c_lflag = 0; | |
206 | state.termios.c_cflag &= ~CSIZE; | |
207 | state.termios.c_cflag |= CLOCAL | CS8; | |
208 | #ifdef CRTSCTS | |
209 | /* h/w flow control. */ | |
210 | if (serial_hwflow) | |
211 | state.termios.c_cflag |= CRTSCTS; | |
212 | else | |
213 | state.termios.c_cflag &= ~CRTSCTS; | |
214 | #ifdef CRTS_IFLOW | |
215 | if (serial_hwflow) | |
216 | state.termios.c_cflag |= CRTS_IFLOW; | |
217 | else | |
218 | state.termios.c_cflag &= ~CRTS_IFLOW; | |
219 | #endif | |
220 | #endif | |
221 | state.termios.c_cc[VMIN] = 0; | |
222 | state.termios.c_cc[VTIME] = 0; | |
223 | ||
224 | if (set_tty_state (scb, &state)) | |
225 | fprintf_unfiltered (gdb_stderr, "set_tty_state failed: %s\n", | |
226 | safe_strerror (errno)); | |
227 | } | |
228 | ||
229 | #ifndef B19200 | |
230 | #define B19200 EXTA | |
231 | #endif | |
232 | ||
233 | #ifndef B38400 | |
234 | #define B38400 EXTB | |
235 | #endif | |
236 | ||
237 | /* Translate baud rates from integers to damn B_codes. Unix should | |
238 | have outgrown this crap years ago, but even POSIX wouldn't buck it. */ | |
239 | ||
240 | static struct | |
241 | { | |
242 | int rate; | |
243 | int code; | |
244 | } | |
245 | baudtab[] = | |
246 | { | |
247 | { | |
248 | 50, B50 | |
249 | } | |
250 | , | |
251 | { | |
252 | 75, B75 | |
253 | } | |
254 | , | |
255 | { | |
256 | 110, B110 | |
257 | } | |
258 | , | |
259 | { | |
260 | 134, B134 | |
261 | } | |
262 | , | |
263 | { | |
264 | 150, B150 | |
265 | } | |
266 | , | |
267 | { | |
268 | 200, B200 | |
269 | } | |
270 | , | |
271 | { | |
272 | 300, B300 | |
273 | } | |
274 | , | |
275 | { | |
276 | 600, B600 | |
277 | } | |
278 | , | |
279 | { | |
280 | 1200, B1200 | |
281 | } | |
282 | , | |
283 | { | |
284 | 1800, B1800 | |
285 | } | |
286 | , | |
287 | { | |
288 | 2400, B2400 | |
289 | } | |
290 | , | |
291 | { | |
292 | 4800, B4800 | |
293 | } | |
294 | , | |
295 | { | |
296 | 9600, B9600 | |
297 | } | |
298 | , | |
299 | { | |
300 | 19200, B19200 | |
301 | } | |
302 | , | |
303 | { | |
304 | 38400, B38400 | |
305 | } | |
306 | , | |
307 | #ifdef B57600 | |
308 | { | |
309 | 57600, B57600 | |
310 | } | |
311 | , | |
312 | #endif | |
313 | #ifdef B115200 | |
314 | { | |
315 | 115200, B115200 | |
316 | } | |
317 | , | |
318 | #endif | |
319 | #ifdef B230400 | |
320 | { | |
321 | 230400, B230400 | |
322 | } | |
323 | , | |
324 | #endif | |
325 | #ifdef B460800 | |
326 | { | |
327 | 460800, B460800 | |
328 | } | |
329 | , | |
330 | #endif | |
331 | { | |
332 | -1, -1 | |
333 | } | |
334 | , | |
335 | }; | |
336 | ||
337 | static int | |
338 | rate_to_code (int rate) | |
339 | { | |
340 | int i; | |
341 | ||
342 | for (i = 0; baudtab[i].rate != -1; i++) | |
343 | { | |
344 | /* test for perfect macth. */ | |
345 | if (rate == baudtab[i].rate) | |
346 | return baudtab[i].code; | |
347 | else | |
348 | { | |
349 | /* check if it is in between valid values. */ | |
350 | if (rate < baudtab[i].rate) | |
351 | { | |
352 | if (i) | |
353 | { | |
354 | warning (_("Invalid baud rate %d. " | |
355 | "Closest values are %d and %d."), | |
356 | rate, baudtab[i - 1].rate, baudtab[i].rate); | |
357 | } | |
358 | else | |
359 | { | |
360 | warning (_("Invalid baud rate %d. Minimum value is %d."), | |
361 | rate, baudtab[0].rate); | |
362 | } | |
363 | return -1; | |
364 | } | |
365 | } | |
366 | } | |
367 | ||
368 | /* The requested speed was too large. */ | |
369 | warning (_("Invalid baud rate %d. Maximum value is %d."), | |
370 | rate, baudtab[i - 1].rate); | |
371 | return -1; | |
372 | } | |
373 | ||
374 | static int | |
375 | hardwire_setbaudrate (struct serial *scb, int rate) | |
376 | { | |
377 | struct hardwire_ttystate state; | |
378 | int baud_code = rate_to_code (rate); | |
379 | ||
380 | if (baud_code < 0) | |
381 | { | |
382 | /* The baud rate was not valid. | |
383 | A warning has already been issued. */ | |
384 | errno = EINVAL; | |
385 | return -1; | |
386 | } | |
387 | ||
388 | if (get_tty_state (scb, &state)) | |
389 | return -1; | |
390 | ||
391 | cfsetospeed (&state.termios, baud_code); | |
392 | cfsetispeed (&state.termios, baud_code); | |
393 | ||
394 | return set_tty_state (scb, &state); | |
395 | } | |
396 | ||
397 | static int | |
398 | hardwire_setstopbits (struct serial *scb, int num) | |
399 | { | |
400 | struct hardwire_ttystate state; | |
401 | int newbit; | |
402 | ||
403 | if (get_tty_state (scb, &state)) | |
404 | return -1; | |
405 | ||
406 | switch (num) | |
407 | { | |
408 | case SERIAL_1_STOPBITS: | |
409 | newbit = 0; | |
410 | break; | |
411 | case SERIAL_1_AND_A_HALF_STOPBITS: | |
412 | case SERIAL_2_STOPBITS: | |
413 | newbit = 1; | |
414 | break; | |
415 | default: | |
416 | return 1; | |
417 | } | |
418 | ||
419 | if (!newbit) | |
420 | state.termios.c_cflag &= ~CSTOPB; | |
421 | else | |
422 | state.termios.c_cflag |= CSTOPB; /* two bits */ | |
423 | ||
424 | return set_tty_state (scb, &state); | |
425 | } | |
426 | ||
427 | /* Implement the "setparity" serial_ops callback. */ | |
428 | ||
429 | static int | |
430 | hardwire_setparity (struct serial *scb, int parity) | |
431 | { | |
432 | struct hardwire_ttystate state; | |
433 | int newparity = 0; | |
434 | ||
435 | if (get_tty_state (scb, &state)) | |
436 | return -1; | |
437 | ||
438 | switch (parity) | |
439 | { | |
440 | case GDBPARITY_NONE: | |
441 | newparity = 0; | |
442 | break; | |
443 | case GDBPARITY_ODD: | |
444 | newparity = PARENB | PARODD; | |
445 | break; | |
446 | case GDBPARITY_EVEN: | |
447 | newparity = PARENB; | |
448 | break; | |
449 | default: | |
450 | internal_warning (__FILE__, __LINE__, | |
451 | "Incorrect parity value: %d", parity); | |
452 | return -1; | |
453 | } | |
454 | ||
455 | state.termios.c_cflag &= ~(PARENB | PARODD); | |
456 | state.termios.c_cflag |= newparity; | |
457 | ||
458 | return set_tty_state (scb, &state); | |
459 | } | |
460 | ||
461 | ||
462 | static void | |
463 | hardwire_close (struct serial *scb) | |
464 | { | |
465 | if (scb->fd < 0) | |
466 | return; | |
467 | ||
468 | close (scb->fd); | |
469 | scb->fd = -1; | |
470 | } | |
471 | \f | |
472 | \f | |
473 | ||
474 | /* The hardwire ops. */ | |
475 | ||
476 | static const struct serial_ops hardwire_ops = | |
477 | { | |
478 | "hardwire", | |
479 | hardwire_open, | |
480 | hardwire_close, | |
481 | NULL, | |
482 | ser_base_readchar, | |
483 | ser_base_write, | |
484 | hardwire_flush_output, | |
485 | hardwire_flush_input, | |
486 | hardwire_send_break, | |
487 | hardwire_raw, | |
488 | hardwire_get_tty_state, | |
489 | hardwire_copy_tty_state, | |
490 | hardwire_set_tty_state, | |
491 | hardwire_print_tty_state, | |
492 | hardwire_setbaudrate, | |
493 | hardwire_setstopbits, | |
494 | hardwire_setparity, | |
495 | hardwire_drain_output, | |
496 | ser_base_async, | |
497 | ser_unix_read_prim, | |
498 | ser_unix_write_prim | |
499 | }; | |
500 | ||
501 | void _initialize_ser_hardwire (); | |
502 | void | |
503 | _initialize_ser_hardwire () | |
504 | { | |
505 | serial_add_interface (&hardwire_ops); | |
506 | ||
507 | #ifdef CRTSCTS | |
508 | add_setshow_boolean_cmd ("remoteflow", no_class, | |
509 | &serial_hwflow, _("\ | |
510 | Set use of hardware flow control for remote serial I/O."), _("\ | |
511 | Show use of hardware flow control for remote serial I/O."), _("\ | |
512 | Enable or disable hardware flow control (RTS/CTS) on the serial port\n\ | |
513 | when debugging using remote targets."), | |
514 | NULL, | |
515 | show_serial_hwflow, | |
516 | &setlist, &showlist); | |
517 | #endif | |
518 | } | |
519 | ||
520 | int | |
521 | ser_unix_read_prim (struct serial *scb, size_t count) | |
522 | { | |
523 | return read (scb->fd, scb->buf, count); | |
524 | } | |
525 | ||
526 | int | |
527 | ser_unix_write_prim (struct serial *scb, const void *buf, size_t len) | |
528 | { | |
529 | return write (scb->fd, buf, len); | |
530 | } |