set the other three terminal state pieces for systems that HAVE_SGTTY
[external/binutils.git] / gdb / ser-unix.c
1 /* Serial interface for local (hardwired) serial ports on Un*x like systems
2    Copyright 1992, 1993 Free Software Foundation, Inc.
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"
21 #include "serial.h"
22 #include <fcntl.h>
23 #include <sys/types.h>
24
25 #if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY)
26 #define HAVE_SGTTY
27 #endif
28
29 #ifdef HAVE_TERMIOS
30 #include <termios.h>
31 #include <unistd.h>
32
33 struct hardwire_ttystate
34 {
35   struct termios termios;
36 };
37 #endif /* termios */
38
39 #ifdef HAVE_TERMIO
40 #include <termio.h>
41
42 /* It is believed that all systems which have added job control to SVR3
43    (e.g. sco) have also added termios.  Even if not, trying to figure out
44    all the variations (TIOCGPGRP vs. TCGETPGRP, etc.) would be pretty
45    bewildering.  So we don't attempt it.  */
46
47 struct hardwire_ttystate
48 {
49   struct termio termio;
50 };
51 #endif /* termio */
52
53 #ifdef HAVE_SGTTY
54 /* Needed for the code which uses select().  We would include <sys/select.h>
55    too if it existed on all systems.  */
56 #include <sys/time.h>
57
58 #include <sgtty.h>
59
60 struct hardwire_ttystate
61 {
62   struct sgttyb sgttyb;
63   struct tchars tc;
64   struct ltchars ltc;
65   /* Line discipline flags.  */
66   int lmode;
67 };
68 #endif /* sgtty */
69
70 static int hardwire_open PARAMS ((serial_t scb, const char *name));
71 static void hardwire_raw PARAMS ((serial_t scb));
72 static int wait_for PARAMS ((serial_t scb, int timeout));
73 static int hardwire_readchar PARAMS ((serial_t scb, int timeout));
74 static int rate_to_code PARAMS ((int rate));
75 static int hardwire_setbaudrate PARAMS ((serial_t scb, int rate));
76 static int hardwire_write PARAMS ((serial_t scb, const char *str, int len));
77 /* FIXME: static void hardwire_restore PARAMS ((serial_t scb)); */
78 static void hardwire_close PARAMS ((serial_t scb));
79 static int get_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
80 static int set_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
81 static serial_ttystate hardwire_get_tty_state PARAMS ((serial_t scb));
82 static int hardwire_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
83
84 /* Open up a real live device for serial I/O */
85
86 static int
87 hardwire_open(scb, name)
88      serial_t scb;
89      const char *name;
90 {
91   scb->fd = open (name, O_RDWR);
92   if (scb->fd < 0)
93     return -1;
94
95   return 0;
96 }
97
98 static int
99 get_tty_state(scb, state)
100      serial_t scb;
101      struct hardwire_ttystate *state;
102 {
103 #ifdef HAVE_TERMIOS
104   extern int errno;
105
106   if (tcgetattr(scb->fd, &state->termios) < 0)
107     return -1;
108
109   return 0;
110 #endif
111
112 #ifdef HAVE_TERMIO
113   if (ioctl (scb->fd, TCGETA, &state->termio) < 0)
114     return -1;
115   return 0;
116 #endif
117
118 #ifdef HAVE_SGTTY
119   if (ioctl (scb->fd, TIOCGETP, &state->sgttyb) < 0)
120     return -1;
121   if (ioctl (scb->fd, TIOCGETC, &state->tc) < 0)
122     return -1;
123   if (ioctl (scb->fd, TIOCGLTC, &state->ltc) < 0)
124     return -1;
125   if (ioctl (scb->fd, TIOCLGET, &state->lmode) < 0)
126     return -1;
127
128   return 0;
129 #endif
130 }
131
132 static int
133 set_tty_state(scb, state)
134      serial_t scb;
135      struct hardwire_ttystate *state;
136 {
137 #ifdef HAVE_TERMIOS
138   if (tcsetattr(scb->fd, TCSANOW, &state->termios) < 0)
139     return -1;
140
141   return 0;
142 #endif
143
144 #ifdef HAVE_TERMIO
145   if (ioctl (scb->fd, TCSETA, &state->termio) < 0)
146     return -1;
147   return 0;
148 #endif
149
150 #ifdef HAVE_SGTTY
151   if (ioctl (scb->fd, TIOCSETN, &state->sgttyb) < 0)
152     return -1;
153   if (ioctl (scb->fd, TIOCSETC, &state->tc) < 0)
154     return -1;
155   if (ioctl (scb->fd, TIOCSLTC, &state->ltc) < 0)
156     return -1;
157   if (ioctl (scb->fd, TIOCLSET, &state->lmode) < 0)
158     return -1;
159
160   return 0;
161 #endif
162 }
163
164 static serial_ttystate
165 hardwire_get_tty_state(scb)
166      serial_t scb;
167 {
168   struct hardwire_ttystate *state;
169
170   state = (struct hardwire_ttystate *)xmalloc(sizeof *state);
171
172   if (get_tty_state(scb, state))
173     return NULL;
174
175   return (serial_ttystate)state;
176 }
177
178 static int
179 hardwire_set_tty_state(scb, ttystate)
180      serial_t scb;
181      serial_ttystate ttystate;
182 {
183   struct hardwire_ttystate *state;
184
185   state = (struct hardwire_ttystate *)ttystate;
186
187   return set_tty_state(scb, state);
188 }
189
190 static int
191 hardwire_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
192      serial_t scb;
193      serial_ttystate new_ttystate;
194      serial_ttystate old_ttystate;
195 {
196   struct hardwire_ttystate new_state;
197   struct hardwire_ttystate *state = (struct hardwire_ttystate *) old_ttystate;
198
199   new_state = *(struct hardwire_ttystate *)new_ttystate;
200
201 #ifdef HAVE_TERMIOS
202   /* I'm not sure whether this is necessary; the manpage makes no mention
203      of discarding input when switching to/from ICANON.  */
204   if (state->termios.c_lflag & ICANON)
205     new_state.termios.c_lflag |= ICANON;
206   else
207     new_state.termios.c_lflag &= ~ICANON;
208 #endif
209
210 #ifdef HAVE_TERMIO
211   /* I'm not sure whether this is necessary; the manpage makes no mention
212      of discarding input when switching to/from ICANON.  */
213   if (state->termio.c_lflag & ICANON)
214     new_state.termio.c_lflag |= ICANON;
215   else
216     new_state.termio.c_lflag &= ~ICANON;
217 #endif
218
219 #ifdef HAVE_SGTTY
220   if (state->sgttyb.sg_flags & RAW)
221     new_state.sgttyb.sg_flags |= RAW;
222   else
223     new_state.sgttyb.sg_flags &= ~RAW;
224
225   /* I'm not sure whether this is necessary; the manpage just mentions
226      RAW not CBREAK.  */
227   if (state->sgttyb.sg_flags & CBREAK)
228     new_state.sgttyb.sg_flags |= CBREAK;
229   else
230     new_state.sgttyb.sg_flags &= ~CBREAK;
231 #endif
232
233   return set_tty_state (scb, &new_state);
234 }
235
236 static void
237 hardwire_print_tty_state (scb, ttystate)
238      serial_t scb;
239      serial_ttystate ttystate;
240 {
241   struct hardwire_ttystate *state = (struct hardwire_ttystate *) ttystate;
242   int i;
243
244 #ifdef HAVE_TERMIOS
245   printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n",
246                    state->termios.c_iflag, state->termios.c_oflag);
247   printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x\n",
248                    state->termios.c_cflag, state->termios.c_lflag);
249 #if 0
250   /* This not in POSIX, and is not really documented by those systems
251      which have it (at least not Sun).  */
252   printf_filtered ("c_line = 0x%x.\n", state->termios.c_line);
253 #endif
254   printf_filtered ("c_cc: ");
255   for (i = 0; i < NCCS; i += 1)
256     printf_filtered ("0x%x ", state->termios.c_cc[i]);
257   printf_filtered ("\n");
258 #endif
259
260 #ifdef HAVE_TERMIO
261   printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n",
262                    state->termio.c_iflag, state->termio.c_oflag);
263   printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
264                    state->termio.c_cflag, state->termio.c_lflag,
265                    state->termio.c_line);
266   printf_filtered ("c_cc: ");
267   for (i = 0; i < NCC; i += 1)
268     printf_filtered ("0x%x ", state->termio.c_cc[i]);
269   printf_filtered ("\n");
270 #endif
271
272 #ifdef HAVE_SGTTY
273   printf_filtered ("sgttyb.sg_flags = 0x%x.\n", state->sgttyb.sg_flags);
274
275   printf_filtered ("tchars: ");
276   for (i = 0; i < (int)sizeof (struct tchars); i++)
277     printf_filtered ("0x%x ", ((unsigned char *)&state->tc)[i]);
278   printf_filtered ("\n");
279
280   printf_filtered ("ltchars: ");
281   for (i = 0; i < (int)sizeof (struct ltchars); i++)
282     printf_filtered ("0x%x ", ((unsigned char *)&state->ltc)[i]);
283   printf_filtered ("\n");
284
285   printf_filtered ("lmode:  0x%x\n", state->lmode);
286 #endif
287 }
288
289 static int
290 hardwire_flush_output (scb)
291      serial_t scb;
292 {
293 #ifdef HAVE_TERMIOS
294   return tcflush (scb->fd, TCOFLUSH);
295 #endif
296
297 #ifdef HAVE_TERMIO
298   return ioctl (scb->fd, TCFLSH, 1);
299 #endif
300
301 #ifdef HAVE_SGTTY
302   /* This flushes both input and output, but we can't do better.  */
303   return ioctl (scb->fd, TIOCFLUSH, 0);
304 #endif  
305 }
306
307 static int
308 hardwire_flush_input (scb)
309      serial_t scb;
310 {
311 #ifdef HAVE_TERMIOS
312   return tcflush (scb->fd, TCIFLUSH);
313 #endif
314
315 #ifdef HAVE_TERMIO
316   return ioctl (scb->fd, TCFLSH, 0);
317 #endif
318
319 #ifdef HAVE_SGTTY
320   /* This flushes both input and output, but we can't do better.  */
321   return ioctl (scb->fd, TIOCFLUSH, 0);
322 #endif  
323 }
324
325 static int
326 hardwire_send_break (scb)
327      serial_t scb;
328 {
329 #ifdef HAVE_TERMIOS
330   return tcsendbreak (scb->fd, 0);
331 #endif
332
333 #ifdef HAVE_TERMIO
334   return ioctl (scb->fd, TCSBRK, 0);
335 #endif
336
337 #ifdef HAVE_SGTTY
338   {
339     int status;
340     struct timeval timeout;
341
342     status = ioctl (scb->fd, TIOCSBRK, 0);
343
344     /* Can't use usleep; it doesn't exist in BSD 4.2.  */
345     /* Note that if this select() is interrupted by a signal it will not wait
346        the full length of time.  I think that is OK.  */
347     timeout.tv_sec = 0;
348     timeout.tv_usec = 250000;
349     select (0, 0, 0, 0, &timeout);
350     status = ioctl (scb->fd, TIOCCBRK, 0);
351     return status;
352   }
353 #endif  
354 }
355
356 static void
357 hardwire_raw(scb)
358      serial_t scb;
359 {
360   struct hardwire_ttystate state;
361
362   if (get_tty_state(scb, &state))
363     fprintf_unfiltered(gdb_stderr, "get_tty_state failed: %s\n", safe_strerror(errno));
364
365 #ifdef HAVE_TERMIOS
366   state.termios.c_iflag = 0;
367   state.termios.c_oflag = 0;
368   state.termios.c_lflag = 0;
369   state.termios.c_cflag &= ~(CSIZE|PARENB);
370   state.termios.c_cflag |= CS8;
371   state.termios.c_cc[VMIN] = 0;
372   state.termios.c_cc[VTIME] = 0;
373 #endif
374
375 #ifdef HAVE_TERMIO
376   state.termio.c_iflag = 0;
377   state.termio.c_oflag = 0;
378   state.termio.c_lflag = 0;
379   state.termio.c_cflag &= ~(CSIZE|PARENB);
380   state.termio.c_cflag |= CS8;
381   state.termio.c_cc[VMIN] = 0;
382   state.termio.c_cc[VTIME] = 0;
383 #endif
384
385 #ifdef HAVE_SGTTY
386   state.sgttyb.sg_flags |= RAW | ANYP;
387   state.sgttyb.sg_flags &= ~(CBREAK | ECHO);
388 #endif
389
390   scb->current_timeout = 0;
391
392   if (set_tty_state (scb, &state))
393     fprintf_unfiltered(gdb_stderr, "set_tty_state failed: %s\n", safe_strerror(errno));
394 }
395
396 /* Wait for input on scb, with timeout seconds.  Returns 0 on success,
397    otherwise SERIAL_TIMEOUT or SERIAL_ERROR.
398
399    For termio{s}, we actually just setup VTIME if necessary, and let the
400    timeout occur in the read() in hardwire_read().
401  */
402
403 static int
404 wait_for(scb, timeout)
405      serial_t scb;
406      int timeout;
407 {
408 #ifdef HAVE_SGTTY
409   struct timeval tv;
410   fd_set readfds;
411
412   FD_ZERO (&readfds);
413
414   tv.tv_sec = timeout;
415   tv.tv_usec = 0;
416
417   FD_SET(scb->fd, &readfds);
418
419   while (1)
420     {
421       int numfds;
422
423       if (timeout >= 0)
424         numfds = select(scb->fd+1, &readfds, 0, 0, &tv);
425       else
426         numfds = select(scb->fd+1, &readfds, 0, 0, 0);
427
428       if (numfds <= 0)
429         if (numfds == 0)
430           return SERIAL_TIMEOUT;
431         else if (errno == EINTR)
432           continue;
433         else
434           return SERIAL_ERROR;  /* Got an error from select or poll */
435
436       return 0;
437     }
438
439 #endif  /* HAVE_SGTTY */
440
441 #if defined HAVE_TERMIO || defined HAVE_TERMIOS
442   if (timeout == scb->current_timeout)
443     return 0;
444
445   {
446     struct hardwire_ttystate state;
447
448     if (get_tty_state(scb, &state))
449       fprintf_unfiltered(gdb_stderr, "get_tty_state failed: %s\n", safe_strerror(errno));
450
451 #ifdef HAVE_TERMIOS
452     state.termios.c_cc[VTIME] = timeout * 10;
453 #endif
454
455 #ifdef HAVE_TERMIO
456     state.termio.c_cc[VTIME] = timeout * 10;
457 #endif
458
459     scb->current_timeout = timeout;
460
461     if (set_tty_state (scb, &state))
462       fprintf_unfiltered(gdb_stderr, "set_tty_state failed: %s\n", safe_strerror(errno));
463
464     return 0;
465   }
466 #endif  /* HAVE_TERMIO || HAVE_TERMIOS */
467 }
468
469 /* Read a character with user-specified timeout.  TIMEOUT is number of seconds
470    to wait, or -1 to wait forever.  Use timeout of 0 to effect a poll.  Returns
471    char if successful.  Returns SERIAL_TIMEOUT if timeout expired, EOF if line
472    dropped dead, or SERIAL_ERROR for any other error (see errno in that case).  */
473
474 static int
475 hardwire_readchar(scb, timeout)
476      serial_t scb;
477      int timeout;
478 {
479   int status;
480
481   if (scb->bufcnt-- > 0)
482     return *scb->bufp++;
483
484   status = wait_for(scb, timeout);
485
486   if (status < 0)
487     return status;
488
489   scb->bufcnt = read(scb->fd, scb->buf, BUFSIZ);
490
491   if (scb->bufcnt <= 0)
492     if (scb->bufcnt == 0)
493       return SERIAL_TIMEOUT;    /* 0 chars means timeout [may need to
494                                    distinguish between EOF & timeouts
495                                    someday] */
496     else
497       return SERIAL_ERROR;      /* Got an error from read */
498
499   scb->bufcnt--;
500   scb->bufp = scb->buf;
501   return *scb->bufp++;
502 }
503
504 #ifndef B19200
505 #define B19200 EXTA
506 #endif
507
508 #ifndef B38400
509 #define B38400 EXTB
510 #endif
511
512 /* Translate baud rates from integers to damn B_codes.  Unix should
513    have outgrown this crap years ago, but even POSIX wouldn't buck it.  */
514
515 static struct
516 {
517   int rate;
518   int code;
519 }
520 baudtab[] =
521 {
522   {50, B50},
523   {75, B75},
524   {110, B110},
525   {134, B134},
526   {150, B150},
527   {200, B200},
528   {300, B300},
529   {600, B600},
530   {1200, B1200},
531   {1800, B1800},
532   {2400, B2400},
533   {4800, B4800},
534   {9600, B9600},
535   {19200, B19200},
536   {38400, B38400},
537   {-1, -1},
538 };
539
540 static int 
541 rate_to_code(rate)
542      int rate;
543 {
544   int i;
545
546   for (i = 0; baudtab[i].rate != -1; i++)
547     if (rate == baudtab[i].rate)  
548       return baudtab[i].code;
549
550   return -1;
551 }
552
553 static int
554 hardwire_setbaudrate(scb, rate)
555      serial_t scb;
556      int rate;
557 {
558   struct hardwire_ttystate state;
559
560   if (get_tty_state(scb, &state))
561     return -1;
562
563 #ifdef HAVE_TERMIOS
564   cfsetospeed (&state.termios, rate_to_code (rate));
565   cfsetispeed (&state.termios, rate_to_code (rate));
566 #endif
567
568 #ifdef HAVE_TERMIO
569 #ifndef CIBAUD
570 #define CIBAUD CBAUD
571 #endif
572
573   state.termio.c_cflag &= ~(CBAUD | CIBAUD);
574   state.termio.c_cflag |= rate_to_code (rate);
575 #endif
576
577 #ifdef HAVE_SGTTY
578   state.sgttyb.sg_ispeed = rate_to_code (rate);
579   state.sgttyb.sg_ospeed = rate_to_code (rate);
580 #endif
581
582   return set_tty_state (scb, &state);
583 }
584
585 static int
586 hardwire_write(scb, str, len)
587      serial_t scb;
588      const char *str;
589      int len;
590 {
591   int cc;
592
593   while (len > 0)
594     {
595       cc = write(scb->fd, str, len);
596
597       if (cc < 0)
598         return 1;
599       len -= cc;
600       str += cc;
601     }
602   return 0;
603 }
604
605 static void
606 hardwire_close(scb)
607      serial_t scb;
608 {
609   if (scb->fd < 0)
610     return;
611
612   close(scb->fd);
613   scb->fd = -1;
614 }
615
616 static struct serial_ops hardwire_ops =
617 {
618   "hardwire",
619   0,
620   hardwire_open,
621   hardwire_close,
622   hardwire_readchar,
623   hardwire_write,
624   hardwire_flush_output,
625   hardwire_flush_input,
626   hardwire_send_break,
627   hardwire_raw,
628   hardwire_get_tty_state,
629   hardwire_set_tty_state,
630   hardwire_print_tty_state,
631   hardwire_noflush_set_tty_state,
632   hardwire_setbaudrate,
633 };
634
635 void
636 _initialize_ser_hardwire ()
637 {
638   serial_add_interface (&hardwire_ops);
639 }