1/* Generic serial interface routines
2
3   Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
4   2001, 2002 Free Software Foundation, Inc.
5
6   This file is part of GDB.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place - Suite 330,
21   Boston, MA 02111-1307, USA.  */
22
23#include "defs.h"
24#include <ctype.h>
25#include "serial.h"
26#include "gdb_string.h"
27#include "gdbcmd.h"
28
29extern void _initialize_serial (void);
30
31/* Is serial being debugged? */
32
33static int global_serial_debug_p;
34
35/* Linked list of serial I/O handlers */
36
37static struct serial_ops *serial_ops_list = NULL;
38
39/* This is the last serial stream opened.  Used by connect command. */
40
41static struct serial *last_serial_opened = NULL;
42
43/* Pointer to list of scb's. */
44
45static struct serial *scb_base;
46
47/* Non-NULL gives filename which contains a recording of the remote session,
48   suitable for playback by gdbserver. */
49
50static char *serial_logfile = NULL;
51static struct ui_file *serial_logfp = NULL;
52
53static struct serial_ops *serial_interface_lookup (char *);
54static void serial_logchar (struct ui_file *stream, int ch_type, int ch, int timeout);
55static const char logbase_hex[] = "hex";
56static const char logbase_octal[] = "octal";
57static const char logbase_ascii[] = "ascii";
58static const char *logbase_enums[] =
59{logbase_hex, logbase_octal, logbase_ascii, NULL};
60static const char *serial_logbase = logbase_ascii;
61
62
63static int serial_current_type = 0;
64
65/* Log char CH of type CHTYPE, with TIMEOUT */
66
67/* Define bogus char to represent a BREAK.  Should be careful to choose a value
68   that can't be confused with a normal char, or an error code.  */
69#define SERIAL_BREAK 1235
70
71static void
72serial_logchar (struct ui_file *stream, int ch_type, int ch, int timeout)
73{
74  if (ch_type != serial_current_type)
75    {
76      fprintf_unfiltered (stream, "\n%c ", ch_type);
77      serial_current_type = ch_type;
78    }
79
80  if (serial_logbase != logbase_ascii)
81    fputc_unfiltered (' ', stream);
82
83  switch (ch)
84    {
85    case SERIAL_TIMEOUT:
86      fprintf_unfiltered (stream, "<Timeout: %d seconds>", timeout);
87      return;
88    case SERIAL_ERROR:
89      fprintf_unfiltered (stream, "<Error: %s>", safe_strerror (errno));
90      return;
91    case SERIAL_EOF:
92      fputs_unfiltered ("<Eof>", stream);
93      return;
94    case SERIAL_BREAK:
95      fputs_unfiltered ("<Break>", stream);
96      return;
97    default:
98      if (serial_logbase == logbase_hex)
99	fprintf_unfiltered (stream, "%02x", ch & 0xff);
100      else if (serial_logbase == logbase_octal)
101	fprintf_unfiltered (stream, "%03o", ch & 0xff);
102      else
103	switch (ch)
104	  {
105	  case '\\':
106	    fputs_unfiltered ("\\\\", stream);
107	    break;
108	  case '\b':
109	    fputs_unfiltered ("\\b", stream);
110	    break;
111	  case '\f':
112	    fputs_unfiltered ("\\f", stream);
113	    break;
114	  case '\n':
115	    fputs_unfiltered ("\\n", stream);
116	    break;
117	  case '\r':
118	    fputs_unfiltered ("\\r", stream);
119	    break;
120	  case '\t':
121	    fputs_unfiltered ("\\t", stream);
122	    break;
123	  case '\v':
124	    fputs_unfiltered ("\\v", stream);
125	    break;
126	  default:
127	    fprintf_unfiltered (stream, isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF);
128	    break;
129	  }
130    }
131}
132
133void
134serial_log_command (const char *cmd)
135{
136  if (!serial_logfp)
137    return;
138
139  serial_current_type = 'c';
140
141  fputs_unfiltered ("\nc ", serial_logfp);
142  fputs_unfiltered (cmd, serial_logfp);
143
144  /* Make sure that the log file is as up-to-date as possible,
145     in case we are getting ready to dump core or something. */
146  gdb_flush (serial_logfp);
147}
148
149
150static struct serial_ops *
151serial_interface_lookup (char *name)
152{
153  struct serial_ops *ops;
154
155  for (ops = serial_ops_list; ops; ops = ops->next)
156    if (strcmp (name, ops->name) == 0)
157      return ops;
158
159  return NULL;
160}
161
162void
163serial_add_interface (struct serial_ops *optable)
164{
165  optable->next = serial_ops_list;
166  serial_ops_list = optable;
167}
168
169/* Open up a device or a network socket, depending upon the syntax of NAME. */
170
171struct serial *
172serial_open (const char *name)
173{
174  struct serial *scb;
175  struct serial_ops *ops;
176  const char *open_name = name;
177
178  for (scb = scb_base; scb; scb = scb->next)
179    if (scb->name && strcmp (scb->name, name) == 0)
180      {
181	scb->refcnt++;
182	return scb;
183      }
184
185  if (strcmp (name, "pc") == 0)
186    ops = serial_interface_lookup ("pc");
187  else if (strchr (name, ':'))
188    ops = serial_interface_lookup ("tcp");
189  else if (strncmp (name, "lpt", 3) == 0)
190    ops = serial_interface_lookup ("parallel");
191  else if (strncmp (name, "|", 1) == 0)
192    {
193      ops = serial_interface_lookup ("pipe");
194      open_name = name + 1; /* discard ``|'' */
195    }
196  else
197    ops = serial_interface_lookup ("hardwire");
198
199  if (!ops)
200    return NULL;
201
202  scb = XMALLOC (struct serial);
203
204  scb->ops = ops;
205
206  scb->bufcnt = 0;
207  scb->bufp = scb->buf;
208
209  if (scb->ops->open (scb, open_name))
210    {
211      xfree (scb);
212      return NULL;
213    }
214
215  scb->name = xstrdup (name);
216  scb->next = scb_base;
217  scb->refcnt = 1;
218  scb->debug_p = 0;
219  scb->async_state = 0;
220  scb->async_handler = NULL;
221  scb->async_context = NULL;
222  scb_base = scb;
223
224  last_serial_opened = scb;
225
226  if (serial_logfile != NULL)
227    {
228      serial_logfp = gdb_fopen (serial_logfile, "w");
229      if (serial_logfp == NULL)
230	perror_with_name (serial_logfile);
231    }
232
233  return scb;
234}
235
236struct serial *
237serial_fdopen (const int fd)
238{
239  struct serial *scb;
240  struct serial_ops *ops;
241
242  for (scb = scb_base; scb; scb = scb->next)
243    if (scb->fd == fd)
244      {
245	scb->refcnt++;
246	return scb;
247      }
248
249  ops = serial_interface_lookup ("hardwire");
250
251  if (!ops)
252    return NULL;
253
254  scb = XMALLOC (struct serial);
255
256  scb->ops = ops;
257
258  scb->bufcnt = 0;
259  scb->bufp = scb->buf;
260
261  scb->fd = fd;
262
263  scb->name = NULL;
264  scb->next = scb_base;
265  scb->refcnt = 1;
266  scb->debug_p = 0;
267  scb->async_state = 0;
268  scb->async_handler = NULL;
269  scb->async_context = NULL;
270  scb_base = scb;
271
272  last_serial_opened = scb;
273
274  return scb;
275}
276
277static void
278do_serial_close (struct serial *scb, int really_close)
279{
280  struct serial *tmp_scb;
281
282  last_serial_opened = NULL;
283
284  if (serial_logfp)
285    {
286      fputs_unfiltered ("\nEnd of log\n", serial_logfp);
287      serial_current_type = 0;
288
289      /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */
290      ui_file_delete (serial_logfp);
291      serial_logfp = NULL;
292    }
293
294/* This is bogus.  It's not our fault if you pass us a bad scb...!  Rob, you
295   should fix your code instead.  */
296
297  if (!scb)
298    return;
299
300  scb->refcnt--;
301  if (scb->refcnt > 0)
302    return;
303
304  /* ensure that the FD has been taken out of async mode */
305  if (scb->async_handler != NULL)
306    serial_async (scb, NULL, NULL);
307
308  if (really_close)
309    scb->ops->close (scb);
310
311  if (scb->name)
312    xfree (scb->name);
313
314  if (scb_base == scb)
315    scb_base = scb_base->next;
316  else
317    for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
318      {
319	if (tmp_scb->next != scb)
320	  continue;
321
322	tmp_scb->next = tmp_scb->next->next;
323	break;
324      }
325
326  xfree (scb);
327}
328
329void
330serial_close (struct serial *scb)
331{
332  do_serial_close (scb, 1);
333}
334
335void
336serial_un_fdopen (struct serial *scb)
337{
338  do_serial_close (scb, 0);
339}
340
341int
342serial_readchar (struct serial *scb, int timeout)
343{
344  int ch;
345
346  /* FIXME: cagney/1999-10-11: Don't enable this check until the ASYNC
347     code is finished. */
348  if (0 && serial_is_async_p (scb) && timeout < 0)
349    internal_error (__FILE__, __LINE__,
350		    "serial_readchar: blocking read in async mode");
351
352  ch = scb->ops->readchar (scb, timeout);
353  if (serial_logfp != NULL)
354    {
355      serial_logchar (serial_logfp, 'r', ch, timeout);
356
357      /* Make sure that the log file is as up-to-date as possible,
358         in case we are getting ready to dump core or something. */
359      gdb_flush (serial_logfp);
360    }
361  if (serial_debug_p (scb))
362    {
363      fprintf_unfiltered (gdb_stdlog, "[");
364      serial_logchar (gdb_stdlog, 'r', ch, timeout);
365      fprintf_unfiltered (gdb_stdlog, "]");
366      gdb_flush (gdb_stdlog);
367    }
368
369  return (ch);
370}
371
372int
373serial_write (struct serial *scb, const char *str, int len)
374{
375  if (serial_logfp != NULL)
376    {
377      int count;
378
379      for (count = 0; count < len; count++)
380	serial_logchar (serial_logfp, 'w', str[count] & 0xff, 0);
381
382      /* Make sure that the log file is as up-to-date as possible,
383         in case we are getting ready to dump core or something. */
384      gdb_flush (serial_logfp);
385    }
386
387  return (scb->ops->write (scb, str, len));
388}
389
390void
391serial_printf (struct serial *desc, const char *format,...)
392{
393  va_list args;
394  char *buf;
395  va_start (args, format);
396
397  buf = xstrvprintf (format, args);
398  serial_write (desc, buf, strlen (buf));
399
400  xfree (buf);
401  va_end (args);
402}
403
404int
405serial_drain_output (struct serial *scb)
406{
407  return scb->ops->drain_output (scb);
408}
409
410int
411serial_flush_output (struct serial *scb)
412{
413  return scb->ops->flush_output (scb);
414}
415
416int
417serial_flush_input (struct serial *scb)
418{
419  return scb->ops->flush_input (scb);
420}
421
422int
423serial_send_break (struct serial *scb)
424{
425  if (serial_logfp != NULL)
426    serial_logchar (serial_logfp, 'w', SERIAL_BREAK, 0);
427
428  return (scb->ops->send_break (scb));
429}
430
431void
432serial_raw (struct serial *scb)
433{
434  scb->ops->go_raw (scb);
435}
436
437serial_ttystate
438serial_get_tty_state (struct serial *scb)
439{
440  return scb->ops->get_tty_state (scb);
441}
442
443int
444serial_set_tty_state (struct serial *scb, serial_ttystate ttystate)
445{
446  return scb->ops->set_tty_state (scb, ttystate);
447}
448
449void
450serial_print_tty_state (struct serial *scb,
451			serial_ttystate ttystate,
452			struct ui_file *stream)
453{
454  scb->ops->print_tty_state (scb, ttystate, stream);
455}
456
457int
458serial_noflush_set_tty_state (struct serial *scb,
459			      serial_ttystate new_ttystate,
460			      serial_ttystate old_ttystate)
461{
462  return scb->ops->noflush_set_tty_state (scb, new_ttystate, old_ttystate);
463}
464
465int
466serial_setbaudrate (struct serial *scb, int rate)
467{
468  return scb->ops->setbaudrate (scb, rate);
469}
470
471int
472serial_setstopbits (struct serial *scb, int num)
473{
474  return scb->ops->setstopbits (scb, num);
475}
476
477int
478serial_can_async_p (struct serial *scb)
479{
480  return (scb->ops->async != NULL);
481}
482
483int
484serial_is_async_p (struct serial *scb)
485{
486  return (scb->ops->async != NULL) && (scb->async_handler != NULL);
487}
488
489void
490serial_async (struct serial *scb,
491	      serial_event_ftype *handler,
492	      void *context)
493{
494  /* Only change mode if there is a need. */
495  if ((scb->async_handler == NULL)
496      != (handler == NULL))
497    scb->ops->async (scb, handler != NULL);
498  scb->async_handler = handler;
499  scb->async_context = context;
500}
501
502int
503deprecated_serial_fd (struct serial *scb)
504{
505  /* FIXME: should this output a warning that deprecated code is being
506     called? */
507  if (scb->fd < 0)
508    {
509      internal_error (__FILE__, __LINE__,
510		      "serial: FD not valid");
511    }
512  return scb->fd; /* sigh */
513}
514
515void
516serial_debug (struct serial *scb, int debug_p)
517{
518  scb->debug_p = debug_p;
519}
520
521int
522serial_debug_p (struct serial *scb)
523{
524  return scb->debug_p || global_serial_debug_p;
525}
526
527
528#if 0
529/* The connect command is #if 0 because I hadn't thought of an elegant
530   way to wait for I/O on two `struct serial *'s simultaneously.  Two
531   solutions came to mind:
532
533   1) Fork, and have have one fork handle the to user direction,
534   and have the other hand the to target direction.  This
535   obviously won't cut it for MSDOS.
536
537   2) Use something like select.  This assumes that stdin and
538   the target side can both be waited on via the same
539   mechanism.  This may not be true for DOS, if GDB is
540   talking to the target via a TCP socket.
541   -grossman, 8 Jun 93 */
542
543/* Connect the user directly to the remote system.  This command acts just like
544   the 'cu' or 'tip' command.  Use <CR>~. or <CR>~^D to break out.  */
545
546static struct serial *tty_desc;	/* Controlling terminal */
547
548static void
549cleanup_tty (serial_ttystate ttystate)
550{
551  printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
552  serial_set_tty_state (tty_desc, ttystate);
553  xfree (ttystate);
554  serial_close (tty_desc);
555}
556
557static void
558connect_command (char *args, int fromtty)
559{
560  int c;
561  char cur_esc = 0;
562  serial_ttystate ttystate;
563  struct serial *port_desc;		/* TTY port */
564
565  dont_repeat ();
566
567  if (args)
568    fprintf_unfiltered (gdb_stderr, "This command takes no args.  They have been ignored.\n");
569
570  printf_unfiltered ("[Entering connect mode.  Use ~. or ~^D to escape]\n");
571
572  tty_desc = serial_fdopen (0);
573  port_desc = last_serial_opened;
574
575  ttystate = serial_get_tty_state (tty_desc);
576
577  serial_raw (tty_desc);
578  serial_raw (port_desc);
579
580  make_cleanup (cleanup_tty, ttystate);
581
582  while (1)
583    {
584      int mask;
585
586      mask = serial_wait_2 (tty_desc, port_desc, -1);
587
588      if (mask & 2)
589	{			/* tty input */
590	  char cx;
591
592	  while (1)
593	    {
594	      c = serial_readchar (tty_desc, 0);
595
596	      if (c == SERIAL_TIMEOUT)
597		break;
598
599	      if (c < 0)
600		perror_with_name ("connect");
601
602	      cx = c;
603	      serial_write (port_desc, &cx, 1);
604
605	      switch (cur_esc)
606		{
607		case 0:
608		  if (c == '\r')
609		    cur_esc = c;
610		  break;
611		case '\r':
612		  if (c == '~')
613		    cur_esc = c;
614		  else
615		    cur_esc = 0;
616		  break;
617		case '~':
618		  if (c == '.' || c == '\004')
619		    return;
620		  else
621		    cur_esc = 0;
622		}
623	    }
624	}
625
626      if (mask & 1)
627	{			/* Port input */
628	  char cx;
629
630	  while (1)
631	    {
632	      c = serial_readchar (port_desc, 0);
633
634	      if (c == SERIAL_TIMEOUT)
635		break;
636
637	      if (c < 0)
638		perror_with_name ("connect");
639
640	      cx = c;
641
642	      serial_write (tty_desc, &cx, 1);
643	    }
644	}
645    }
646}
647#endif /* 0 */
648
649/* Serial set/show framework.  */
650
651static struct cmd_list_element *serial_set_cmdlist;
652static struct cmd_list_element *serial_show_cmdlist;
653
654static void
655serial_set_cmd (char *args, int from_tty)
656{
657  printf_unfiltered ("\"set serial\" must be followed by the name of a command.\n");
658  help_list (serial_set_cmdlist, "set serial ", -1, gdb_stdout);
659}
660
661static void
662serial_show_cmd (char *args, int from_tty)
663{
664  cmd_show_list (serial_show_cmdlist, from_tty, "");
665}
666
667
668void
669_initialize_serial (void)
670{
671#if 0
672  add_com ("connect", class_obscure, connect_command,
673	   "Connect the terminal directly up to the command monitor.\n\
674Use <CR>~. or <CR>~^D to break out.");
675#endif /* 0 */
676
677  add_prefix_cmd ("serial", class_maintenance, serial_set_cmd, "\
678Set default serial/parallel port configuration.",
679		  &serial_set_cmdlist, "set serial ",
680		  0/*allow-unknown*/,
681		  &setlist);
682
683  add_prefix_cmd ("serial", class_maintenance, serial_show_cmd, "\
684Show default serial/parallel port configuration.",
685		  &serial_show_cmdlist, "show serial ",
686		  0/*allow-unknown*/,
687		  &showlist);
688
689  deprecated_add_show_from_set
690    (add_set_cmd ("remotelogfile", no_class,
691		  var_filename, (char *) &serial_logfile,
692		  "Set filename for remote session recording.\n\
693This file is used to record the remote session for future playback\n\
694by gdbserver.",
695		  &setlist),
696     &showlist);
697
698  deprecated_add_show_from_set
699    (add_set_enum_cmd ("remotelogbase", no_class,
700		       logbase_enums, &serial_logbase,
701		       "Set numerical base for remote session logging",
702		       &setlist),
703     &showlist);
704
705  deprecated_add_show_from_set
706    (add_set_cmd ("serial",
707		  class_maintenance,
708		  var_zinteger,
709		  (char *)&global_serial_debug_p,
710		  "Set serial debugging.\n\
711When non-zero, serial port debugging is enabled.", &setdebuglist),
712     &showdebuglist);
713}
714