xref: /dflybsd-src/contrib/gdb-7/gdb/serial.c (revision de8e141f24382815c10a4012d209bbbf7abf1112)
15796c8dcSSimon Schubert /* Generic serial interface routines
25796c8dcSSimon Schubert 
3*ef5ccd6cSJohn Marino    Copyright (C) 1992-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert 
55796c8dcSSimon Schubert    This file is part of GDB.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert    (at your option) any later version.
115796c8dcSSimon Schubert 
125796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
155796c8dcSSimon Schubert    GNU General Public License for more details.
165796c8dcSSimon Schubert 
175796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
195796c8dcSSimon Schubert 
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include <ctype.h>
225796c8dcSSimon Schubert #include "serial.h"
235796c8dcSSimon Schubert #include "gdb_string.h"
245796c8dcSSimon Schubert #include "gdbcmd.h"
25*ef5ccd6cSJohn Marino #include "cli/cli-utils.h"
265796c8dcSSimon Schubert 
275796c8dcSSimon Schubert extern void _initialize_serial (void);
285796c8dcSSimon Schubert 
295796c8dcSSimon Schubert /* Is serial being debugged?  */
305796c8dcSSimon Schubert 
31*ef5ccd6cSJohn Marino static unsigned int global_serial_debug_p;
325796c8dcSSimon Schubert 
33c50c785cSJohn Marino /* Linked list of serial I/O handlers.  */
345796c8dcSSimon Schubert 
355796c8dcSSimon Schubert static struct serial_ops *serial_ops_list = NULL;
365796c8dcSSimon Schubert 
375796c8dcSSimon Schubert /* Pointer to list of scb's.  */
385796c8dcSSimon Schubert 
395796c8dcSSimon Schubert static struct serial *scb_base;
405796c8dcSSimon Schubert 
415796c8dcSSimon Schubert /* Non-NULL gives filename which contains a recording of the remote session,
425796c8dcSSimon Schubert    suitable for playback by gdbserver.  */
435796c8dcSSimon Schubert 
445796c8dcSSimon Schubert static char *serial_logfile = NULL;
455796c8dcSSimon Schubert static struct ui_file *serial_logfp = NULL;
465796c8dcSSimon Schubert 
47c50c785cSJohn Marino static struct serial_ops *serial_interface_lookup (const char *);
48c50c785cSJohn Marino static void serial_logchar (struct ui_file *stream,
49c50c785cSJohn Marino 			    int ch_type, int ch, int timeout);
505796c8dcSSimon Schubert static const char logbase_hex[] = "hex";
515796c8dcSSimon Schubert static const char logbase_octal[] = "octal";
525796c8dcSSimon Schubert static const char logbase_ascii[] = "ascii";
53*ef5ccd6cSJohn Marino static const char *const logbase_enums[] =
545796c8dcSSimon Schubert {logbase_hex, logbase_octal, logbase_ascii, NULL};
555796c8dcSSimon Schubert static const char *serial_logbase = logbase_ascii;
565796c8dcSSimon Schubert 
575796c8dcSSimon Schubert 
585796c8dcSSimon Schubert static int serial_current_type = 0;
595796c8dcSSimon Schubert 
60c50c785cSJohn Marino /* Log char CH of type CHTYPE, with TIMEOUT.  */
615796c8dcSSimon Schubert 
625796c8dcSSimon Schubert /* Define bogus char to represent a BREAK.  Should be careful to choose a value
635796c8dcSSimon Schubert    that can't be confused with a normal char, or an error code.  */
645796c8dcSSimon Schubert #define SERIAL_BREAK 1235
655796c8dcSSimon Schubert 
665796c8dcSSimon Schubert static void
serial_logchar(struct ui_file * stream,int ch_type,int ch,int timeout)675796c8dcSSimon Schubert serial_logchar (struct ui_file *stream, int ch_type, int ch, int timeout)
685796c8dcSSimon Schubert {
695796c8dcSSimon Schubert   if (ch_type != serial_current_type)
705796c8dcSSimon Schubert     {
715796c8dcSSimon Schubert       fprintf_unfiltered (stream, "\n%c ", ch_type);
725796c8dcSSimon Schubert       serial_current_type = ch_type;
735796c8dcSSimon Schubert     }
745796c8dcSSimon Schubert 
755796c8dcSSimon Schubert   if (serial_logbase != logbase_ascii)
765796c8dcSSimon Schubert     fputc_unfiltered (' ', stream);
775796c8dcSSimon Schubert 
785796c8dcSSimon Schubert   switch (ch)
795796c8dcSSimon Schubert     {
805796c8dcSSimon Schubert     case SERIAL_TIMEOUT:
815796c8dcSSimon Schubert       fprintf_unfiltered (stream, "<Timeout: %d seconds>", timeout);
825796c8dcSSimon Schubert       return;
835796c8dcSSimon Schubert     case SERIAL_ERROR:
845796c8dcSSimon Schubert       fprintf_unfiltered (stream, "<Error: %s>", safe_strerror (errno));
855796c8dcSSimon Schubert       return;
865796c8dcSSimon Schubert     case SERIAL_EOF:
875796c8dcSSimon Schubert       fputs_unfiltered ("<Eof>", stream);
885796c8dcSSimon Schubert       return;
895796c8dcSSimon Schubert     case SERIAL_BREAK:
905796c8dcSSimon Schubert       fputs_unfiltered ("<Break>", stream);
915796c8dcSSimon Schubert       return;
925796c8dcSSimon Schubert     default:
935796c8dcSSimon Schubert       if (serial_logbase == logbase_hex)
945796c8dcSSimon Schubert 	fprintf_unfiltered (stream, "%02x", ch & 0xff);
955796c8dcSSimon Schubert       else if (serial_logbase == logbase_octal)
965796c8dcSSimon Schubert 	fprintf_unfiltered (stream, "%03o", ch & 0xff);
975796c8dcSSimon Schubert       else
985796c8dcSSimon Schubert 	switch (ch)
995796c8dcSSimon Schubert 	  {
1005796c8dcSSimon Schubert 	  case '\\':
1015796c8dcSSimon Schubert 	    fputs_unfiltered ("\\\\", stream);
1025796c8dcSSimon Schubert 	    break;
1035796c8dcSSimon Schubert 	  case '\b':
1045796c8dcSSimon Schubert 	    fputs_unfiltered ("\\b", stream);
1055796c8dcSSimon Schubert 	    break;
1065796c8dcSSimon Schubert 	  case '\f':
1075796c8dcSSimon Schubert 	    fputs_unfiltered ("\\f", stream);
1085796c8dcSSimon Schubert 	    break;
1095796c8dcSSimon Schubert 	  case '\n':
1105796c8dcSSimon Schubert 	    fputs_unfiltered ("\\n", stream);
1115796c8dcSSimon Schubert 	    break;
1125796c8dcSSimon Schubert 	  case '\r':
1135796c8dcSSimon Schubert 	    fputs_unfiltered ("\\r", stream);
1145796c8dcSSimon Schubert 	    break;
1155796c8dcSSimon Schubert 	  case '\t':
1165796c8dcSSimon Schubert 	    fputs_unfiltered ("\\t", stream);
1175796c8dcSSimon Schubert 	    break;
1185796c8dcSSimon Schubert 	  case '\v':
1195796c8dcSSimon Schubert 	    fputs_unfiltered ("\\v", stream);
1205796c8dcSSimon Schubert 	    break;
1215796c8dcSSimon Schubert 	  default:
122c50c785cSJohn Marino 	    fprintf_unfiltered (stream,
123c50c785cSJohn Marino 				isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF);
1245796c8dcSSimon Schubert 	    break;
1255796c8dcSSimon Schubert 	  }
1265796c8dcSSimon Schubert     }
1275796c8dcSSimon Schubert }
1285796c8dcSSimon Schubert 
1295796c8dcSSimon Schubert void
serial_log_command(const char * cmd)1305796c8dcSSimon Schubert serial_log_command (const char *cmd)
1315796c8dcSSimon Schubert {
1325796c8dcSSimon Schubert   if (!serial_logfp)
1335796c8dcSSimon Schubert     return;
1345796c8dcSSimon Schubert 
1355796c8dcSSimon Schubert   serial_current_type = 'c';
1365796c8dcSSimon Schubert 
1375796c8dcSSimon Schubert   fputs_unfiltered ("\nc ", serial_logfp);
1385796c8dcSSimon Schubert   fputs_unfiltered (cmd, serial_logfp);
1395796c8dcSSimon Schubert 
1405796c8dcSSimon Schubert   /* Make sure that the log file is as up-to-date as possible,
1415796c8dcSSimon Schubert      in case we are getting ready to dump core or something.  */
1425796c8dcSSimon Schubert   gdb_flush (serial_logfp);
1435796c8dcSSimon Schubert }
1445796c8dcSSimon Schubert 
1455796c8dcSSimon Schubert 
1465796c8dcSSimon Schubert static struct serial_ops *
serial_interface_lookup(const char * name)147c50c785cSJohn Marino serial_interface_lookup (const char *name)
1485796c8dcSSimon Schubert {
1495796c8dcSSimon Schubert   struct serial_ops *ops;
1505796c8dcSSimon Schubert 
1515796c8dcSSimon Schubert   for (ops = serial_ops_list; ops; ops = ops->next)
1525796c8dcSSimon Schubert     if (strcmp (name, ops->name) == 0)
1535796c8dcSSimon Schubert       return ops;
1545796c8dcSSimon Schubert 
1555796c8dcSSimon Schubert   return NULL;
1565796c8dcSSimon Schubert }
1575796c8dcSSimon Schubert 
1585796c8dcSSimon Schubert void
serial_add_interface(struct serial_ops * optable)1595796c8dcSSimon Schubert serial_add_interface (struct serial_ops *optable)
1605796c8dcSSimon Schubert {
1615796c8dcSSimon Schubert   optable->next = serial_ops_list;
1625796c8dcSSimon Schubert   serial_ops_list = optable;
1635796c8dcSSimon Schubert }
1645796c8dcSSimon Schubert 
165*ef5ccd6cSJohn Marino /* Return the open serial device for FD, if found, or NULL if FD is
166*ef5ccd6cSJohn Marino    not already opened.  */
167*ef5ccd6cSJohn Marino 
168*ef5ccd6cSJohn Marino struct serial *
serial_for_fd(int fd)169*ef5ccd6cSJohn Marino serial_for_fd (int fd)
170*ef5ccd6cSJohn Marino {
171*ef5ccd6cSJohn Marino   struct serial *scb;
172*ef5ccd6cSJohn Marino 
173*ef5ccd6cSJohn Marino   for (scb = scb_base; scb; scb = scb->next)
174*ef5ccd6cSJohn Marino     if (scb->fd == fd)
175*ef5ccd6cSJohn Marino       return scb;
176*ef5ccd6cSJohn Marino 
177*ef5ccd6cSJohn Marino   return NULL;
178*ef5ccd6cSJohn Marino }
179*ef5ccd6cSJohn Marino 
1805796c8dcSSimon Schubert /* Open up a device or a network socket, depending upon the syntax of NAME.  */
1815796c8dcSSimon Schubert 
1825796c8dcSSimon Schubert struct serial *
serial_open(const char * name)1835796c8dcSSimon Schubert serial_open (const char *name)
1845796c8dcSSimon Schubert {
1855796c8dcSSimon Schubert   struct serial *scb;
1865796c8dcSSimon Schubert   struct serial_ops *ops;
1875796c8dcSSimon Schubert   const char *open_name = name;
1885796c8dcSSimon Schubert 
1895796c8dcSSimon Schubert   if (strcmp (name, "pc") == 0)
1905796c8dcSSimon Schubert     ops = serial_interface_lookup ("pc");
1915796c8dcSSimon Schubert   else if (strncmp (name, "lpt", 3) == 0)
1925796c8dcSSimon Schubert     ops = serial_interface_lookup ("parallel");
1935796c8dcSSimon Schubert   else if (strncmp (name, "|", 1) == 0)
1945796c8dcSSimon Schubert     {
1955796c8dcSSimon Schubert       ops = serial_interface_lookup ("pipe");
1965796c8dcSSimon Schubert       /* Discard ``|'' and any space before the command itself.  */
1975796c8dcSSimon Schubert       ++open_name;
198*ef5ccd6cSJohn Marino       open_name = skip_spaces_const (open_name);
1995796c8dcSSimon Schubert     }
2005796c8dcSSimon Schubert   /* Check for a colon, suggesting an IP address/port pair.
2015796c8dcSSimon Schubert      Do this *after* checking for all the interesting prefixes.  We
2025796c8dcSSimon Schubert      don't want to constrain the syntax of what can follow them.  */
2035796c8dcSSimon Schubert   else if (strchr (name, ':'))
2045796c8dcSSimon Schubert     ops = serial_interface_lookup ("tcp");
2055796c8dcSSimon Schubert   else
2065796c8dcSSimon Schubert     ops = serial_interface_lookup ("hardwire");
2075796c8dcSSimon Schubert 
2085796c8dcSSimon Schubert   if (!ops)
2095796c8dcSSimon Schubert     return NULL;
2105796c8dcSSimon Schubert 
2115796c8dcSSimon Schubert   scb = XMALLOC (struct serial);
2125796c8dcSSimon Schubert 
2135796c8dcSSimon Schubert   scb->ops = ops;
2145796c8dcSSimon Schubert 
2155796c8dcSSimon Schubert   scb->bufcnt = 0;
2165796c8dcSSimon Schubert   scb->bufp = scb->buf;
2175796c8dcSSimon Schubert   scb->error_fd = -1;
218*ef5ccd6cSJohn Marino   scb->refcnt = 1;
2195796c8dcSSimon Schubert 
220c50c785cSJohn Marino   /* `...->open (...)' would get expanded by the open(2) syscall macro.  */
2215796c8dcSSimon Schubert   if ((*scb->ops->open) (scb, open_name))
2225796c8dcSSimon Schubert     {
2235796c8dcSSimon Schubert       xfree (scb);
2245796c8dcSSimon Schubert       return NULL;
2255796c8dcSSimon Schubert     }
2265796c8dcSSimon Schubert 
2275796c8dcSSimon Schubert   scb->name = xstrdup (name);
2285796c8dcSSimon Schubert   scb->next = scb_base;
2295796c8dcSSimon Schubert   scb->debug_p = 0;
2305796c8dcSSimon Schubert   scb->async_state = 0;
2315796c8dcSSimon Schubert   scb->async_handler = NULL;
2325796c8dcSSimon Schubert   scb->async_context = NULL;
2335796c8dcSSimon Schubert   scb_base = scb;
2345796c8dcSSimon Schubert 
2355796c8dcSSimon Schubert   if (serial_logfile != NULL)
2365796c8dcSSimon Schubert     {
2375796c8dcSSimon Schubert       serial_logfp = gdb_fopen (serial_logfile, "w");
2385796c8dcSSimon Schubert       if (serial_logfp == NULL)
2395796c8dcSSimon Schubert 	perror_with_name (serial_logfile);
2405796c8dcSSimon Schubert     }
2415796c8dcSSimon Schubert 
2425796c8dcSSimon Schubert   return scb;
2435796c8dcSSimon Schubert }
2445796c8dcSSimon Schubert 
245c50c785cSJohn Marino /* Open a new serial stream using a file handle, using serial
246c50c785cSJohn Marino    interface ops OPS.  */
247c50c785cSJohn Marino 
248c50c785cSJohn Marino static struct serial *
serial_fdopen_ops(const int fd,struct serial_ops * ops)249c50c785cSJohn Marino serial_fdopen_ops (const int fd, struct serial_ops *ops)
2505796c8dcSSimon Schubert {
2515796c8dcSSimon Schubert   struct serial *scb;
2525796c8dcSSimon Schubert 
253c50c785cSJohn Marino   if (!ops)
254c50c785cSJohn Marino     {
2555796c8dcSSimon Schubert       ops = serial_interface_lookup ("terminal");
2565796c8dcSSimon Schubert       if (!ops)
2575796c8dcSSimon Schubert  	ops = serial_interface_lookup ("hardwire");
258c50c785cSJohn Marino     }
2595796c8dcSSimon Schubert 
2605796c8dcSSimon Schubert   if (!ops)
2615796c8dcSSimon Schubert     return NULL;
2625796c8dcSSimon Schubert 
2635796c8dcSSimon Schubert   scb = XCALLOC (1, struct serial);
2645796c8dcSSimon Schubert 
2655796c8dcSSimon Schubert   scb->ops = ops;
2665796c8dcSSimon Schubert 
2675796c8dcSSimon Schubert   scb->bufcnt = 0;
2685796c8dcSSimon Schubert   scb->bufp = scb->buf;
269c50c785cSJohn Marino   scb->error_fd = -1;
270*ef5ccd6cSJohn Marino   scb->refcnt = 1;
2715796c8dcSSimon Schubert 
2725796c8dcSSimon Schubert   scb->name = NULL;
2735796c8dcSSimon Schubert   scb->next = scb_base;
2745796c8dcSSimon Schubert   scb->debug_p = 0;
2755796c8dcSSimon Schubert   scb->async_state = 0;
2765796c8dcSSimon Schubert   scb->async_handler = NULL;
2775796c8dcSSimon Schubert   scb->async_context = NULL;
2785796c8dcSSimon Schubert   scb_base = scb;
2795796c8dcSSimon Schubert 
280c50c785cSJohn Marino   if ((ops->fdopen) != NULL)
281c50c785cSJohn Marino     (*ops->fdopen) (scb, fd);
282c50c785cSJohn Marino   else
283c50c785cSJohn Marino     scb->fd = fd;
284c50c785cSJohn Marino 
2855796c8dcSSimon Schubert   return scb;
2865796c8dcSSimon Schubert }
2875796c8dcSSimon Schubert 
288c50c785cSJohn Marino struct serial *
serial_fdopen(const int fd)289c50c785cSJohn Marino serial_fdopen (const int fd)
290c50c785cSJohn Marino {
291c50c785cSJohn Marino   return serial_fdopen_ops (fd, NULL);
292c50c785cSJohn Marino }
293c50c785cSJohn Marino 
2945796c8dcSSimon Schubert static void
do_serial_close(struct serial * scb,int really_close)2955796c8dcSSimon Schubert do_serial_close (struct serial *scb, int really_close)
2965796c8dcSSimon Schubert {
2975796c8dcSSimon Schubert   struct serial *tmp_scb;
2985796c8dcSSimon Schubert 
2995796c8dcSSimon Schubert   if (serial_logfp)
3005796c8dcSSimon Schubert     {
3015796c8dcSSimon Schubert       fputs_unfiltered ("\nEnd of log\n", serial_logfp);
3025796c8dcSSimon Schubert       serial_current_type = 0;
3035796c8dcSSimon Schubert 
3045796c8dcSSimon Schubert       /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr?  */
3055796c8dcSSimon Schubert       ui_file_delete (serial_logfp);
3065796c8dcSSimon Schubert       serial_logfp = NULL;
3075796c8dcSSimon Schubert     }
3085796c8dcSSimon Schubert 
309c50c785cSJohn Marino   /* ensure that the FD has been taken out of async mode.  */
3105796c8dcSSimon Schubert   if (scb->async_handler != NULL)
3115796c8dcSSimon Schubert     serial_async (scb, NULL, NULL);
3125796c8dcSSimon Schubert 
3135796c8dcSSimon Schubert   if (really_close)
3145796c8dcSSimon Schubert     scb->ops->close (scb);
3155796c8dcSSimon Schubert 
3165796c8dcSSimon Schubert   if (scb->name)
3175796c8dcSSimon Schubert     xfree (scb->name);
3185796c8dcSSimon Schubert 
319*ef5ccd6cSJohn Marino   /* For serial_is_open.  */
320*ef5ccd6cSJohn Marino   scb->bufp = NULL;
321*ef5ccd6cSJohn Marino 
3225796c8dcSSimon Schubert   if (scb_base == scb)
3235796c8dcSSimon Schubert     scb_base = scb_base->next;
3245796c8dcSSimon Schubert   else
3255796c8dcSSimon Schubert     for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
3265796c8dcSSimon Schubert       {
3275796c8dcSSimon Schubert 	if (tmp_scb->next != scb)
3285796c8dcSSimon Schubert 	  continue;
3295796c8dcSSimon Schubert 
3305796c8dcSSimon Schubert 	tmp_scb->next = tmp_scb->next->next;
3315796c8dcSSimon Schubert 	break;
3325796c8dcSSimon Schubert       }
3335796c8dcSSimon Schubert 
334*ef5ccd6cSJohn Marino   serial_unref (scb);
3355796c8dcSSimon Schubert }
3365796c8dcSSimon Schubert 
3375796c8dcSSimon Schubert void
serial_close(struct serial * scb)3385796c8dcSSimon Schubert serial_close (struct serial *scb)
3395796c8dcSSimon Schubert {
3405796c8dcSSimon Schubert   do_serial_close (scb, 1);
3415796c8dcSSimon Schubert }
3425796c8dcSSimon Schubert 
3435796c8dcSSimon Schubert void
serial_un_fdopen(struct serial * scb)3445796c8dcSSimon Schubert serial_un_fdopen (struct serial *scb)
3455796c8dcSSimon Schubert {
3465796c8dcSSimon Schubert   do_serial_close (scb, 0);
3475796c8dcSSimon Schubert }
3485796c8dcSSimon Schubert 
3495796c8dcSSimon Schubert int
serial_is_open(struct serial * scb)350*ef5ccd6cSJohn Marino serial_is_open (struct serial *scb)
351*ef5ccd6cSJohn Marino {
352*ef5ccd6cSJohn Marino   return scb->bufp != NULL;
353*ef5ccd6cSJohn Marino }
354*ef5ccd6cSJohn Marino 
355*ef5ccd6cSJohn Marino void
serial_ref(struct serial * scb)356*ef5ccd6cSJohn Marino serial_ref (struct serial *scb)
357*ef5ccd6cSJohn Marino {
358*ef5ccd6cSJohn Marino   scb->refcnt++;
359*ef5ccd6cSJohn Marino }
360*ef5ccd6cSJohn Marino 
361*ef5ccd6cSJohn Marino void
serial_unref(struct serial * scb)362*ef5ccd6cSJohn Marino serial_unref (struct serial *scb)
363*ef5ccd6cSJohn Marino {
364*ef5ccd6cSJohn Marino   --scb->refcnt;
365*ef5ccd6cSJohn Marino   if (scb->refcnt == 0)
366*ef5ccd6cSJohn Marino     xfree (scb);
367*ef5ccd6cSJohn Marino }
368*ef5ccd6cSJohn Marino 
369*ef5ccd6cSJohn Marino int
serial_readchar(struct serial * scb,int timeout)3705796c8dcSSimon Schubert serial_readchar (struct serial *scb, int timeout)
3715796c8dcSSimon Schubert {
3725796c8dcSSimon Schubert   int ch;
3735796c8dcSSimon Schubert 
3745796c8dcSSimon Schubert   /* FIXME: cagney/1999-10-11: Don't enable this check until the ASYNC
3755796c8dcSSimon Schubert      code is finished.  */
3765796c8dcSSimon Schubert   if (0 && serial_is_async_p (scb) && timeout < 0)
3775796c8dcSSimon Schubert     internal_error (__FILE__, __LINE__,
3785796c8dcSSimon Schubert 		    _("serial_readchar: blocking read in async mode"));
3795796c8dcSSimon Schubert 
3805796c8dcSSimon Schubert   ch = scb->ops->readchar (scb, timeout);
3815796c8dcSSimon Schubert   if (serial_logfp != NULL)
3825796c8dcSSimon Schubert     {
3835796c8dcSSimon Schubert       serial_logchar (serial_logfp, 'r', ch, timeout);
3845796c8dcSSimon Schubert 
3855796c8dcSSimon Schubert       /* Make sure that the log file is as up-to-date as possible,
3865796c8dcSSimon Schubert          in case we are getting ready to dump core or something.  */
3875796c8dcSSimon Schubert       gdb_flush (serial_logfp);
3885796c8dcSSimon Schubert     }
3895796c8dcSSimon Schubert   if (serial_debug_p (scb))
3905796c8dcSSimon Schubert     {
3915796c8dcSSimon Schubert       fprintf_unfiltered (gdb_stdlog, "[");
3925796c8dcSSimon Schubert       serial_logchar (gdb_stdlog, 'r', ch, timeout);
3935796c8dcSSimon Schubert       fprintf_unfiltered (gdb_stdlog, "]");
3945796c8dcSSimon Schubert       gdb_flush (gdb_stdlog);
3955796c8dcSSimon Schubert     }
3965796c8dcSSimon Schubert 
3975796c8dcSSimon Schubert   return (ch);
3985796c8dcSSimon Schubert }
3995796c8dcSSimon Schubert 
4005796c8dcSSimon Schubert int
serial_write(struct serial * scb,const char * str,int len)4015796c8dcSSimon Schubert serial_write (struct serial *scb, const char *str, int len)
4025796c8dcSSimon Schubert {
4035796c8dcSSimon Schubert   if (serial_logfp != NULL)
4045796c8dcSSimon Schubert     {
4055796c8dcSSimon Schubert       int count;
4065796c8dcSSimon Schubert 
4075796c8dcSSimon Schubert       for (count = 0; count < len; count++)
4085796c8dcSSimon Schubert 	serial_logchar (serial_logfp, 'w', str[count] & 0xff, 0);
4095796c8dcSSimon Schubert 
4105796c8dcSSimon Schubert       /* Make sure that the log file is as up-to-date as possible,
4115796c8dcSSimon Schubert          in case we are getting ready to dump core or something.  */
4125796c8dcSSimon Schubert       gdb_flush (serial_logfp);
4135796c8dcSSimon Schubert     }
414cf7f2e2dSJohn Marino   if (serial_debug_p (scb))
415cf7f2e2dSJohn Marino     {
416cf7f2e2dSJohn Marino       int count;
417cf7f2e2dSJohn Marino 
418cf7f2e2dSJohn Marino       for (count = 0; count < len; count++)
419cf7f2e2dSJohn Marino 	{
420cf7f2e2dSJohn Marino 	  fprintf_unfiltered (gdb_stdlog, "[");
421cf7f2e2dSJohn Marino 	  serial_logchar (gdb_stdlog, 'w', str[count] & 0xff, 0);
422cf7f2e2dSJohn Marino 	  fprintf_unfiltered (gdb_stdlog, "]");
423cf7f2e2dSJohn Marino 	}
424cf7f2e2dSJohn Marino       gdb_flush (gdb_stdlog);
425cf7f2e2dSJohn Marino     }
4265796c8dcSSimon Schubert 
4275796c8dcSSimon Schubert   return (scb->ops->write (scb, str, len));
4285796c8dcSSimon Schubert }
4295796c8dcSSimon Schubert 
4305796c8dcSSimon Schubert void
serial_printf(struct serial * desc,const char * format,...)4315796c8dcSSimon Schubert serial_printf (struct serial *desc, const char *format,...)
4325796c8dcSSimon Schubert {
4335796c8dcSSimon Schubert   va_list args;
4345796c8dcSSimon Schubert   char *buf;
4355796c8dcSSimon Schubert   va_start (args, format);
4365796c8dcSSimon Schubert 
4375796c8dcSSimon Schubert   buf = xstrvprintf (format, args);
4385796c8dcSSimon Schubert   serial_write (desc, buf, strlen (buf));
4395796c8dcSSimon Schubert 
4405796c8dcSSimon Schubert   xfree (buf);
4415796c8dcSSimon Schubert   va_end (args);
4425796c8dcSSimon Schubert }
4435796c8dcSSimon Schubert 
4445796c8dcSSimon Schubert int
serial_drain_output(struct serial * scb)4455796c8dcSSimon Schubert serial_drain_output (struct serial *scb)
4465796c8dcSSimon Schubert {
4475796c8dcSSimon Schubert   return scb->ops->drain_output (scb);
4485796c8dcSSimon Schubert }
4495796c8dcSSimon Schubert 
4505796c8dcSSimon Schubert int
serial_flush_output(struct serial * scb)4515796c8dcSSimon Schubert serial_flush_output (struct serial *scb)
4525796c8dcSSimon Schubert {
4535796c8dcSSimon Schubert   return scb->ops->flush_output (scb);
4545796c8dcSSimon Schubert }
4555796c8dcSSimon Schubert 
4565796c8dcSSimon Schubert int
serial_flush_input(struct serial * scb)4575796c8dcSSimon Schubert serial_flush_input (struct serial *scb)
4585796c8dcSSimon Schubert {
4595796c8dcSSimon Schubert   return scb->ops->flush_input (scb);
4605796c8dcSSimon Schubert }
4615796c8dcSSimon Schubert 
4625796c8dcSSimon Schubert int
serial_send_break(struct serial * scb)4635796c8dcSSimon Schubert serial_send_break (struct serial *scb)
4645796c8dcSSimon Schubert {
4655796c8dcSSimon Schubert   if (serial_logfp != NULL)
4665796c8dcSSimon Schubert     serial_logchar (serial_logfp, 'w', SERIAL_BREAK, 0);
4675796c8dcSSimon Schubert 
4685796c8dcSSimon Schubert   return (scb->ops->send_break (scb));
4695796c8dcSSimon Schubert }
4705796c8dcSSimon Schubert 
4715796c8dcSSimon Schubert void
serial_raw(struct serial * scb)4725796c8dcSSimon Schubert serial_raw (struct serial *scb)
4735796c8dcSSimon Schubert {
4745796c8dcSSimon Schubert   scb->ops->go_raw (scb);
4755796c8dcSSimon Schubert }
4765796c8dcSSimon Schubert 
4775796c8dcSSimon Schubert serial_ttystate
serial_get_tty_state(struct serial * scb)4785796c8dcSSimon Schubert serial_get_tty_state (struct serial *scb)
4795796c8dcSSimon Schubert {
4805796c8dcSSimon Schubert   return scb->ops->get_tty_state (scb);
4815796c8dcSSimon Schubert }
4825796c8dcSSimon Schubert 
483c50c785cSJohn Marino serial_ttystate
serial_copy_tty_state(struct serial * scb,serial_ttystate ttystate)484c50c785cSJohn Marino serial_copy_tty_state (struct serial *scb, serial_ttystate ttystate)
485c50c785cSJohn Marino {
486c50c785cSJohn Marino   return scb->ops->copy_tty_state (scb, ttystate);
487c50c785cSJohn Marino }
488c50c785cSJohn Marino 
4895796c8dcSSimon Schubert int
serial_set_tty_state(struct serial * scb,serial_ttystate ttystate)4905796c8dcSSimon Schubert serial_set_tty_state (struct serial *scb, serial_ttystate ttystate)
4915796c8dcSSimon Schubert {
4925796c8dcSSimon Schubert   return scb->ops->set_tty_state (scb, ttystate);
4935796c8dcSSimon Schubert }
4945796c8dcSSimon Schubert 
4955796c8dcSSimon Schubert void
serial_print_tty_state(struct serial * scb,serial_ttystate ttystate,struct ui_file * stream)4965796c8dcSSimon Schubert serial_print_tty_state (struct serial *scb,
4975796c8dcSSimon Schubert 			serial_ttystate ttystate,
4985796c8dcSSimon Schubert 			struct ui_file *stream)
4995796c8dcSSimon Schubert {
5005796c8dcSSimon Schubert   scb->ops->print_tty_state (scb, ttystate, stream);
5015796c8dcSSimon Schubert }
5025796c8dcSSimon Schubert 
5035796c8dcSSimon Schubert int
serial_noflush_set_tty_state(struct serial * scb,serial_ttystate new_ttystate,serial_ttystate old_ttystate)5045796c8dcSSimon Schubert serial_noflush_set_tty_state (struct serial *scb,
5055796c8dcSSimon Schubert 			      serial_ttystate new_ttystate,
5065796c8dcSSimon Schubert 			      serial_ttystate old_ttystate)
5075796c8dcSSimon Schubert {
5085796c8dcSSimon Schubert   return scb->ops->noflush_set_tty_state (scb, new_ttystate, old_ttystate);
5095796c8dcSSimon Schubert }
5105796c8dcSSimon Schubert 
5115796c8dcSSimon Schubert int
serial_setbaudrate(struct serial * scb,int rate)5125796c8dcSSimon Schubert serial_setbaudrate (struct serial *scb, int rate)
5135796c8dcSSimon Schubert {
5145796c8dcSSimon Schubert   return scb->ops->setbaudrate (scb, rate);
5155796c8dcSSimon Schubert }
5165796c8dcSSimon Schubert 
5175796c8dcSSimon Schubert int
serial_setstopbits(struct serial * scb,int num)5185796c8dcSSimon Schubert serial_setstopbits (struct serial *scb, int num)
5195796c8dcSSimon Schubert {
5205796c8dcSSimon Schubert   return scb->ops->setstopbits (scb, num);
5215796c8dcSSimon Schubert }
5225796c8dcSSimon Schubert 
5235796c8dcSSimon Schubert int
serial_can_async_p(struct serial * scb)5245796c8dcSSimon Schubert serial_can_async_p (struct serial *scb)
5255796c8dcSSimon Schubert {
5265796c8dcSSimon Schubert   return (scb->ops->async != NULL);
5275796c8dcSSimon Schubert }
5285796c8dcSSimon Schubert 
5295796c8dcSSimon Schubert int
serial_is_async_p(struct serial * scb)5305796c8dcSSimon Schubert serial_is_async_p (struct serial *scb)
5315796c8dcSSimon Schubert {
5325796c8dcSSimon Schubert   return (scb->ops->async != NULL) && (scb->async_handler != NULL);
5335796c8dcSSimon Schubert }
5345796c8dcSSimon Schubert 
5355796c8dcSSimon Schubert void
serial_async(struct serial * scb,serial_event_ftype * handler,void * context)5365796c8dcSSimon Schubert serial_async (struct serial *scb,
5375796c8dcSSimon Schubert 	      serial_event_ftype *handler,
5385796c8dcSSimon Schubert 	      void *context)
5395796c8dcSSimon Schubert {
5405796c8dcSSimon Schubert   int changed = ((scb->async_handler == NULL) != (handler == NULL));
541cf7f2e2dSJohn Marino 
5425796c8dcSSimon Schubert   scb->async_handler = handler;
5435796c8dcSSimon Schubert   scb->async_context = context;
5445796c8dcSSimon Schubert   /* Only change mode if there is a need.  */
5455796c8dcSSimon Schubert   if (changed)
5465796c8dcSSimon Schubert     scb->ops->async (scb, handler != NULL);
5475796c8dcSSimon Schubert }
5485796c8dcSSimon Schubert 
5495796c8dcSSimon Schubert void
serial_debug(struct serial * scb,int debug_p)5505796c8dcSSimon Schubert serial_debug (struct serial *scb, int debug_p)
5515796c8dcSSimon Schubert {
5525796c8dcSSimon Schubert   scb->debug_p = debug_p;
5535796c8dcSSimon Schubert }
5545796c8dcSSimon Schubert 
5555796c8dcSSimon Schubert int
serial_debug_p(struct serial * scb)5565796c8dcSSimon Schubert serial_debug_p (struct serial *scb)
5575796c8dcSSimon Schubert {
5585796c8dcSSimon Schubert   return scb->debug_p || global_serial_debug_p;
5595796c8dcSSimon Schubert }
5605796c8dcSSimon Schubert 
5615796c8dcSSimon Schubert #ifdef USE_WIN32API
5625796c8dcSSimon Schubert void
serial_wait_handle(struct serial * scb,HANDLE * read,HANDLE * except)5635796c8dcSSimon Schubert serial_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
5645796c8dcSSimon Schubert {
5655796c8dcSSimon Schubert   if (scb->ops->wait_handle)
5665796c8dcSSimon Schubert     scb->ops->wait_handle (scb, read, except);
5675796c8dcSSimon Schubert   else
5685796c8dcSSimon Schubert     {
5695796c8dcSSimon Schubert       *read = (HANDLE) _get_osfhandle (scb->fd);
5705796c8dcSSimon Schubert       *except = NULL;
5715796c8dcSSimon Schubert     }
5725796c8dcSSimon Schubert }
5735796c8dcSSimon Schubert 
5745796c8dcSSimon Schubert void
serial_done_wait_handle(struct serial * scb)5755796c8dcSSimon Schubert serial_done_wait_handle (struct serial *scb)
5765796c8dcSSimon Schubert {
5775796c8dcSSimon Schubert   if (scb->ops->done_wait_handle)
5785796c8dcSSimon Schubert     scb->ops->done_wait_handle (scb);
5795796c8dcSSimon Schubert }
5805796c8dcSSimon Schubert #endif
5815796c8dcSSimon Schubert 
582c50c785cSJohn Marino int
serial_pipe(struct serial * scbs[2])583c50c785cSJohn Marino serial_pipe (struct serial *scbs[2])
584c50c785cSJohn Marino {
585c50c785cSJohn Marino   struct serial_ops *ops;
586c50c785cSJohn Marino   int fildes[2];
587c50c785cSJohn Marino 
588c50c785cSJohn Marino   ops = serial_interface_lookup ("pipe");
589c50c785cSJohn Marino   if (!ops)
590c50c785cSJohn Marino     {
591c50c785cSJohn Marino       errno = ENOSYS;
592c50c785cSJohn Marino       return -1;
593c50c785cSJohn Marino     }
594c50c785cSJohn Marino 
595c50c785cSJohn Marino   if (gdb_pipe (fildes) == -1)
596c50c785cSJohn Marino     return -1;
597c50c785cSJohn Marino 
598c50c785cSJohn Marino   scbs[0] = serial_fdopen_ops (fildes[0], ops);
599c50c785cSJohn Marino   scbs[1] = serial_fdopen_ops (fildes[1], ops);
600c50c785cSJohn Marino   return 0;
601c50c785cSJohn Marino }
602c50c785cSJohn Marino 
6035796c8dcSSimon Schubert /* Serial set/show framework.  */
6045796c8dcSSimon Schubert 
6055796c8dcSSimon Schubert static struct cmd_list_element *serial_set_cmdlist;
6065796c8dcSSimon Schubert static struct cmd_list_element *serial_show_cmdlist;
6075796c8dcSSimon Schubert 
6085796c8dcSSimon Schubert static void
serial_set_cmd(char * args,int from_tty)6095796c8dcSSimon Schubert serial_set_cmd (char *args, int from_tty)
6105796c8dcSSimon Schubert {
611c50c785cSJohn Marino   printf_unfiltered ("\"set serial\" must be followed "
612c50c785cSJohn Marino 		     "by the name of a command.\n");
6135796c8dcSSimon Schubert   help_list (serial_set_cmdlist, "set serial ", -1, gdb_stdout);
6145796c8dcSSimon Schubert }
6155796c8dcSSimon Schubert 
6165796c8dcSSimon Schubert static void
serial_show_cmd(char * args,int from_tty)6175796c8dcSSimon Schubert serial_show_cmd (char *args, int from_tty)
6185796c8dcSSimon Schubert {
6195796c8dcSSimon Schubert   cmd_show_list (serial_show_cmdlist, from_tty, "");
6205796c8dcSSimon Schubert }
6215796c8dcSSimon Schubert 
6225796c8dcSSimon Schubert 
6235796c8dcSSimon Schubert void
_initialize_serial(void)6245796c8dcSSimon Schubert _initialize_serial (void)
6255796c8dcSSimon Schubert {
6265796c8dcSSimon Schubert #if 0
6275796c8dcSSimon Schubert   add_com ("connect", class_obscure, connect_command, _("\
6285796c8dcSSimon Schubert Connect the terminal directly up to the command monitor.\n\
6295796c8dcSSimon Schubert Use <CR>~. or <CR>~^D to break out."));
6305796c8dcSSimon Schubert #endif /* 0 */
6315796c8dcSSimon Schubert 
6325796c8dcSSimon Schubert   add_prefix_cmd ("serial", class_maintenance, serial_set_cmd, _("\
6335796c8dcSSimon Schubert Set default serial/parallel port configuration."),
6345796c8dcSSimon Schubert 		  &serial_set_cmdlist, "set serial ",
6355796c8dcSSimon Schubert 		  0/*allow-unknown*/,
6365796c8dcSSimon Schubert 		  &setlist);
6375796c8dcSSimon Schubert 
6385796c8dcSSimon Schubert   add_prefix_cmd ("serial", class_maintenance, serial_show_cmd, _("\
6395796c8dcSSimon Schubert Show default serial/parallel port configuration."),
6405796c8dcSSimon Schubert 		  &serial_show_cmdlist, "show serial ",
6415796c8dcSSimon Schubert 		  0/*allow-unknown*/,
6425796c8dcSSimon Schubert 		  &showlist);
6435796c8dcSSimon Schubert 
6445796c8dcSSimon Schubert   add_setshow_filename_cmd ("remotelogfile", no_class, &serial_logfile, _("\
6455796c8dcSSimon Schubert Set filename for remote session recording."), _("\
6465796c8dcSSimon Schubert Show filename for remote session recording."), _("\
6475796c8dcSSimon Schubert This file is used to record the remote session for future playback\n\
6485796c8dcSSimon Schubert by gdbserver."),
6495796c8dcSSimon Schubert 			    NULL,
6505796c8dcSSimon Schubert 			    NULL, /* FIXME: i18n: */
6515796c8dcSSimon Schubert 			    &setlist, &showlist);
6525796c8dcSSimon Schubert 
6535796c8dcSSimon Schubert   add_setshow_enum_cmd ("remotelogbase", no_class, logbase_enums,
6545796c8dcSSimon Schubert 			&serial_logbase, _("\
6555796c8dcSSimon Schubert Set numerical base for remote session logging"), _("\
6565796c8dcSSimon Schubert Show numerical base for remote session logging"), NULL,
6575796c8dcSSimon Schubert 			NULL,
6585796c8dcSSimon Schubert 			NULL, /* FIXME: i18n: */
6595796c8dcSSimon Schubert 			&setlist, &showlist);
6605796c8dcSSimon Schubert 
661*ef5ccd6cSJohn Marino   add_setshow_zuinteger_cmd ("serial", class_maintenance,
6625796c8dcSSimon Schubert 			     &global_serial_debug_p, _("\
6635796c8dcSSimon Schubert Set serial debugging."), _("\
6645796c8dcSSimon Schubert Show serial debugging."), _("\
6655796c8dcSSimon Schubert When non-zero, serial port debugging is enabled."),
6665796c8dcSSimon Schubert 			     NULL,
6675796c8dcSSimon Schubert 			     NULL, /* FIXME: i18n: */
6685796c8dcSSimon Schubert 			     &setdebuglist, &showdebuglist);
6695796c8dcSSimon Schubert }
670