OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [serial.c] - Blame information for rev 1767

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* Generic serial interface routines
2
 
3
   Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
4
   Free Software 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
 
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
 
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.