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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [serial.c] - Blame information for rev 105

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

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

powered by: WebSVN 2.1.0

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