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. */
22 #include "gdb_string.h"
25 /* Linked list of serial I/O handlers */
27 static struct serial_ops
*serial_ops_list
= NULL
;
29 /* This is the last serial stream opened. Used by connect command. */
31 static serial_t last_serial_opened
= NULL
;
33 /* Pointer to list of scb's. */
35 static serial_t scb_base
;
37 /* Non-NULL gives filename which contains a recording of the remote session,
38 suitable for playback by gdbserver. */
40 char *serial_logfile
= NULL
;
41 FILE *serial_logfp
= NULL
;
44 static int serial_reading
= 0;
45 static int serial_writing
= 0;
48 serial_log_command (cmd
)
51 if (serial_reading
|| serial_writing
)
53 fputc_unfiltered ('\n', serial_logfp
);
57 fprintf_unfiltered (serial_logfp
, "c %s\n", cmd
);
58 /* Make sure that the log file is as up-to-date as possible,
59 in case we are getting ready to dump core or something. */
60 fflush (serial_logfp
);
69 case '\\': fputs_unfiltered ("\\\\", serial_logfp
); break;
70 case '\b': fputs_unfiltered ("\\b", serial_logfp
); break;
71 case '\f': fputs_unfiltered ("\\f", serial_logfp
); break;
72 case '\n': fputs_unfiltered ("\\n", serial_logfp
); break;
73 case '\r': fputs_unfiltered ("\\r", serial_logfp
); break;
74 case '\t': fputs_unfiltered ("\\t", serial_logfp
); break;
75 case '\v': fputs_unfiltered ("\\v", serial_logfp
); break;
76 default: fprintf_unfiltered (serial_logfp
, isprint (ch
) ? "%c" : "\\x%02x", ch
& 0xFF); break;
81 serial_write (scb
, str
, len
)
88 if (serial_logfp
!= NULL
)
92 fputc_unfiltered ('\n', serial_logfp
);
101 for (count
= 0; count
< len
; count
++)
103 serial_logchar (str
[count
]);
105 /* Make sure that the log file is as up-to-date as possible,
106 in case we are getting ready to dump core or something. */
107 fflush (serial_logfp
);
109 return (scb
-> ops
-> write (scb
, str
, len
));
113 serial_readchar (scb
, timeout
)
119 ch
= scb
-> ops
-> readchar (scb
, timeout
);
120 if (serial_logfp
!= NULL
)
124 fputc_unfiltered ('\n', serial_logfp
);
129 serial_logchar ('r');
130 serial_logchar (' ');
134 /* Make sure that the log file is as up-to-date as possible,
135 in case we are getting ready to dump core or something. */
136 fflush (serial_logfp
);
141 static struct serial_ops
*
142 serial_interface_lookup (name
)
145 struct serial_ops
*ops
;
147 for (ops
= serial_ops_list
; ops
; ops
= ops
->next
)
148 if (strcmp (name
, ops
->name
) == 0)
155 serial_add_interface(optable
)
156 struct serial_ops
*optable
;
158 optable
->next
= serial_ops_list
;
159 serial_ops_list
= optable
;
162 /* Open up a device or a network socket, depending upon the syntax of NAME. */
169 struct serial_ops
*ops
;
171 for (scb
= scb_base
; scb
; scb
= scb
->next
)
172 if (scb
->name
&& strcmp (scb
->name
, name
) == 0)
178 if (strcmp (name
, "pc") == 0)
179 ops
= serial_interface_lookup ("pc");
180 else if (strchr (name
, ':'))
181 ops
= serial_interface_lookup ("tcp");
182 else if (strncmp (name
, "lpt", 3) == 0)
183 ops
= serial_interface_lookup ("parallel");
185 ops
= serial_interface_lookup ("hardwire");
190 scb
= (serial_t
)xmalloc (sizeof (struct _serial_t
));
195 scb
->bufp
= scb
->buf
;
197 if (scb
->ops
->open(scb
, name
))
203 scb
->name
= strsave (name
);
204 scb
->next
= scb_base
;
208 last_serial_opened
= scb
;
210 if (serial_logfile
!= NULL
)
212 serial_logfp
= fopen (serial_logfile
, "w");
213 if (serial_logfp
== NULL
)
215 perror_with_name (serial_logfile
);
227 struct serial_ops
*ops
;
229 for (scb
= scb_base
; scb
; scb
= scb
->next
)
236 ops
= serial_interface_lookup ("hardwire");
241 scb
= (serial_t
)xmalloc (sizeof (struct _serial_t
));
246 scb
->bufp
= scb
->buf
;
251 scb
->next
= scb_base
;
255 last_serial_opened
= scb
;
261 serial_close(scb
, really_close
)
267 last_serial_opened
= NULL
;
271 if (serial_reading
|| serial_writing
)
273 fputc_unfiltered ('\n', serial_logfp
);
277 fclose (serial_logfp
);
281 /* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you
282 should fix your code instead. */
292 scb
->ops
->close (scb
);
298 scb_base
= scb_base
->next
;
300 for (tmp_scb
= scb_base
; tmp_scb
; tmp_scb
= tmp_scb
->next
)
302 if (tmp_scb
->next
!= scb
)
305 tmp_scb
->next
= tmp_scb
->next
->next
;
314 The connect command is #if 0 because I hadn't thought of an elegant
315 way to wait for I/O on two serial_t's simultaneously. Two solutions
318 1) Fork, and have have one fork handle the to user direction,
319 and have the other hand the to target direction. This
320 obviously won't cut it for MSDOS.
322 2) Use something like select. This assumes that stdin and
323 the target side can both be waited on via the same
324 mechanism. This may not be true for DOS, if GDB is
325 talking to the target via a TCP socket.
329 /* Connect the user directly to the remote system. This command acts just like
330 the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
332 static serial_t tty_desc
; /* Controlling terminal */
335 cleanup_tty(ttystate
)
336 serial_ttystate ttystate
;
338 printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
339 SERIAL_SET_TTY_STATE (tty_desc
, ttystate
);
341 SERIAL_CLOSE (tty_desc
);
345 connect_command (args
, fromtty
)
351 serial_ttystate ttystate
;
352 serial_t port_desc
; /* TTY port */
357 fprintf_unfiltered(gdb_stderr
, "This command takes no args. They have been ignored.\n");
359 printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n");
361 tty_desc
= SERIAL_FDOPEN (0);
362 port_desc
= last_serial_opened
;
364 ttystate
= SERIAL_GET_TTY_STATE (tty_desc
);
366 SERIAL_RAW (tty_desc
);
367 SERIAL_RAW (port_desc
);
369 make_cleanup (cleanup_tty
, ttystate
);
375 mask
= SERIAL_WAIT_2 (tty_desc
, port_desc
, -1);
383 c
= SERIAL_READCHAR(tty_desc
, 0);
385 if (c
== SERIAL_TIMEOUT
)
389 perror_with_name("connect");
392 SERIAL_WRITE(port_desc
, &cx
, 1);
407 if (c
== '.' || c
== '\004')
421 c
= SERIAL_READCHAR(port_desc
, 0);
423 if (c
== SERIAL_TIMEOUT
)
427 perror_with_name("connect");
431 SERIAL_WRITE(tty_desc
, &cx
, 1);
440 #ifdef ANSI_PROTOTYPES
441 serial_printf (serial_t desc
, const char *format
, ...)
443 serial_printf (va_alist
)
449 #ifdef ANSI_PROTOTYPES
450 va_start (args
, format
);
456 desc
= va_arg (args
, serial_t
);
457 format
= va_arg (args
, char *);
460 vasprintf (&buf
, format
, args
);
461 SERIAL_WRITE (desc
, buf
, strlen (buf
));
468 _initialize_serial ()
471 add_com ("connect", class_obscure
, connect_command
,
472 "Connect the terminal directly up to the command monitor.\n\
473 Use <CR>~. or <CR>~^D to break out.");
476 add_show_from_set (add_set_cmd ("remotelogfile", no_class
,
477 var_filename
, (char *)&serial_logfile
,
478 "Set filename for remote session recording.\n\
479 This file is used to record the remote session for future playback\n\
480 by gdbserver.", &setlist
),