Update FSF address.
[deliverable/binutils-gdb.git] / gdb / serial.c
CommitLineData
4e772f44
SG
1/* Generic serial interface routines
2 Copyright 1992, 1993 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
6c9638b4 18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
4e772f44
SG
19
20#include "defs.h"
21#include "serial.h"
22
38dc5e12 23/* Linked list of serial I/O handlers */
4e772f44
SG
24
25static struct serial_ops *serial_ops_list = NULL;
26
38dc5e12
SG
27/* This is the last serial stream opened. Used by connect command. */
28
29static serial_t last_serial_opened = NULL;
30
bbcc95bd
PS
31/* Pointer to list of scb's. */
32
33static serial_t scb_base;
34
4e772f44
SG
35static struct serial_ops *
36serial_interface_lookup (name)
37 char *name;
38{
39 struct serial_ops *ops;
40
41 for (ops = serial_ops_list; ops; ops = ops->next)
42 if (strcmp (name, ops->name) == 0)
43 return ops;
44
45 return NULL;
46}
47
48void
49serial_add_interface(optable)
50 struct serial_ops *optable;
51{
52 optable->next = serial_ops_list;
53 serial_ops_list = optable;
54}
55
38dc5e12
SG
56/* Open up a device or a network socket, depending upon the syntax of NAME. */
57
4e772f44 58serial_t
55679787 59serial_open (name)
4e772f44
SG
60 const char *name;
61{
62 serial_t scb;
63 struct serial_ops *ops;
64
4887063b
SG
65 for (scb = scb_base; scb; scb = scb->next)
66 if (scb->name && strcmp (scb->name, name) == 0)
67 {
68 scb->refcnt++;
69 return scb;
70 }
71
55679787
SC
72 if (strcmp (name, "pc") == 0)
73 ops = serial_interface_lookup ("pc");
74 else if (strchr (name, ':'))
38dc5e12
SG
75 ops = serial_interface_lookup ("tcp");
76 else
77 ops = serial_interface_lookup ("hardwire");
4e772f44
SG
78
79 if (!ops)
80 return NULL;
81
82 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
83
84 scb->ops = ops;
85
86 scb->bufcnt = 0;
87 scb->bufp = scb->buf;
88
4febd102 89 if (scb->ops->open(scb, name))
4e772f44
SG
90 {
91 free (scb);
92 return NULL;
93 }
94
4887063b
SG
95 scb->name = strsave (name);
96 scb->next = scb_base;
97 scb->refcnt = 1;
98 scb_base = scb;
99
38dc5e12
SG
100 last_serial_opened = scb;
101
102 return scb;
103}
104
105serial_t
4887063b 106serial_fdopen (fd)
38dc5e12
SG
107 const int fd;
108{
109 serial_t scb;
110 struct serial_ops *ops;
111
4887063b
SG
112 for (scb = scb_base; scb; scb = scb->next)
113 if (scb->fd == fd)
114 {
115 scb->refcnt++;
116 return scb;
117 }
118
38dc5e12
SG
119 ops = serial_interface_lookup ("hardwire");
120
121 if (!ops)
122 return NULL;
123
124 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
125
126 scb->ops = ops;
127
128 scb->bufcnt = 0;
129 scb->bufp = scb->buf;
130
131 scb->fd = fd;
132
4887063b
SG
133 scb->name = NULL;
134 scb->next = scb_base;
135 scb->refcnt = 1;
136 scb_base = scb;
137
38dc5e12
SG
138 last_serial_opened = scb;
139
4e772f44
SG
140 return scb;
141}
142
4febd102 143void
bbcc95bd 144serial_close(scb, really_close)
4febd102 145 serial_t scb;
bbcc95bd 146 int really_close;
4febd102 147{
4887063b
SG
148 serial_t tmp_scb;
149
38dc5e12
SG
150 last_serial_opened = NULL;
151
a037b21e
SG
152/* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you
153 should fix your code instead. */
154
155 if (!scb)
156 return;
157
4887063b
SG
158 scb->refcnt--;
159 if (scb->refcnt > 0)
160 return;
161
bbcc95bd
PS
162 if (really_close)
163 scb->ops->close (scb);
4887063b
SG
164
165 if (scb->name)
166 free (scb->name);
167
168 if (scb_base == scb)
169 scb_base = scb_base->next;
170 else
171 for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
172 {
173 if (tmp_scb->next != scb)
174 continue;
175
176 tmp_scb->next = tmp_scb->next->next;
177 break;
178 }
179
a037b21e 180 free(scb);
4febd102
SG
181}
182
4e772f44 183#if 0
bf3b8abd
JK
184/*
185The connect command is #if 0 because I hadn't thought of an elegant
186way to wait for I/O on two serial_t's simultaneously. Two solutions
187came to mind:
188
189 1) Fork, and have have one fork handle the to user direction,
190 and have the other hand the to target direction. This
191 obviously won't cut it for MSDOS.
192
193 2) Use something like select. This assumes that stdin and
194 the target side can both be waited on via the same
195 mechanism. This may not be true for DOS, if GDB is
196 talking to the target via a TCP socket.
197-grossman, 8 Jun 93
198*/
38dc5e12 199
4e772f44
SG
200/* Connect the user directly to the remote system. This command acts just like
201 the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
202
38dc5e12
SG
203static serial_t tty_desc; /* Controlling terminal */
204
4e772f44
SG
205static void
206cleanup_tty(ttystate)
38dc5e12 207 serial_ttystate ttystate;
4e772f44 208{
199b2450 209 printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
38dc5e12
SG
210 SERIAL_SET_TTY_STATE (tty_desc, ttystate);
211 free (ttystate);
212 SERIAL_CLOSE (tty_desc);
4e772f44
SG
213}
214
215static void
216connect_command (args, fromtty)
217 char *args;
218 int fromtty;
219{
4e772f44
SG
220 int c;
221 char cur_esc = 0;
38dc5e12
SG
222 serial_ttystate ttystate;
223 serial_t port_desc; /* TTY port */
4e772f44
SG
224
225 dont_repeat();
226
4e772f44 227 if (args)
199b2450 228 fprintf_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n");
4e772f44 229
199b2450 230 printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n");
4e772f44 231
38dc5e12
SG
232 tty_desc = SERIAL_FDOPEN (0);
233 port_desc = last_serial_opened;
4e772f44 234
38dc5e12 235 ttystate = SERIAL_GET_TTY_STATE (tty_desc);
4e772f44 236
38dc5e12
SG
237 SERIAL_RAW (tty_desc);
238 SERIAL_RAW (port_desc);
239
240 make_cleanup (cleanup_tty, ttystate);
4e772f44
SG
241
242 while (1)
243 {
38dc5e12 244 int mask;
4e772f44 245
38dc5e12 246 mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
4e772f44 247
38dc5e12
SG
248 if (mask & 2)
249 { /* tty input */
4e772f44
SG
250 char cx;
251
38dc5e12 252 while (1)
4e772f44 253 {
38dc5e12
SG
254 c = SERIAL_READCHAR(tty_desc, 0);
255
256 if (c == SERIAL_TIMEOUT)
257 break;
258
259 if (c < 0)
260 perror_with_name("connect");
261
262 cx = c;
263 SERIAL_WRITE(port_desc, &cx, 1);
264
265 switch (cur_esc)
266 {
267 case 0:
268 if (c == '\r')
269 cur_esc = c;
270 break;
271 case '\r':
272 if (c == '~')
273 cur_esc = c;
274 else
275 cur_esc = 0;
276 break;
277 case '~':
278 if (c == '.' || c == '\004')
279 return;
280 else
281 cur_esc = 0;
282 }
4e772f44
SG
283 }
284 }
285
38dc5e12
SG
286 if (mask & 1)
287 { /* Port input */
288 char cx;
289
4e772f44
SG
290 while (1)
291 {
38dc5e12
SG
292 c = SERIAL_READCHAR(port_desc, 0);
293
294 if (c == SERIAL_TIMEOUT)
295 break;
296
4e772f44 297 if (c < 0)
38dc5e12
SG
298 perror_with_name("connect");
299
300 cx = c;
301
302 SERIAL_WRITE(tty_desc, &cx, 1);
4e772f44 303 }
4e772f44
SG
304 }
305 }
306}
976bb0be 307#endif /* 0 */
4e772f44 308
4e772f44
SG
309void
310_initialize_serial ()
311{
976bb0be 312#if 0
4e772f44
SG
313 add_com ("connect", class_obscure, connect_command,
314 "Connect the terminal directly up to the command monitor.\n\
315Use <CR>~. or <CR>~^D to break out.");
38dc5e12 316#endif /* 0 */
976bb0be 317}
This page took 0.166952 seconds and 4 git commands to generate.