119370Spst/* Generic serial interface routines
219370Spst
3130803Smarcel   Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
4130803Smarcel   2001, 2002 Free Software Foundation, Inc.
519370Spst
698944Sobrien   This file is part of GDB.
719370Spst
898944Sobrien   This program is free software; you can redistribute it and/or modify
998944Sobrien   it under the terms of the GNU General Public License as published by
1098944Sobrien   the Free Software Foundation; either version 2 of the License, or
1198944Sobrien   (at your option) any later version.
1219370Spst
1398944Sobrien   This program is distributed in the hope that it will be useful,
1498944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1598944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1698944Sobrien   GNU General Public License for more details.
1719370Spst
1898944Sobrien   You should have received a copy of the GNU General Public License
1998944Sobrien   along with this program; if not, write to the Free Software
2098944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2198944Sobrien   Boston, MA 02111-1307, USA.  */
2298944Sobrien
2319370Spst#include "defs.h"
2419370Spst#include <ctype.h>
2519370Spst#include "serial.h"
2619370Spst#include "gdb_string.h"
2719370Spst#include "gdbcmd.h"
2819370Spst
2998944Sobrienextern void _initialize_serial (void);
3098944Sobrien
3198944Sobrien/* Is serial being debugged? */
3298944Sobrien
3398944Sobrienstatic int global_serial_debug_p;
3498944Sobrien
3519370Spst/* Linked list of serial I/O handlers */
3619370Spst
3719370Spststatic struct serial_ops *serial_ops_list = NULL;
3819370Spst
3919370Spst/* This is the last serial stream opened.  Used by connect command. */
4019370Spst
4198944Sobrienstatic struct serial *last_serial_opened = NULL;
4219370Spst
4319370Spst/* Pointer to list of scb's. */
4419370Spst
4598944Sobrienstatic struct serial *scb_base;
4619370Spst
4719370Spst/* Non-NULL gives filename which contains a recording of the remote session,
4819370Spst   suitable for playback by gdbserver. */
4919370Spst
5046283Sdfrstatic char *serial_logfile = NULL;
5198944Sobrienstatic struct ui_file *serial_logfp = NULL;
5219370Spst
5398944Sobrienstatic struct serial_ops *serial_interface_lookup (char *);
5498944Sobrienstatic void serial_logchar (struct ui_file *stream, int ch_type, int ch, int timeout);
5598944Sobrienstatic const char logbase_hex[] = "hex";
5698944Sobrienstatic const char logbase_octal[] = "octal";
5798944Sobrienstatic const char logbase_ascii[] = "ascii";
5898944Sobrienstatic const char *logbase_enums[] =
5998944Sobrien{logbase_hex, logbase_octal, logbase_ascii, NULL};
6098944Sobrienstatic const char *serial_logbase = logbase_ascii;
6119370Spst
6298944Sobrien
6346283Sdfrstatic int serial_current_type = 0;
6419370Spst
6546283Sdfr/* Log char CH of type CHTYPE, with TIMEOUT */
6646283Sdfr
6746283Sdfr/* Define bogus char to represent a BREAK.  Should be careful to choose a value
6846283Sdfr   that can't be confused with a normal char, or an error code.  */
6946283Sdfr#define SERIAL_BREAK 1235
7046283Sdfr
7146283Sdfrstatic void
7298944Sobrienserial_logchar (struct ui_file *stream, int ch_type, int ch, int timeout)
7319370Spst{
7446283Sdfr  if (ch_type != serial_current_type)
7519370Spst    {
7698944Sobrien      fprintf_unfiltered (stream, "\n%c ", ch_type);
7746283Sdfr      serial_current_type = ch_type;
7819370Spst    }
7919370Spst
8046283Sdfr  if (serial_logbase != logbase_ascii)
8198944Sobrien    fputc_unfiltered (' ', stream);
8246283Sdfr
8319370Spst  switch (ch)
8419370Spst    {
8546283Sdfr    case SERIAL_TIMEOUT:
8698944Sobrien      fprintf_unfiltered (stream, "<Timeout: %d seconds>", timeout);
8746283Sdfr      return;
8846283Sdfr    case SERIAL_ERROR:
8998944Sobrien      fprintf_unfiltered (stream, "<Error: %s>", safe_strerror (errno));
9046283Sdfr      return;
9146283Sdfr    case SERIAL_EOF:
9298944Sobrien      fputs_unfiltered ("<Eof>", stream);
9346283Sdfr      return;
9446283Sdfr    case SERIAL_BREAK:
9598944Sobrien      fputs_unfiltered ("<Break>", stream);
9646283Sdfr      return;
9746283Sdfr    default:
9846283Sdfr      if (serial_logbase == logbase_hex)
9998944Sobrien	fprintf_unfiltered (stream, "%02x", ch & 0xff);
10046283Sdfr      else if (serial_logbase == logbase_octal)
10198944Sobrien	fprintf_unfiltered (stream, "%03o", ch & 0xff);
10246283Sdfr      else
10346283Sdfr	switch (ch)
10446283Sdfr	  {
10598944Sobrien	  case '\\':
10698944Sobrien	    fputs_unfiltered ("\\\\", stream);
10798944Sobrien	    break;
10898944Sobrien	  case '\b':
10998944Sobrien	    fputs_unfiltered ("\\b", stream);
11098944Sobrien	    break;
11198944Sobrien	  case '\f':
11298944Sobrien	    fputs_unfiltered ("\\f", stream);
11398944Sobrien	    break;
11498944Sobrien	  case '\n':
11598944Sobrien	    fputs_unfiltered ("\\n", stream);
11698944Sobrien	    break;
11798944Sobrien	  case '\r':
11898944Sobrien	    fputs_unfiltered ("\\r", stream);
11998944Sobrien	    break;
12098944Sobrien	  case '\t':
12198944Sobrien	    fputs_unfiltered ("\\t", stream);
12298944Sobrien	    break;
12398944Sobrien	  case '\v':
12498944Sobrien	    fputs_unfiltered ("\\v", stream);
12598944Sobrien	    break;
12698944Sobrien	  default:
12798944Sobrien	    fprintf_unfiltered (stream, isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF);
12898944Sobrien	    break;
12946283Sdfr	  }
13019370Spst    }
13119370Spst}
13219370Spst
13346283Sdfrvoid
13498944Sobrienserial_log_command (const char *cmd)
13546283Sdfr{
13646283Sdfr  if (!serial_logfp)
13746283Sdfr    return;
13846283Sdfr
13946283Sdfr  serial_current_type = 'c';
14046283Sdfr
14146283Sdfr  fputs_unfiltered ("\nc ", serial_logfp);
14246283Sdfr  fputs_unfiltered (cmd, serial_logfp);
14346283Sdfr
14446283Sdfr  /* Make sure that the log file is as up-to-date as possible,
14546283Sdfr     in case we are getting ready to dump core or something. */
14646283Sdfr  gdb_flush (serial_logfp);
14746283Sdfr}
14846283Sdfr
14998944Sobrien
15019370Spststatic struct serial_ops *
15198944Sobrienserial_interface_lookup (char *name)
15219370Spst{
15319370Spst  struct serial_ops *ops;
15419370Spst
15519370Spst  for (ops = serial_ops_list; ops; ops = ops->next)
15619370Spst    if (strcmp (name, ops->name) == 0)
15719370Spst      return ops;
15819370Spst
15919370Spst  return NULL;
16019370Spst}
16119370Spst
16219370Spstvoid
16398944Sobrienserial_add_interface (struct serial_ops *optable)
16419370Spst{
16519370Spst  optable->next = serial_ops_list;
16619370Spst  serial_ops_list = optable;
16719370Spst}
16819370Spst
16919370Spst/* Open up a device or a network socket, depending upon the syntax of NAME. */
17019370Spst
17198944Sobrienstruct serial *
17298944Sobrienserial_open (const char *name)
17319370Spst{
17498944Sobrien  struct serial *scb;
17519370Spst  struct serial_ops *ops;
17698944Sobrien  const char *open_name = name;
17719370Spst
17819370Spst  for (scb = scb_base; scb; scb = scb->next)
17919370Spst    if (scb->name && strcmp (scb->name, name) == 0)
18019370Spst      {
18119370Spst	scb->refcnt++;
18219370Spst	return scb;
18319370Spst      }
18419370Spst
18598944Sobrien  if (strcmp (name, "pc") == 0)
18619370Spst    ops = serial_interface_lookup ("pc");
18719370Spst  else if (strchr (name, ':'))
18819370Spst    ops = serial_interface_lookup ("tcp");
18919370Spst  else if (strncmp (name, "lpt", 3) == 0)
19019370Spst    ops = serial_interface_lookup ("parallel");
19198944Sobrien  else if (strncmp (name, "|", 1) == 0)
19298944Sobrien    {
19398944Sobrien      ops = serial_interface_lookup ("pipe");
19498944Sobrien      open_name = name + 1; /* discard ``|'' */
19598944Sobrien    }
19619370Spst  else
19719370Spst    ops = serial_interface_lookup ("hardwire");
19819370Spst
19919370Spst  if (!ops)
20019370Spst    return NULL;
20119370Spst
20298944Sobrien  scb = XMALLOC (struct serial);
20319370Spst
20419370Spst  scb->ops = ops;
20519370Spst
20619370Spst  scb->bufcnt = 0;
20719370Spst  scb->bufp = scb->buf;
20819370Spst
20998944Sobrien  if (scb->ops->open (scb, open_name))
21019370Spst    {
21198944Sobrien      xfree (scb);
21219370Spst      return NULL;
21319370Spst    }
21419370Spst
21598944Sobrien  scb->name = xstrdup (name);
21619370Spst  scb->next = scb_base;
21719370Spst  scb->refcnt = 1;
21898944Sobrien  scb->debug_p = 0;
21998944Sobrien  scb->async_state = 0;
22098944Sobrien  scb->async_handler = NULL;
22198944Sobrien  scb->async_context = NULL;
22219370Spst  scb_base = scb;
22319370Spst
22419370Spst  last_serial_opened = scb;
22519370Spst
22619370Spst  if (serial_logfile != NULL)
22719370Spst    {
22846283Sdfr      serial_logfp = gdb_fopen (serial_logfile, "w");
22919370Spst      if (serial_logfp == NULL)
23046283Sdfr	perror_with_name (serial_logfile);
23119370Spst    }
23219370Spst
23319370Spst  return scb;
23419370Spst}
23519370Spst
23698944Sobrienstruct serial *
23798944Sobrienserial_fdopen (const int fd)
23819370Spst{
23998944Sobrien  struct serial *scb;
24019370Spst  struct serial_ops *ops;
24119370Spst
24219370Spst  for (scb = scb_base; scb; scb = scb->next)
24319370Spst    if (scb->fd == fd)
24419370Spst      {
24519370Spst	scb->refcnt++;
24619370Spst	return scb;
24719370Spst      }
24819370Spst
24919370Spst  ops = serial_interface_lookup ("hardwire");
25019370Spst
25119370Spst  if (!ops)
25219370Spst    return NULL;
25319370Spst
25498944Sobrien  scb = XMALLOC (struct serial);
25519370Spst
25619370Spst  scb->ops = ops;
25719370Spst
25819370Spst  scb->bufcnt = 0;
25919370Spst  scb->bufp = scb->buf;
26019370Spst
26119370Spst  scb->fd = fd;
26219370Spst
26319370Spst  scb->name = NULL;
26419370Spst  scb->next = scb_base;
26519370Spst  scb->refcnt = 1;
26698944Sobrien  scb->debug_p = 0;
26798944Sobrien  scb->async_state = 0;
26898944Sobrien  scb->async_handler = NULL;
26998944Sobrien  scb->async_context = NULL;
27019370Spst  scb_base = scb;
27119370Spst
27219370Spst  last_serial_opened = scb;
27319370Spst
27419370Spst  return scb;
27519370Spst}
27619370Spst
27798944Sobrienstatic void
27898944Sobriendo_serial_close (struct serial *scb, int really_close)
27919370Spst{
28098944Sobrien  struct serial *tmp_scb;
28119370Spst
28219370Spst  last_serial_opened = NULL;
28319370Spst
28419370Spst  if (serial_logfp)
28519370Spst    {
28646283Sdfr      fputs_unfiltered ("\nEnd of log\n", serial_logfp);
28746283Sdfr      serial_current_type = 0;
28846283Sdfr
28946283Sdfr      /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */
29098944Sobrien      ui_file_delete (serial_logfp);
29119370Spst      serial_logfp = NULL;
29219370Spst    }
29319370Spst
29419370Spst/* This is bogus.  It's not our fault if you pass us a bad scb...!  Rob, you
29519370Spst   should fix your code instead.  */
29619370Spst
29719370Spst  if (!scb)
29819370Spst    return;
29919370Spst
30019370Spst  scb->refcnt--;
30119370Spst  if (scb->refcnt > 0)
30219370Spst    return;
30319370Spst
30498944Sobrien  /* ensure that the FD has been taken out of async mode */
30598944Sobrien  if (scb->async_handler != NULL)
30698944Sobrien    serial_async (scb, NULL, NULL);
30798944Sobrien
30819370Spst  if (really_close)
30919370Spst    scb->ops->close (scb);
31019370Spst
31119370Spst  if (scb->name)
31298944Sobrien    xfree (scb->name);
31319370Spst
31419370Spst  if (scb_base == scb)
31519370Spst    scb_base = scb_base->next;
31619370Spst  else
31719370Spst    for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
31819370Spst      {
31919370Spst	if (tmp_scb->next != scb)
32019370Spst	  continue;
32119370Spst
32219370Spst	tmp_scb->next = tmp_scb->next->next;
32319370Spst	break;
32419370Spst      }
32519370Spst
32698944Sobrien  xfree (scb);
32719370Spst}
32819370Spst
32998944Sobrienvoid
33098944Sobrienserial_close (struct serial *scb)
33198944Sobrien{
33298944Sobrien  do_serial_close (scb, 1);
33398944Sobrien}
33498944Sobrien
33598944Sobrienvoid
33698944Sobrienserial_un_fdopen (struct serial *scb)
33798944Sobrien{
33898944Sobrien  do_serial_close (scb, 0);
33998944Sobrien}
34098944Sobrien
34198944Sobrienint
34298944Sobrienserial_readchar (struct serial *scb, int timeout)
34398944Sobrien{
34498944Sobrien  int ch;
34598944Sobrien
34698944Sobrien  /* FIXME: cagney/1999-10-11: Don't enable this check until the ASYNC
34798944Sobrien     code is finished. */
34898944Sobrien  if (0 && serial_is_async_p (scb) && timeout < 0)
34998944Sobrien    internal_error (__FILE__, __LINE__,
35098944Sobrien		    "serial_readchar: blocking read in async mode");
35198944Sobrien
35298944Sobrien  ch = scb->ops->readchar (scb, timeout);
35398944Sobrien  if (serial_logfp != NULL)
35498944Sobrien    {
35598944Sobrien      serial_logchar (serial_logfp, 'r', ch, timeout);
35698944Sobrien
35798944Sobrien      /* Make sure that the log file is as up-to-date as possible,
35898944Sobrien         in case we are getting ready to dump core or something. */
35998944Sobrien      gdb_flush (serial_logfp);
36098944Sobrien    }
36198944Sobrien  if (serial_debug_p (scb))
36298944Sobrien    {
36398944Sobrien      fprintf_unfiltered (gdb_stdlog, "[");
36498944Sobrien      serial_logchar (gdb_stdlog, 'r', ch, timeout);
36598944Sobrien      fprintf_unfiltered (gdb_stdlog, "]");
36698944Sobrien      gdb_flush (gdb_stdlog);
36798944Sobrien    }
36898944Sobrien
36998944Sobrien  return (ch);
37098944Sobrien}
37198944Sobrien
37298944Sobrienint
37398944Sobrienserial_write (struct serial *scb, const char *str, int len)
37498944Sobrien{
37598944Sobrien  if (serial_logfp != NULL)
37698944Sobrien    {
37798944Sobrien      int count;
37898944Sobrien
37998944Sobrien      for (count = 0; count < len; count++)
38098944Sobrien	serial_logchar (serial_logfp, 'w', str[count] & 0xff, 0);
38198944Sobrien
38298944Sobrien      /* Make sure that the log file is as up-to-date as possible,
38398944Sobrien         in case we are getting ready to dump core or something. */
38498944Sobrien      gdb_flush (serial_logfp);
38598944Sobrien    }
38698944Sobrien
38798944Sobrien  return (scb->ops->write (scb, str, len));
38898944Sobrien}
38998944Sobrien
39098944Sobrienvoid
39198944Sobrienserial_printf (struct serial *desc, const char *format,...)
39298944Sobrien{
39398944Sobrien  va_list args;
39498944Sobrien  char *buf;
39598944Sobrien  va_start (args, format);
39698944Sobrien
39798944Sobrien  xvasprintf (&buf, format, args);
39898944Sobrien  serial_write (desc, buf, strlen (buf));
39998944Sobrien
40098944Sobrien  xfree (buf);
40198944Sobrien  va_end (args);
40298944Sobrien}
40398944Sobrien
40498944Sobrienint
40598944Sobrienserial_drain_output (struct serial *scb)
40698944Sobrien{
40798944Sobrien  return scb->ops->drain_output (scb);
40898944Sobrien}
40998944Sobrien
41098944Sobrienint
41198944Sobrienserial_flush_output (struct serial *scb)
41298944Sobrien{
41398944Sobrien  return scb->ops->flush_output (scb);
41498944Sobrien}
41598944Sobrien
41698944Sobrienint
41798944Sobrienserial_flush_input (struct serial *scb)
41898944Sobrien{
41998944Sobrien  return scb->ops->flush_input (scb);
42098944Sobrien}
42198944Sobrien
42298944Sobrienint
42398944Sobrienserial_send_break (struct serial *scb)
42498944Sobrien{
42598944Sobrien  if (serial_logfp != NULL)
42698944Sobrien    serial_logchar (serial_logfp, 'w', SERIAL_BREAK, 0);
42798944Sobrien
42898944Sobrien  return (scb->ops->send_break (scb));
42998944Sobrien}
43098944Sobrien
43198944Sobrienvoid
43298944Sobrienserial_raw (struct serial *scb)
43398944Sobrien{
43498944Sobrien  scb->ops->go_raw (scb);
43598944Sobrien}
43698944Sobrien
43798944Sobrienserial_ttystate
43898944Sobrienserial_get_tty_state (struct serial *scb)
43998944Sobrien{
44098944Sobrien  return scb->ops->get_tty_state (scb);
44198944Sobrien}
44298944Sobrien
44398944Sobrienint
44498944Sobrienserial_set_tty_state (struct serial *scb, serial_ttystate ttystate)
44598944Sobrien{
44698944Sobrien  return scb->ops->set_tty_state (scb, ttystate);
44798944Sobrien}
44898944Sobrien
44998944Sobrienvoid
45098944Sobrienserial_print_tty_state (struct serial *scb,
45198944Sobrien			serial_ttystate ttystate,
45298944Sobrien			struct ui_file *stream)
45398944Sobrien{
45498944Sobrien  scb->ops->print_tty_state (scb, ttystate, stream);
45598944Sobrien}
45698944Sobrien
45798944Sobrienint
45898944Sobrienserial_noflush_set_tty_state (struct serial *scb,
45998944Sobrien			      serial_ttystate new_ttystate,
46098944Sobrien			      serial_ttystate old_ttystate)
46198944Sobrien{
46298944Sobrien  return scb->ops->noflush_set_tty_state (scb, new_ttystate, old_ttystate);
46398944Sobrien}
46498944Sobrien
46598944Sobrienint
46698944Sobrienserial_setbaudrate (struct serial *scb, int rate)
46798944Sobrien{
46898944Sobrien  return scb->ops->setbaudrate (scb, rate);
46998944Sobrien}
47098944Sobrien
47198944Sobrienint
47298944Sobrienserial_setstopbits (struct serial *scb, int num)
47398944Sobrien{
47498944Sobrien  return scb->ops->setstopbits (scb, num);
47598944Sobrien}
47698944Sobrien
47798944Sobrienint
47898944Sobrienserial_can_async_p (struct serial *scb)
47998944Sobrien{
48098944Sobrien  return (scb->ops->async != NULL);
48198944Sobrien}
48298944Sobrien
48398944Sobrienint
48498944Sobrienserial_is_async_p (struct serial *scb)
48598944Sobrien{
48698944Sobrien  return (scb->ops->async != NULL) && (scb->async_handler != NULL);
48798944Sobrien}
48898944Sobrien
48998944Sobrienvoid
49098944Sobrienserial_async (struct serial *scb,
49198944Sobrien	      serial_event_ftype *handler,
49298944Sobrien	      void *context)
49398944Sobrien{
49498944Sobrien  /* Only change mode if there is a need. */
49598944Sobrien  if ((scb->async_handler == NULL)
49698944Sobrien      != (handler == NULL))
49798944Sobrien    scb->ops->async (scb, handler != NULL);
49898944Sobrien  scb->async_handler = handler;
49998944Sobrien  scb->async_context = context;
50098944Sobrien}
50198944Sobrien
50298944Sobrienint
50398944Sobriendeprecated_serial_fd (struct serial *scb)
50498944Sobrien{
50598944Sobrien  /* FIXME: should this output a warning that deprecated code is being
50698944Sobrien     called? */
50798944Sobrien  if (scb->fd < 0)
50898944Sobrien    {
50998944Sobrien      internal_error (__FILE__, __LINE__,
51098944Sobrien		      "serial: FD not valid");
51198944Sobrien    }
51298944Sobrien  return scb->fd; /* sigh */
51398944Sobrien}
51498944Sobrien
51598944Sobrienvoid
51698944Sobrienserial_debug (struct serial *scb, int debug_p)
51798944Sobrien{
51898944Sobrien  scb->debug_p = debug_p;
51998944Sobrien}
52098944Sobrien
52198944Sobrienint
52298944Sobrienserial_debug_p (struct serial *scb)
52398944Sobrien{
52498944Sobrien  return scb->debug_p || global_serial_debug_p;
52598944Sobrien}
52698944Sobrien
52798944Sobrien
52819370Spst#if 0
52998944Sobrien/* The connect command is #if 0 because I hadn't thought of an elegant
53098944Sobrien   way to wait for I/O on two `struct serial *'s simultaneously.  Two
53198944Sobrien   solutions came to mind:
53219370Spst
53398944Sobrien   1) Fork, and have have one fork handle the to user direction,
53498944Sobrien   and have the other hand the to target direction.  This
53598944Sobrien   obviously won't cut it for MSDOS.
53619370Spst
53798944Sobrien   2) Use something like select.  This assumes that stdin and
53898944Sobrien   the target side can both be waited on via the same
53998944Sobrien   mechanism.  This may not be true for DOS, if GDB is
54098944Sobrien   talking to the target via a TCP socket.
54198944Sobrien   -grossman, 8 Jun 93 */
54219370Spst
54319370Spst/* Connect the user directly to the remote system.  This command acts just like
54419370Spst   the 'cu' or 'tip' command.  Use <CR>~. or <CR>~^D to break out.  */
54519370Spst
54698944Sobrienstatic struct serial *tty_desc;	/* Controlling terminal */
54719370Spst
54819370Spststatic void
54998944Sobriencleanup_tty (serial_ttystate ttystate)
55019370Spst{
55119370Spst  printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
55298944Sobrien  serial_set_tty_state (tty_desc, ttystate);
55398944Sobrien  xfree (ttystate);
55498944Sobrien  serial_close (tty_desc);
55519370Spst}
55619370Spst
55719370Spststatic void
55898944Sobrienconnect_command (char *args, int fromtty)
55919370Spst{
56019370Spst  int c;
56119370Spst  char cur_esc = 0;
56219370Spst  serial_ttystate ttystate;
56398944Sobrien  struct serial *port_desc;		/* TTY port */
56419370Spst
56598944Sobrien  dont_repeat ();
56619370Spst
56719370Spst  if (args)
56898944Sobrien    fprintf_unfiltered (gdb_stderr, "This command takes no args.  They have been ignored.\n");
56919370Spst
57098944Sobrien  printf_unfiltered ("[Entering connect mode.  Use ~. or ~^D to escape]\n");
57198944Sobrien
57298944Sobrien  tty_desc = serial_fdopen (0);
57319370Spst  port_desc = last_serial_opened;
57419370Spst
57598944Sobrien  ttystate = serial_get_tty_state (tty_desc);
57619370Spst
57798944Sobrien  serial_raw (tty_desc);
57898944Sobrien  serial_raw (port_desc);
57919370Spst
58019370Spst  make_cleanup (cleanup_tty, ttystate);
58119370Spst
58219370Spst  while (1)
58319370Spst    {
58419370Spst      int mask;
58519370Spst
58698944Sobrien      mask = serial_wait_2 (tty_desc, port_desc, -1);
58719370Spst
58819370Spst      if (mask & 2)
58919370Spst	{			/* tty input */
59019370Spst	  char cx;
59119370Spst
59219370Spst	  while (1)
59319370Spst	    {
59498944Sobrien	      c = serial_readchar (tty_desc, 0);
59519370Spst
59619370Spst	      if (c == SERIAL_TIMEOUT)
59798944Sobrien		break;
59819370Spst
59919370Spst	      if (c < 0)
60098944Sobrien		perror_with_name ("connect");
60119370Spst
60219370Spst	      cx = c;
60398944Sobrien	      serial_write (port_desc, &cx, 1);
60419370Spst
60519370Spst	      switch (cur_esc)
60619370Spst		{
60719370Spst		case 0:
60819370Spst		  if (c == '\r')
60919370Spst		    cur_esc = c;
61019370Spst		  break;
61119370Spst		case '\r':
61219370Spst		  if (c == '~')
61319370Spst		    cur_esc = c;
61419370Spst		  else
61519370Spst		    cur_esc = 0;
61619370Spst		  break;
61719370Spst		case '~':
61819370Spst		  if (c == '.' || c == '\004')
61919370Spst		    return;
62019370Spst		  else
62119370Spst		    cur_esc = 0;
62219370Spst		}
62319370Spst	    }
62419370Spst	}
62519370Spst
62619370Spst      if (mask & 1)
62719370Spst	{			/* Port input */
62819370Spst	  char cx;
62919370Spst
63019370Spst	  while (1)
63119370Spst	    {
63298944Sobrien	      c = serial_readchar (port_desc, 0);
63319370Spst
63419370Spst	      if (c == SERIAL_TIMEOUT)
63598944Sobrien		break;
63619370Spst
63719370Spst	      if (c < 0)
63898944Sobrien		perror_with_name ("connect");
63919370Spst
64019370Spst	      cx = c;
64119370Spst
64298944Sobrien	      serial_write (tty_desc, &cx, 1);
64319370Spst	    }
64419370Spst	}
64519370Spst    }
64619370Spst}
64719370Spst#endif /* 0 */
64819370Spst
64998944Sobrien/* Serial set/show framework.  */
65019370Spst
65198944Sobrienstatic struct cmd_list_element *serial_set_cmdlist;
65298944Sobrienstatic struct cmd_list_element *serial_show_cmdlist;
65319370Spst
65498944Sobrienstatic void
65598944Sobrienserial_set_cmd (char *args, int from_tty)
65698944Sobrien{
65798944Sobrien  printf_unfiltered ("\"set serial\" must be followed by the name of a command.\n");
65898944Sobrien  help_list (serial_set_cmdlist, "set serial ", -1, gdb_stdout);
65998944Sobrien}
66019370Spst
66198944Sobrienstatic void
66298944Sobrienserial_show_cmd (char *args, int from_tty)
66398944Sobrien{
66498944Sobrien  cmd_show_list (serial_show_cmdlist, from_tty, "");
66519370Spst}
66619370Spst
66798944Sobrien
66819370Spstvoid
66998944Sobrien_initialize_serial (void)
67019370Spst{
67119370Spst#if 0
67219370Spst  add_com ("connect", class_obscure, connect_command,
67319370Spst	   "Connect the terminal directly up to the command monitor.\n\
67419370SpstUse <CR>~. or <CR>~^D to break out.");
67519370Spst#endif /* 0 */
67619370Spst
67798944Sobrien  add_prefix_cmd ("serial", class_maintenance, serial_set_cmd, "\
67898944SobrienSet default serial/parallel port configuration.",
67998944Sobrien		  &serial_set_cmdlist, "set serial ",
68098944Sobrien		  0/*allow-unknown*/,
68198944Sobrien		  &setlist);
68298944Sobrien
68398944Sobrien  add_prefix_cmd ("serial", class_maintenance, serial_show_cmd, "\
68498944SobrienShow default serial/parallel port configuration.",
68598944Sobrien		  &serial_show_cmdlist, "show serial ",
68698944Sobrien		  0/*allow-unknown*/,
68798944Sobrien		  &showlist);
68898944Sobrien
68998944Sobrien  add_show_from_set
69046283Sdfr    (add_set_cmd ("remotelogfile", no_class,
69146283Sdfr		  var_filename, (char *) &serial_logfile,
69246283Sdfr		  "Set filename for remote session recording.\n\
69319370SpstThis file is used to record the remote session for future playback\n\
69498944Sobrienby gdbserver.",
69546283Sdfr		  &setlist),
69646283Sdfr     &showlist);
69719370Spst
69898944Sobrien  add_show_from_set
69946283Sdfr    (add_set_enum_cmd ("remotelogbase", no_class,
70098944Sobrien		       logbase_enums, &serial_logbase,
70146283Sdfr		       "Set numerical base for remote session logging",
70246283Sdfr		       &setlist),
70346283Sdfr     &showlist);
70498944Sobrien
70598944Sobrien  add_show_from_set (add_set_cmd ("serial",
70698944Sobrien				  class_maintenance,
70798944Sobrien				  var_zinteger,
70898944Sobrien				  (char *)&global_serial_debug_p,
70998944Sobrien				  "Set serial debugging.\n\
71098944SobrienWhen non-zero, serial port debugging is enabled.", &setdebuglist),
71198944Sobrien		     &showdebuglist);
71219370Spst}
713