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