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