1 /* Generic serial interface routines
2 Copyright 1992, 1993, 1996 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23 #include "gdb_string.h"
26 /* Linked list of serial I/O handlers */
28 static struct serial_ops *serial_ops_list = NULL;
30 /* This is the last serial stream opened. Used by connect command. */
32 static serial_t last_serial_opened = NULL;
34 /* Pointer to list of scb's. */
36 static serial_t scb_base;
38 /* Non-NULL gives filename which contains a recording of the remote session,
39 suitable for playback by gdbserver. */
41 char *serial_logfile = NULL;
42 FILE *serial_logfp = NULL;
45 static int serial_reading = 0;
46 static int serial_writing = 0;
49 serial_log_command (cmd)
52 if (serial_reading || serial_writing)
54 fputc_unfiltered ('\n', serial_logfp);
58 fprintf_unfiltered (serial_logfp, "c %s\n", cmd);
59 /* Make sure that the log file is as up-to-date as possible,
60 in case we are getting ready to dump core or something. */
61 fflush (serial_logfp);
70 case '\\': fputs_unfiltered ("\\\\", serial_logfp); break;
71 case '\b': fputs_unfiltered ("\\b", serial_logfp); break;
72 case '\f': fputs_unfiltered ("\\f", serial_logfp); break;
73 case '\n': fputs_unfiltered ("\\n", serial_logfp); break;
74 case '\r': fputs_unfiltered ("\\r", serial_logfp); break;
75 case '\t': fputs_unfiltered ("\\t", serial_logfp); break;
76 case '\v': fputs_unfiltered ("\\v", serial_logfp); break;
77 default: fprintf_unfiltered (serial_logfp, isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF); break;
82 serial_write (scb, str, len)
89 if (serial_logfp != NULL)
93 fputc_unfiltered ('\n', serial_logfp);
102 for (count = 0; count < len; count++)
104 serial_logchar (str[count]);
106 /* Make sure that the log file is as up-to-date as possible,
107 in case we are getting ready to dump core or something. */
108 fflush (serial_logfp);
110 return (scb -> ops -> write (scb, str, len));
114 serial_readchar (scb, timeout)
120 ch = scb -> ops -> readchar (scb, timeout);
121 if (serial_logfp != NULL)
125 fputc_unfiltered ('\n', serial_logfp);
130 serial_logchar ('r');
131 serial_logchar (' ');
135 /* Make sure that the log file is as up-to-date as possible,
136 in case we are getting ready to dump core or something. */
137 fflush (serial_logfp);
142 static struct serial_ops *
143 serial_interface_lookup (name)
146 struct serial_ops *ops;
148 for (ops = serial_ops_list; ops; ops = ops->next)
149 if (strcmp (name, ops->name) == 0)
156 serial_add_interface(optable)
157 struct serial_ops *optable;
159 optable->next = serial_ops_list;
160 serial_ops_list = optable;
163 /* Open up a device or a network socket, depending upon the syntax of NAME. */
170 struct serial_ops *ops;
172 for (scb = scb_base; scb; scb = scb->next)
173 if (scb->name && strcmp (scb->name, name) == 0)
179 if (strcmp (name, "pc") == 0)
180 ops = serial_interface_lookup ("pc");
181 else if (strchr (name, ':'))
182 ops = serial_interface_lookup ("tcp");
183 else if (strncmp (name, "lpt", 3) == 0)
184 ops = serial_interface_lookup ("parallel");
186 ops = serial_interface_lookup ("hardwire");
191 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
196 scb->bufp = scb->buf;
198 if (scb->ops->open(scb, name))
204 scb->name = strsave (name);
205 scb->next = scb_base;
209 last_serial_opened = scb;
211 if (serial_logfile != NULL)
213 serial_logfp = fopen (serial_logfile, "w");
214 if (serial_logfp == NULL)
216 perror_with_name (serial_logfile);
228 struct serial_ops *ops;
230 for (scb = scb_base; scb; scb = scb->next)
237 ops = serial_interface_lookup ("hardwire");
242 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
247 scb->bufp = scb->buf;
252 scb->next = scb_base;
256 last_serial_opened = scb;
262 serial_close(scb, really_close)
268 last_serial_opened = NULL;
272 if (serial_reading || serial_writing)
274 fputc_unfiltered ('\n', serial_logfp);
278 fclose (serial_logfp);
282 /* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you
283 should fix your code instead. */
293 scb->ops->close (scb);
299 scb_base = scb_base->next;
301 for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
303 if (tmp_scb->next != scb)
306 tmp_scb->next = tmp_scb->next->next;
315 The connect command is #if 0 because I hadn't thought of an elegant
316 way to wait for I/O on two serial_t's simultaneously. Two solutions
319 1) Fork, and have have one fork handle the to user direction,
320 and have the other hand the to target direction. This
321 obviously won't cut it for MSDOS.
323 2) Use something like select. This assumes that stdin and
324 the target side can both be waited on via the same
325 mechanism. This may not be true for DOS, if GDB is
326 talking to the target via a TCP socket.
330 /* Connect the user directly to the remote system. This command acts just like
331 the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
333 static serial_t tty_desc; /* Controlling terminal */
336 cleanup_tty(ttystate)
337 serial_ttystate ttystate;
339 printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
340 SERIAL_SET_TTY_STATE (tty_desc, ttystate);
342 SERIAL_CLOSE (tty_desc);
346 connect_command (args, fromtty)
352 serial_ttystate ttystate;
353 serial_t port_desc; /* TTY port */
358 fprintf_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n");
360 printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n");
362 tty_desc = SERIAL_FDOPEN (0);
363 port_desc = last_serial_opened;
365 ttystate = SERIAL_GET_TTY_STATE (tty_desc);
367 SERIAL_RAW (tty_desc);
368 SERIAL_RAW (port_desc);
370 make_cleanup (cleanup_tty, ttystate);
376 mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
384 c = SERIAL_READCHAR(tty_desc, 0);
386 if (c == SERIAL_TIMEOUT)
390 perror_with_name("connect");
393 SERIAL_WRITE(port_desc, &cx, 1);
408 if (c == '.' || c == '\004')
422 c = SERIAL_READCHAR(port_desc, 0);
424 if (c == SERIAL_TIMEOUT)
428 perror_with_name("connect");
432 SERIAL_WRITE(tty_desc, &cx, 1);
441 #ifdef ANSI_PROTOTYPES
442 serial_printf (serial_t desc, const char *format, ...)
444 serial_printf (va_alist)
450 #ifdef ANSI_PROTOTYPES
451 va_start (args, format);
457 desc = va_arg (args, serial_t);
458 format = va_arg (args, char *);
461 vasprintf (&buf, format, args);
462 SERIAL_WRITE (desc, buf, strlen (buf));
469 _initialize_serial ()
472 add_com ("connect", class_obscure, connect_command,
473 "Connect the terminal directly up to the command monitor.\n\
474 Use <CR>~. or <CR>~^D to break out.");
477 add_show_from_set (add_set_cmd ("remotelogfile", no_class,
478 var_filename, (char *)&serial_logfile,
479 "Set filename for remote session recording.\n\
480 This file is used to record the remote session for future playback\n\
481 by gdbserver.", &setlist),