1 /* Serial interface for local (hardwired) serial ports on Windows systems
4 Free Software Foundation, Inc.
6 This file is part of GDB.
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.
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.
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., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
32 #include <sys/types.h>
34 #include "gdb_assert.h"
35 #include "gdb_string.h"
37 void _initialize_ser_windows (void);
39 struct ser_windows_state
47 /* Open up a real live device for serial I/O. */
50 ser_windows_open (struct serial
*scb
, const char *name
)
53 struct ser_windows_state
*state
;
54 COMMTIMEOUTS timeouts
;
56 /* Only allow COM ports. */
57 if (strncmp (name
, "COM", 3) != 0)
63 h
= CreateFile (name
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
,
64 OPEN_EXISTING
, FILE_FLAG_OVERLAPPED
, NULL
);
65 if (h
== INVALID_HANDLE_VALUE
)
71 scb
->fd
= _open_osfhandle ((long) h
, O_RDWR
);
78 if (!SetCommMask (h
, EV_RXCHAR
))
84 timeouts
.ReadIntervalTimeout
= MAXDWORD
;
85 timeouts
.ReadTotalTimeoutConstant
= 0;
86 timeouts
.ReadTotalTimeoutMultiplier
= 0;
87 timeouts
.WriteTotalTimeoutConstant
= 0;
88 timeouts
.WriteTotalTimeoutMultiplier
= 0;
89 if (!SetCommTimeouts (h
, &timeouts
))
95 state
= xmalloc (sizeof (struct ser_windows_state
));
96 memset (state
, 0, sizeof (struct ser_windows_state
));
99 /* Create a manual reset event to watch the input buffer. */
100 state
->ov
.hEvent
= CreateEvent (0, TRUE
, FALSE
, 0);
102 /* Create a (currently unused) handle to record exceptions. */
103 state
->except_event
= CreateEvent (0, TRUE
, FALSE
, 0);
108 /* Wait for the output to drain away, as opposed to flushing (discarding)
112 ser_windows_drain_output (struct serial
*scb
)
114 HANDLE h
= (HANDLE
) _get_osfhandle (scb
->fd
);
116 return (FlushFileBuffers (h
) != 0) ? 0 : -1;
120 ser_windows_flush_output (struct serial
*scb
)
122 HANDLE h
= (HANDLE
) _get_osfhandle (scb
->fd
);
124 return (PurgeComm (h
, PURGE_TXCLEAR
) != 0) ? 0 : -1;
128 ser_windows_flush_input (struct serial
*scb
)
130 HANDLE h
= (HANDLE
) _get_osfhandle (scb
->fd
);
132 return (PurgeComm (h
, PURGE_RXCLEAR
) != 0) ? 0 : -1;
136 ser_windows_send_break (struct serial
*scb
)
138 HANDLE h
= (HANDLE
) _get_osfhandle (scb
->fd
);
140 if (SetCommBreak (h
) == 0)
143 /* Delay for 250 milliseconds. */
146 if (ClearCommBreak (h
))
153 ser_windows_raw (struct serial
*scb
)
155 HANDLE h
= (HANDLE
) _get_osfhandle (scb
->fd
);
158 if (GetCommState (h
, &state
) == 0)
161 state
.fParity
= FALSE
;
162 state
.fOutxCtsFlow
= FALSE
;
163 state
.fOutxDsrFlow
= FALSE
;
164 state
.fDtrControl
= DTR_CONTROL_ENABLE
;
165 state
.fDsrSensitivity
= FALSE
;
169 state
.fAbortOnError
= FALSE
;
171 state
.Parity
= NOPARITY
;
173 scb
->current_timeout
= 0;
175 if (SetCommState (h
, &state
) == 0)
176 warning (_("SetCommState failed\n"));
180 ser_windows_setstopbits (struct serial
*scb
, int num
)
182 HANDLE h
= (HANDLE
) _get_osfhandle (scb
->fd
);
185 if (GetCommState (h
, &state
) == 0)
190 case SERIAL_1_STOPBITS
:
191 state
.StopBits
= ONESTOPBIT
;
193 case SERIAL_1_AND_A_HALF_STOPBITS
:
194 state
.StopBits
= ONE5STOPBITS
;
196 case SERIAL_2_STOPBITS
:
197 state
.StopBits
= TWOSTOPBITS
;
203 return (SetCommState (h
, &state
) != 0) ? 0 : -1;
207 ser_windows_setbaudrate (struct serial
*scb
, int rate
)
209 HANDLE h
= (HANDLE
) _get_osfhandle (scb
->fd
);
212 if (GetCommState (h
, &state
) == 0)
215 state
.BaudRate
= rate
;
217 return (SetCommState (h
, &state
) != 0) ? 0 : -1;
221 ser_windows_close (struct serial
*scb
)
223 struct ser_windows_state
*state
;
225 /* Stop any pending selects. */
226 CancelIo ((HANDLE
) _get_osfhandle (scb
->fd
));
228 CloseHandle (state
->ov
.hEvent
);
229 CloseHandle (state
->except_event
);
241 ser_windows_wait_handle (struct serial
*scb
, HANDLE
*read
, HANDLE
*except
)
243 struct ser_windows_state
*state
;
246 HANDLE h
= (HANDLE
) _get_osfhandle (scb
->fd
);
250 *except
= state
->except_event
;
251 *read
= state
->ov
.hEvent
;
253 if (state
->in_progress
)
256 /* Reset the mask - we are only interested in any characters which
257 arrive after this point, not characters which might have arrived
258 and already been read. */
260 /* This really, really shouldn't be necessary - just the second one.
261 But otherwise an internal flag for EV_RXCHAR does not get
262 cleared, and we get a duplicated event, if the last batch
263 of characters included at least two arriving close together. */
264 if (!SetCommMask (h
, 0))
265 warning (_("ser_windows_wait_handle: reseting mask failed"));
267 if (!SetCommMask (h
, EV_RXCHAR
))
268 warning (_("ser_windows_wait_handle: reseting mask failed (2)"));
270 /* There's a potential race condition here; we must check cbInQue
271 and not wait if that's nonzero. */
273 ClearCommError (h
, &errors
, &status
);
274 if (status
.cbInQue
> 0)
276 SetEvent (state
->ov
.hEvent
);
280 state
->in_progress
= 1;
281 ResetEvent (state
->ov
.hEvent
);
282 state
->lastCommMask
= -2;
283 if (WaitCommEvent (h
, &state
->lastCommMask
, &state
->ov
))
285 gdb_assert (state
->lastCommMask
& EV_RXCHAR
);
286 SetEvent (state
->ov
.hEvent
);
289 gdb_assert (GetLastError () == ERROR_IO_PENDING
);
293 ser_windows_read_prim (struct serial
*scb
, size_t count
)
295 struct ser_windows_state
*state
;
297 DWORD bytes_read
, bytes_read_tmp
;
302 if (state
->in_progress
)
304 WaitForSingleObject (state
->ov
.hEvent
, INFINITE
);
305 state
->in_progress
= 0;
306 ResetEvent (state
->ov
.hEvent
);
309 memset (&ov
, 0, sizeof (OVERLAPPED
));
310 ov
.hEvent
= CreateEvent (0, FALSE
, FALSE
, 0);
311 h
= (HANDLE
) _get_osfhandle (scb
->fd
);
313 if (!ReadFile (h
, scb
->buf
, /* count */ 1, &bytes_read
, &ov
))
315 if (GetLastError () != ERROR_IO_PENDING
316 || !GetOverlappedResult (h
, &ov
, &bytes_read
, TRUE
))
320 CloseHandle (ov
.hEvent
);
325 ser_windows_write_prim (struct serial
*scb
, const void *buf
, size_t len
)
327 struct ser_windows_state
*state
;
332 memset (&ov
, 0, sizeof (OVERLAPPED
));
333 ov
.hEvent
= CreateEvent (0, FALSE
, FALSE
, 0);
334 h
= (HANDLE
) _get_osfhandle (scb
->fd
);
335 if (!WriteFile (h
, buf
, len
, &bytes_written
, &ov
))
337 if (GetLastError () != ERROR_IO_PENDING
338 || !GetOverlappedResult (h
, &ov
, &bytes_written
, TRUE
))
342 CloseHandle (ov
.hEvent
);
343 return bytes_written
;
346 struct ser_console_state
356 console_select_thread (void *arg
)
358 struct serial
*scb
= arg
;
359 struct ser_console_state
*state
, state_copy
;
363 /* Copy useful information out of the control block, to make sure
364 that we do not race with freeing it. */
365 state_copy
= *(struct ser_console_state
*) scb
->state
;
369 h
= (HANDLE
) _get_osfhandle (fd
);
373 HANDLE wait_events
[2];
377 wait_events
[0] = state
->start_select
;
378 wait_events
[1] = state
->stop_select
;
380 if (WaitForMultipleObjects (2, wait_events
, FALSE
, INFINITE
) != WAIT_OBJECT_0
)
382 CloseHandle (state
->stop_select
);
387 wait_events
[0] = state
->stop_select
;
390 event_index
= WaitForMultipleObjects (2, wait_events
, FALSE
, INFINITE
);
392 if (event_index
== WAIT_OBJECT_0
393 || WaitForSingleObject (state
->stop_select
, 0) == WAIT_OBJECT_0
)
395 CloseHandle (state
->stop_select
);
399 if (event_index
!= WAIT_OBJECT_0
+ 1)
401 /* Wait must have failed; assume an error has occured, e.g.
402 the handle has been closed. */
403 SetEvent (state
->except_event
);
407 /* We've got a pending event on the console. See if it's
409 if (!PeekConsoleInput (h
, &record
, 1, &n_records
) || n_records
!= 1)
411 /* Something went wrong. Maybe the console is gone. */
412 SetEvent (state
->except_event
);
416 if (record
.EventType
== KEY_EVENT
&& record
.Event
.KeyEvent
.bKeyDown
)
418 /* This is really a keypress. */
419 SetEvent (state
->read_event
);
423 /* Otherwise discard it and wait again. */
424 ReadConsoleInput (h
, &record
, 1, &n_records
);
432 if (PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, NULL
, NULL
))
439 pipe_select_thread (void *arg
)
441 struct serial
*scb
= arg
;
442 struct ser_console_state
*state
, state_copy
;
446 /* Copy useful information out of the control block, to make sure
447 that we do not race with freeing it. */
448 state_copy
= *(struct ser_console_state
*) scb
->state
;
452 h
= (HANDLE
) _get_osfhandle (fd
);
456 HANDLE wait_events
[2];
459 wait_events
[0] = state
->start_select
;
460 wait_events
[1] = state
->stop_select
;
462 if (WaitForMultipleObjects (2, wait_events
, FALSE
, INFINITE
) != WAIT_OBJECT_0
)
464 CloseHandle (state
->stop_select
);
469 if (!PeekNamedPipe (h
, NULL
, 0, NULL
, &n_avail
, NULL
))
471 SetEvent (state
->except_event
);
477 SetEvent (state
->read_event
);
481 if (WaitForSingleObject (state
->stop_select
, 0) == WAIT_OBJECT_0
)
483 CloseHandle (state
->stop_select
);
493 ser_console_wait_handle (struct serial
*scb
, HANDLE
*read
, HANDLE
*except
)
495 struct ser_console_state
*state
= scb
->state
;
502 is_tty
= isatty (scb
->fd
);
503 if (!is_tty
&& !fd_is_pipe (scb
->fd
))
510 state
= xmalloc (sizeof (struct ser_console_state
));
511 memset (state
, 0, sizeof (struct ser_console_state
));
514 /* Create auto reset events to wake and terminate the select thread. */
515 state
->start_select
= CreateEvent (0, FALSE
, FALSE
, 0);
516 state
->stop_select
= CreateEvent (0, FALSE
, FALSE
, 0);
518 /* Create our own events to report read and exceptions separately.
519 The exception event is currently never used. */
520 state
->read_event
= CreateEvent (0, FALSE
, FALSE
, 0);
521 state
->except_event
= CreateEvent (0, FALSE
, FALSE
, 0);
523 /* And finally start the select thread. */
525 CreateThread (NULL
, 0, console_select_thread
, scb
, 0, &threadId
);
527 CreateThread (NULL
, 0, pipe_select_thread
, scb
, 0, &threadId
);
530 ResetEvent (state
->read_event
);
531 ResetEvent (state
->except_event
);
533 SetEvent (state
->start_select
);
535 *read
= state
->read_event
;
536 *except
= state
->except_event
;
540 ser_console_close (struct serial
*scb
)
542 struct ser_console_state
*state
= scb
->state
;
546 SetEvent (state
->stop_select
);
548 CloseHandle (state
->read_event
);
549 CloseHandle (state
->except_event
);
555 struct ser_console_ttystate
560 static serial_ttystate
561 ser_console_get_tty_state (struct serial
*scb
)
563 if (isatty (scb
->fd
))
565 struct ser_console_ttystate
*state
;
566 state
= (struct ser_console_ttystate
*) xmalloc (sizeof *state
);
574 struct net_windows_state
585 net_windows_select_thread (void *arg
)
587 struct serial
*scb
= arg
;
588 struct net_windows_state
*state
, state_copy
;
591 /* Copy useful information out of the control block, to make sure
592 that we do not race with freeing it. */
593 state_copy
= *(struct net_windows_state
*) scb
->state
;
599 HANDLE wait_events
[2];
600 WSANETWORKEVENTS events
;
602 wait_events
[0] = state
->start_select
;
603 wait_events
[1] = state
->stop_select
;
605 if (WaitForMultipleObjects (2, wait_events
, FALSE
, INFINITE
) != WAIT_OBJECT_0
)
607 CloseHandle (state
->stop_select
);
611 wait_events
[0] = state
->stop_select
;
612 wait_events
[1] = state
->sock_event
;
614 event_index
= WaitForMultipleObjects (2, wait_events
, FALSE
, INFINITE
);
616 if (event_index
== WAIT_OBJECT_0
617 || WaitForSingleObject (state
->stop_select
, 0) == WAIT_OBJECT_0
)
619 CloseHandle (state
->stop_select
);
623 if (event_index
!= WAIT_OBJECT_0
+ 1)
625 /* Some error has occured. Assume that this is an error
627 SetEvent (state
->except_event
);
631 /* Enumerate the internal network events, and reset the object that
632 signalled us to catch the next event. */
633 WSAEnumNetworkEvents (fd
, state
->sock_event
, &events
);
635 if (events
.lNetworkEvents
& FD_READ
)
636 SetEvent (state
->read_event
);
638 if (events
.lNetworkEvents
& FD_CLOSE
)
639 SetEvent (state
->except_event
);
644 net_windows_wait_handle (struct serial
*scb
, HANDLE
*read
, HANDLE
*except
)
646 struct net_windows_state
*state
= scb
->state
;
648 ResetEvent (state
->read_event
);
649 ResetEvent (state
->except_event
);
651 SetEvent (state
->start_select
);
653 *read
= state
->read_event
;
654 *except
= state
->except_event
;
658 net_windows_open (struct serial
*scb
, const char *name
)
660 struct net_windows_state
*state
;
664 ret
= net_open (scb
, name
);
668 state
= xmalloc (sizeof (struct net_windows_state
));
669 memset (state
, 0, sizeof (struct net_windows_state
));
672 /* Create auto reset events to wake and terminate the select thread. */
673 state
->start_select
= CreateEvent (0, FALSE
, FALSE
, 0);
674 state
->stop_select
= CreateEvent (0, FALSE
, FALSE
, 0);
676 /* Associate an event with the socket. */
677 state
->sock_event
= CreateEvent (0, TRUE
, FALSE
, 0);
678 WSAEventSelect (scb
->fd
, state
->sock_event
, FD_READ
| FD_CLOSE
);
680 /* Create our own events to report read and close separately. */
681 state
->read_event
= CreateEvent (0, FALSE
, FALSE
, 0);
682 state
->except_event
= CreateEvent (0, FALSE
, FALSE
, 0);
684 /* And finally start the select thread. */
685 CreateThread (NULL
, 0, net_windows_select_thread
, scb
, 0, &threadId
);
692 net_windows_close (struct serial
*scb
)
694 struct net_windows_state
*state
= scb
->state
;
696 SetEvent (state
->stop_select
);
698 CloseHandle (state
->read_event
);
699 CloseHandle (state
->except_event
);
700 CloseHandle (state
->start_select
);
701 CloseHandle (state
->sock_event
);
709 _initialize_ser_windows (void)
712 struct serial_ops
*ops
;
714 /* First register the serial port driver. */
716 ops
= XMALLOC (struct serial_ops
);
717 memset (ops
, 0, sizeof (struct serial_ops
));
718 ops
->name
= "hardwire";
720 ops
->open
= ser_windows_open
;
721 ops
->close
= ser_windows_close
;
723 ops
->flush_output
= ser_windows_flush_output
;
724 ops
->flush_input
= ser_windows_flush_input
;
725 ops
->send_break
= ser_windows_send_break
;
727 /* These are only used for stdin; we do not need them for serial
728 ports, so supply the standard dummies. */
729 ops
->get_tty_state
= ser_base_get_tty_state
;
730 ops
->set_tty_state
= ser_base_set_tty_state
;
731 ops
->print_tty_state
= ser_base_print_tty_state
;
732 ops
->noflush_set_tty_state
= ser_base_noflush_set_tty_state
;
734 ops
->go_raw
= ser_windows_raw
;
735 ops
->setbaudrate
= ser_windows_setbaudrate
;
736 ops
->setstopbits
= ser_windows_setstopbits
;
737 ops
->drain_output
= ser_windows_drain_output
;
738 ops
->readchar
= ser_base_readchar
;
739 ops
->write
= ser_base_write
;
740 ops
->async
= ser_base_async
;
741 ops
->read_prim
= ser_windows_read_prim
;
742 ops
->write_prim
= ser_windows_write_prim
;
743 ops
->wait_handle
= ser_windows_wait_handle
;
745 serial_add_interface (ops
);
747 /* Next create the dummy serial driver used for terminals. We only
748 provide the TTY-related methods. */
750 ops
= XMALLOC (struct serial_ops
);
751 memset (ops
, 0, sizeof (struct serial_ops
));
753 ops
->name
= "terminal";
756 ops
->close
= ser_console_close
;
757 ops
->get_tty_state
= ser_console_get_tty_state
;
758 ops
->set_tty_state
= ser_base_set_tty_state
;
759 ops
->print_tty_state
= ser_base_print_tty_state
;
760 ops
->noflush_set_tty_state
= ser_base_noflush_set_tty_state
;
761 ops
->drain_output
= ser_base_drain_output
;
762 ops
->wait_handle
= ser_console_wait_handle
;
764 serial_add_interface (ops
);
766 /* If WinSock works, register the TCP/UDP socket driver. */
768 if (WSAStartup (MAKEWORD (1, 0), &wsa_data
) != 0)
769 /* WinSock is unavailable. */
772 ops
= XMALLOC (struct serial_ops
);
773 memset (ops
, 0, sizeof (struct serial_ops
));
776 ops
->open
= net_windows_open
;
777 ops
->close
= net_windows_close
;
778 ops
->readchar
= ser_base_readchar
;
779 ops
->write
= ser_base_write
;
780 ops
->flush_output
= ser_base_flush_output
;
781 ops
->flush_input
= ser_base_flush_input
;
782 ops
->send_break
= ser_base_send_break
;
783 ops
->go_raw
= ser_base_raw
;
784 ops
->get_tty_state
= ser_base_get_tty_state
;
785 ops
->set_tty_state
= ser_base_set_tty_state
;
786 ops
->print_tty_state
= ser_base_print_tty_state
;
787 ops
->noflush_set_tty_state
= ser_base_noflush_set_tty_state
;
788 ops
->setbaudrate
= ser_base_setbaudrate
;
789 ops
->setstopbits
= ser_base_setstopbits
;
790 ops
->drain_output
= ser_base_drain_output
;
791 ops
->async
= ser_base_async
;
792 ops
->read_prim
= net_read_prim
;
793 ops
->write_prim
= net_write_prim
;
794 ops
->wait_handle
= net_windows_wait_handle
;
795 serial_add_interface (ops
);