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