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