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