import gdb-1999-07-05 snapshot
[external/binutils.git] / gdb / ser-unix.c
1 /* Serial interface for local (hardwired) serial ports on Un*x like systems
2    Copyright 1992, 1993, 1994, 1998, 1999 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, Boston, MA 02111-1307, USA.  */
19
20 #include "defs.h"
21 #include "serial.h"
22 #include <fcntl.h>
23 #include <sys/types.h>
24 #include "terminal.h"
25 #ifdef HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28
29 #ifdef HAVE_SYS_SELECT_H
30 #include <sys/select.h>
31 #endif
32
33 #ifdef HAVE_TERMIOS
34
35 struct hardwire_ttystate
36 {
37   struct termios termios;
38 };
39 #endif /* termios */
40
41 #ifdef HAVE_TERMIO
42
43 /* It is believed that all systems which have added job control to SVR3
44    (e.g. sco) have also added termios.  Even if not, trying to figure out
45    all the variations (TIOCGPGRP vs. TCGETPGRP, etc.) would be pretty
46    bewildering.  So we don't attempt it.  */
47
48 struct hardwire_ttystate
49 {
50   struct termio termio;
51 };
52 #endif /* termio */
53
54 #ifdef HAVE_SGTTY
55 /* Needed for the code which uses select().  We would include <sys/select.h>
56    too if it existed on all systems.  */
57 #include <sys/time.h>
58
59 struct hardwire_ttystate
60 {
61   struct sgttyb sgttyb;
62   struct tchars tc;
63   struct ltchars ltc;
64   /* Line discipline flags.  */
65   int lmode;
66 };
67 #endif /* sgtty */
68
69 static int hardwire_open PARAMS ((serial_t scb, const char *name));
70 static void hardwire_raw PARAMS ((serial_t scb));
71 static int wait_for PARAMS ((serial_t scb, int timeout));
72 static int hardwire_readchar PARAMS ((serial_t scb, int timeout));
73 static int rate_to_code PARAMS ((int rate));
74 static int hardwire_setbaudrate PARAMS ((serial_t scb, int rate));
75 static int hardwire_write PARAMS ((serial_t scb, const char *str, int len));
76 static void hardwire_close PARAMS ((serial_t scb));
77 static int get_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
78 static int set_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
79 static serial_ttystate hardwire_get_tty_state PARAMS ((serial_t scb));
80 static int hardwire_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
81 static int hardwire_noflush_set_tty_state PARAMS ((serial_t, serial_ttystate,
82                                                    serial_ttystate));
83 static void hardwire_print_tty_state PARAMS ((serial_t, serial_ttystate));
84 static int hardwire_drain_output PARAMS ((serial_t));
85 static int hardwire_flush_output PARAMS ((serial_t));
86 static int hardwire_flush_input PARAMS ((serial_t));
87 static int hardwire_send_break PARAMS ((serial_t));
88 static int hardwire_setstopbits PARAMS ((serial_t, int));
89
90 void _initialize_ser_hardwire PARAMS ((void));
91
92 extern int (*ui_loop_hook) PARAMS ((int));
93
94 /* Open up a real live device for serial I/O */
95
96 static int
97 hardwire_open(scb, name)
98      serial_t scb;
99      const char *name;
100 {
101   scb->fd = open (name, O_RDWR);
102   if (scb->fd < 0)
103     return -1;
104
105   return 0;
106 }
107
108 static int
109 get_tty_state (scb, state)
110      serial_t scb;
111      struct hardwire_ttystate *state;
112 {
113 #ifdef HAVE_TERMIOS
114   if (tcgetattr(scb->fd, &state->termios) < 0)
115     return -1;
116
117   return 0;
118 #endif
119
120 #ifdef HAVE_TERMIO
121   if (ioctl (scb->fd, TCGETA, &state->termio) < 0)
122     return -1;
123   return 0;
124 #endif
125
126 #ifdef HAVE_SGTTY
127   if (ioctl (scb->fd, TIOCGETP, &state->sgttyb) < 0)
128     return -1;
129   if (ioctl (scb->fd, TIOCGETC, &state->tc) < 0)
130     return -1;
131   if (ioctl (scb->fd, TIOCGLTC, &state->ltc) < 0)
132     return -1;
133   if (ioctl (scb->fd, TIOCLGET, &state->lmode) < 0)
134     return -1;
135
136   return 0;
137 #endif
138 }
139
140 static int
141 set_tty_state(scb, state)
142      serial_t scb;
143      struct hardwire_ttystate *state;
144 {
145 #ifdef HAVE_TERMIOS
146   if (tcsetattr(scb->fd, TCSANOW, &state->termios) < 0)
147     return -1;
148
149   return 0;
150 #endif
151
152 #ifdef HAVE_TERMIO
153   if (ioctl (scb->fd, TCSETA, &state->termio) < 0)
154     return -1;
155   return 0;
156 #endif
157
158 #ifdef HAVE_SGTTY
159   if (ioctl (scb->fd, TIOCSETN, &state->sgttyb) < 0)
160     return -1;
161   if (ioctl (scb->fd, TIOCSETC, &state->tc) < 0)
162     return -1;
163   if (ioctl (scb->fd, TIOCSLTC, &state->ltc) < 0)
164     return -1;
165   if (ioctl (scb->fd, TIOCLSET, &state->lmode) < 0)
166     return -1;
167
168   return 0;
169 #endif
170 }
171
172 static serial_ttystate
173 hardwire_get_tty_state(scb)
174      serial_t scb;
175 {
176   struct hardwire_ttystate *state;
177
178   state = (struct hardwire_ttystate *)xmalloc(sizeof *state);
179
180   if (get_tty_state(scb, state))
181     return NULL;
182
183   return (serial_ttystate)state;
184 }
185
186 static int
187 hardwire_set_tty_state(scb, ttystate)
188      serial_t scb;
189      serial_ttystate ttystate;
190 {
191   struct hardwire_ttystate *state;
192
193   state = (struct hardwire_ttystate *)ttystate;
194
195   return set_tty_state(scb, state);
196 }
197
198 static int
199 hardwire_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
200      serial_t scb;
201      serial_ttystate new_ttystate;
202      serial_ttystate old_ttystate;
203 {
204   struct hardwire_ttystate new_state;
205 #ifdef HAVE_SGTTY
206   struct hardwire_ttystate *state = (struct hardwire_ttystate *) old_ttystate;
207 #endif
208
209   new_state = *(struct hardwire_ttystate *)new_ttystate;
210
211   /* Don't change in or out of raw mode; we don't want to flush input.
212      termio and termios have no such restriction; for them flushing input
213      is separate from setting the attributes.  */
214
215 #ifdef HAVE_SGTTY
216   if (state->sgttyb.sg_flags & RAW)
217     new_state.sgttyb.sg_flags |= RAW;
218   else
219     new_state.sgttyb.sg_flags &= ~RAW;
220
221   /* I'm not sure whether this is necessary; the manpage just mentions
222      RAW not CBREAK.  */
223   if (state->sgttyb.sg_flags & CBREAK)
224     new_state.sgttyb.sg_flags |= CBREAK;
225   else
226     new_state.sgttyb.sg_flags &= ~CBREAK;
227 #endif
228
229   return set_tty_state (scb, &new_state);
230 }
231
232 static void
233 hardwire_print_tty_state (scb, ttystate)
234      serial_t scb;
235      serial_ttystate ttystate;
236 {
237   struct hardwire_ttystate *state = (struct hardwire_ttystate *) ttystate;
238   int i;
239
240 #ifdef HAVE_TERMIOS
241   printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n",
242                    state->termios.c_iflag, state->termios.c_oflag);
243   printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x\n",
244                    state->termios.c_cflag, state->termios.c_lflag);
245 #if 0
246   /* This not in POSIX, and is not really documented by those systems
247      which have it (at least not Sun).  */
248   printf_filtered ("c_line = 0x%x.\n", state->termios.c_line);
249 #endif
250   printf_filtered ("c_cc: ");
251   for (i = 0; i < NCCS; i += 1)
252     printf_filtered ("0x%x ", state->termios.c_cc[i]);
253   printf_filtered ("\n");
254 #endif
255
256 #ifdef HAVE_TERMIO
257   printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n",
258                    state->termio.c_iflag, state->termio.c_oflag);
259   printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
260                    state->termio.c_cflag, state->termio.c_lflag,
261                    state->termio.c_line);
262   printf_filtered ("c_cc: ");
263   for (i = 0; i < NCC; i += 1)
264     printf_filtered ("0x%x ", state->termio.c_cc[i]);
265   printf_filtered ("\n");
266 #endif
267
268 #ifdef HAVE_SGTTY
269   printf_filtered ("sgttyb.sg_flags = 0x%x.\n", state->sgttyb.sg_flags);
270
271   printf_filtered ("tchars: ");
272   for (i = 0; i < (int)sizeof (struct tchars); i++)
273     printf_filtered ("0x%x ", ((unsigned char *)&state->tc)[i]);
274   printf_filtered ("\n");
275
276   printf_filtered ("ltchars: ");
277   for (i = 0; i < (int)sizeof (struct ltchars); i++)
278     printf_filtered ("0x%x ", ((unsigned char *)&state->ltc)[i]);
279   printf_filtered ("\n");
280
281   printf_filtered ("lmode:  0x%x\n", state->lmode);
282 #endif
283 }
284
285 /* Wait for the output to drain away, as opposed to flushing (discarding) it */
286
287 static int
288 hardwire_drain_output (scb)
289      serial_t scb;
290 {
291 #ifdef HAVE_TERMIOS
292   return tcdrain (scb->fd);
293 #endif
294
295 #ifdef HAVE_TERMIO
296   return ioctl (scb->fd, TCSBRK, 1);
297 #endif
298
299 #ifdef HAVE_SGTTY
300   /* Get the current state and then restore it using TIOCSETP,
301      which should cause the output to drain and pending input
302      to be discarded. */
303   {
304     struct hardwire_ttystate state;
305     if (get_tty_state (scb, &state))
306       {
307         return (-1);
308       }
309     else
310       {
311         return (ioctl (scb->fd, TIOCSETP, &state.sgttyb));
312       }
313   }
314 #endif  
315 }
316
317 static int
318 hardwire_flush_output (scb)
319      serial_t scb;
320 {
321 #ifdef HAVE_TERMIOS
322   return tcflush (scb->fd, TCOFLUSH);
323 #endif
324
325 #ifdef HAVE_TERMIO
326   return ioctl (scb->fd, TCFLSH, 1);
327 #endif
328
329 #ifdef HAVE_SGTTY
330   /* This flushes both input and output, but we can't do better.  */
331   return ioctl (scb->fd, TIOCFLUSH, 0);
332 #endif  
333 }
334
335 static int
336 hardwire_flush_input (scb)
337      serial_t scb;
338 {
339   scb->bufcnt = 0;
340   scb->bufp = scb->buf;
341
342 #ifdef HAVE_TERMIOS
343   return tcflush (scb->fd, TCIFLUSH);
344 #endif
345
346 #ifdef HAVE_TERMIO
347   return ioctl (scb->fd, TCFLSH, 0);
348 #endif
349
350 #ifdef HAVE_SGTTY
351   /* This flushes both input and output, but we can't do better.  */
352   return ioctl (scb->fd, TIOCFLUSH, 0);
353 #endif  
354 }
355
356 static int
357 hardwire_send_break (scb)
358      serial_t scb;
359 {
360 #ifdef HAVE_TERMIOS
361   return tcsendbreak (scb->fd, 0);
362 #endif
363
364 #ifdef HAVE_TERMIO
365   return ioctl (scb->fd, TCSBRK, 0);
366 #endif
367
368 #ifdef HAVE_SGTTY
369   {
370     int status;
371     struct timeval timeout;
372
373     status = ioctl (scb->fd, TIOCSBRK, 0);
374
375     /* Can't use usleep; it doesn't exist in BSD 4.2.  */
376     /* Note that if this select() is interrupted by a signal it will not wait
377        the full length of time.  I think that is OK.  */
378     timeout.tv_sec = 0;
379     timeout.tv_usec = 250000;
380     select (0, 0, 0, 0, &timeout);
381     status = ioctl (scb->fd, TIOCCBRK, 0);
382     return status;
383   }
384 #endif  
385 }
386
387 static void
388 hardwire_raw(scb)
389      serial_t scb;
390 {
391   struct hardwire_ttystate state;
392
393   if (get_tty_state(scb, &state))
394     fprintf_unfiltered(gdb_stderr, "get_tty_state failed: %s\n", safe_strerror(errno));
395
396 #ifdef HAVE_TERMIOS
397   state.termios.c_iflag = 0;
398   state.termios.c_oflag = 0;
399   state.termios.c_lflag = 0;
400   state.termios.c_cflag &= ~(CSIZE|PARENB);
401   state.termios.c_cflag |= CLOCAL | CS8;
402   state.termios.c_cc[VMIN] = 0;
403   state.termios.c_cc[VTIME] = 0;
404 #endif
405
406 #ifdef HAVE_TERMIO
407   state.termio.c_iflag = 0;
408   state.termio.c_oflag = 0;
409   state.termio.c_lflag = 0;
410   state.termio.c_cflag &= ~(CSIZE|PARENB);
411   state.termio.c_cflag |= CLOCAL | CS8;
412   state.termio.c_cc[VMIN] = 0;
413   state.termio.c_cc[VTIME] = 0;
414 #endif
415
416 #ifdef HAVE_SGTTY
417   state.sgttyb.sg_flags |= RAW | ANYP;
418   state.sgttyb.sg_flags &= ~(CBREAK | ECHO);
419 #endif
420
421   scb->current_timeout = 0;
422
423   if (set_tty_state (scb, &state))
424     fprintf_unfiltered(gdb_stderr, "set_tty_state failed: %s\n", safe_strerror(errno));
425 }
426
427 /* Wait for input on scb, with timeout seconds.  Returns 0 on success,
428    otherwise SERIAL_TIMEOUT or SERIAL_ERROR.
429
430    For termio{s}, we actually just setup VTIME if necessary, and let the
431    timeout occur in the read() in hardwire_read().
432  */
433
434 static int
435 wait_for(scb, timeout)
436      serial_t scb;
437      int timeout;
438 {
439 #ifdef HAVE_SGTTY
440   {
441     struct timeval tv;
442     fd_set readfds;
443
444     FD_ZERO (&readfds);
445
446     tv.tv_sec = timeout;
447     tv.tv_usec = 0;
448
449     FD_SET(scb->fd, &readfds);
450
451     while (1)
452       {
453         int numfds;
454
455         if (timeout >= 0)
456           numfds = select(scb->fd+1, &readfds, 0, 0, &tv);
457         else
458           numfds = select(scb->fd+1, &readfds, 0, 0, 0);
459
460         if (numfds <= 0)
461           if (numfds == 0)
462             return SERIAL_TIMEOUT;
463           else if (errno == EINTR)
464             continue;
465           else
466             return SERIAL_ERROR;        /* Got an error from select or poll */
467
468         return 0;
469       }
470   }
471 #endif  /* HAVE_SGTTY */
472
473 #if defined HAVE_TERMIO || defined HAVE_TERMIOS
474   if (timeout == scb->current_timeout)
475     return 0;
476
477   scb->current_timeout = timeout;
478
479   {
480     struct hardwire_ttystate state;
481
482     if (get_tty_state(scb, &state))
483       fprintf_unfiltered(gdb_stderr, "get_tty_state failed: %s\n", safe_strerror(errno));
484
485 #ifdef HAVE_TERMIOS
486     if (timeout < 0)
487       {
488         /* No timeout.  */
489         state.termios.c_cc[VTIME] = 0;
490         state.termios.c_cc[VMIN] = 1;
491       }
492     else
493       {
494         state.termios.c_cc[VMIN] = 0;
495         state.termios.c_cc[VTIME] = timeout * 10;
496         if (state.termios.c_cc[VTIME] != timeout * 10)
497           {
498
499             /* If c_cc is an 8-bit signed character, we can't go 
500                bigger than this.  If it is always unsigned, we could use
501                25.  */
502
503             scb->current_timeout = 12;
504             state.termios.c_cc[VTIME] = scb->current_timeout * 10;
505             scb->timeout_remaining = timeout - scb->current_timeout;
506           }
507       }
508 #endif
509
510 #ifdef HAVE_TERMIO
511     if (timeout < 0)
512       {
513         /* No timeout.  */
514         state.termio.c_cc[VTIME] = 0;
515         state.termio.c_cc[VMIN] = 1;
516       }
517     else
518       {
519         state.termio.c_cc[VMIN] = 0;
520         state.termio.c_cc[VTIME] = timeout * 10;
521         if (state.termio.c_cc[VTIME] != timeout * 10)
522           {
523             /* If c_cc is an 8-bit signed character, we can't go 
524                bigger than this.  If it is always unsigned, we could use
525                25.  */
526
527             scb->current_timeout = 12;
528             state.termio.c_cc[VTIME] = scb->current_timeout * 10;
529             scb->timeout_remaining = timeout - scb->current_timeout;
530           }
531       }
532 #endif
533
534     if (set_tty_state (scb, &state))
535       fprintf_unfiltered(gdb_stderr, "set_tty_state failed: %s\n", safe_strerror(errno));
536
537     return 0;
538   }
539 #endif  /* HAVE_TERMIO || HAVE_TERMIOS */
540 }
541
542 /* Read a character with user-specified timeout.  TIMEOUT is number of seconds
543    to wait, or -1 to wait forever.  Use timeout of 0 to effect a poll.  Returns
544    char if successful.  Returns SERIAL_TIMEOUT if timeout expired, EOF if line
545    dropped dead, or SERIAL_ERROR for any other error (see errno in that case).  */
546 static int
547 hardwire_readchar (scb, timeout)
548      serial_t scb;
549      int timeout;
550 {
551   int status, delta;
552   int detach = 0;
553
554   if (scb->bufcnt-- > 0)
555     return *scb->bufp++;
556
557   if (timeout > 0)
558     timeout++;
559
560   /* We have to be able to keep the GUI alive here, so we break the original
561      timeout into steps of 1 second, running the "keep the GUI alive" hook 
562      each time through the loop.
563      Also, timeout = 0 means to poll, so we just set the delta to 0, so we
564      will only go through the loop once. */
565    
566   delta = (timeout == 0 ? 0 : 1);
567   while (1)
568     {
569
570       /* N.B. The UI may destroy our world (for instance by calling
571          remote_stop,) in which case we want to get out of here as
572          quickly as possible.  It is not safe to touch scb, since
573          someone else might have freed it.  The ui_loop_hook signals that 
574          we should exit by returning 1. */
575
576       if (ui_loop_hook)
577         detach = ui_loop_hook (0);
578
579       if (detach)
580         return SERIAL_TIMEOUT;
581
582       scb->timeout_remaining = (timeout < 0 ? timeout : timeout - delta);
583       status = wait_for (scb, delta);
584
585       if (status < 0)
586         return status;
587
588       scb->bufcnt = read (scb->fd, scb->buf, BUFSIZ);
589
590       if (scb->bufcnt <= 0)
591         {
592           if (scb->bufcnt == 0)
593             {
594               /* Zero characters means timeout (it could also be EOF, but
595                  we don't (yet at least) distinguish).  */
596               if (scb->timeout_remaining > 0)
597                 {
598                   timeout = scb->timeout_remaining;
599                   continue;
600                 }
601           else if (scb->timeout_remaining < 0)
602             continue;
603               else
604                 return SERIAL_TIMEOUT;
605             }
606           else if (errno == EINTR)
607             continue;
608           else
609             return SERIAL_ERROR;        /* Got an error from read */
610         }
611
612       scb->bufcnt--;
613       scb->bufp = scb->buf;
614       return *scb->bufp++;
615     }
616 }
617
618 #ifndef B19200
619 #define B19200 EXTA
620 #endif
621
622 #ifndef B38400
623 #define B38400 EXTB
624 #endif
625
626 /* Translate baud rates from integers to damn B_codes.  Unix should
627    have outgrown this crap years ago, but even POSIX wouldn't buck it.  */
628
629 static struct
630 {
631   int rate;
632   int code;
633 }
634 baudtab[] =
635 {
636   {50, B50},
637   {75, B75},
638   {110, B110},
639   {134, B134},
640   {150, B150},
641   {200, B200},
642   {300, B300},
643   {600, B600},
644   {1200, B1200},
645   {1800, B1800},
646   {2400, B2400},
647   {4800, B4800},
648   {9600, B9600},
649   {19200, B19200},
650   {38400, B38400},
651 #ifdef B57600
652   {57600, B57600},
653 #endif
654 #ifdef B115200
655   {115200, B115200},
656 #endif
657 #ifdef B230400
658   {230400, B230400},
659 #endif
660 #ifdef B460800
661   {460800, B460800},
662 #endif
663   {-1, -1},
664 };
665
666 static int 
667 rate_to_code(rate)
668      int rate;
669 {
670   int i;
671
672   for (i = 0; baudtab[i].rate != -1; i++)
673     if (rate == baudtab[i].rate)  
674       return baudtab[i].code;
675
676   return -1;
677 }
678
679 static int
680 hardwire_setbaudrate(scb, rate)
681      serial_t scb;
682      int rate;
683 {
684   struct hardwire_ttystate state;
685
686   if (get_tty_state(scb, &state))
687     return -1;
688
689 #ifdef HAVE_TERMIOS
690   cfsetospeed (&state.termios, rate_to_code (rate));
691   cfsetispeed (&state.termios, rate_to_code (rate));
692 #endif
693
694 #ifdef HAVE_TERMIO
695 #ifndef CIBAUD
696 #define CIBAUD CBAUD
697 #endif
698
699   state.termio.c_cflag &= ~(CBAUD | CIBAUD);
700   state.termio.c_cflag |= rate_to_code (rate);
701 #endif
702
703 #ifdef HAVE_SGTTY
704   state.sgttyb.sg_ispeed = rate_to_code (rate);
705   state.sgttyb.sg_ospeed = rate_to_code (rate);
706 #endif
707
708   return set_tty_state (scb, &state);
709 }
710
711 static int
712 hardwire_setstopbits(scb, num)
713      serial_t scb;
714      int num;
715 {
716   struct hardwire_ttystate state;
717   int newbit;
718
719   if (get_tty_state(scb, &state))
720     return -1;
721
722   switch (num)
723     {
724     case SERIAL_1_STOPBITS:
725       newbit = 0;
726       break;
727     case SERIAL_1_AND_A_HALF_STOPBITS:
728     case SERIAL_2_STOPBITS:
729       newbit = 1;
730       break;
731     default:
732       return 1;
733     }
734
735 #ifdef HAVE_TERMIOS
736   if (!newbit)
737     state.termios.c_cflag &= ~CSTOPB;
738   else
739     state.termios.c_cflag |= CSTOPB; /* two bits */
740 #endif
741
742 #ifdef HAVE_TERMIO
743   if (!newbit)
744     state.termio.c_cflag &= ~CSTOPB;
745   else
746     state.termio.c_cflag |= CSTOPB; /* two bits */
747 #endif
748
749 #ifdef HAVE_SGTTY
750   return 0;                     /* sgtty doesn't support this */
751 #endif
752
753   return set_tty_state (scb, &state);
754 }
755
756 static int
757 hardwire_write(scb, str, len)
758      serial_t scb;
759      const char *str;
760      int len;
761 {
762   int cc;
763
764   while (len > 0)
765     {
766       cc = write(scb->fd, str, len);
767
768       if (cc < 0)
769         return 1;
770       len -= cc;
771       str += cc;
772     }
773   return 0;
774 }
775
776 static void
777 hardwire_close(scb)
778      serial_t scb;
779 {
780   if (scb->fd < 0)
781     return;
782
783   close(scb->fd);
784   scb->fd = -1;
785 }
786
787 static struct serial_ops hardwire_ops =
788 {
789   "hardwire",
790   0,
791   hardwire_open,
792   hardwire_close,
793   hardwire_readchar,
794   hardwire_write,
795   hardwire_flush_output,
796   hardwire_flush_input,
797   hardwire_send_break,
798   hardwire_raw,
799   hardwire_get_tty_state,
800   hardwire_set_tty_state,
801   hardwire_print_tty_state,
802   hardwire_noflush_set_tty_state,
803   hardwire_setbaudrate,
804   hardwire_setstopbits,
805   hardwire_drain_output,        /* wait for output to drain */
806 };
807
808 void
809 _initialize_ser_hardwire ()
810 {
811   serial_add_interface (&hardwire_ops);
812 }