Move 2006 ChangeLog entries to ChangeLog-2006.
[deliverable/binutils-gdb.git] / gdb / ser-mingw.c
CommitLineData
0ea3f30e
DJ
1/* Serial interface for local (hardwired) serial ports on Windows systems
2
3 Copyright (C) 2006
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., 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
22
23#include "defs.h"
24#include "serial.h"
25#include "ser-base.h"
26#include "ser-tcp.h"
27
28#include <windows.h>
c3e2b812 29#include <conio.h>
0ea3f30e
DJ
30
31#include <fcntl.h>
32#include <unistd.h>
33#include <sys/types.h>
34
35#include "gdb_assert.h"
36#include "gdb_string.h"
37
38void _initialize_ser_windows (void);
39
40struct ser_windows_state
41{
42 int in_progress;
43 OVERLAPPED ov;
44 DWORD lastCommMask;
45 HANDLE except_event;
46};
47
48/* Open up a real live device for serial I/O. */
49
50static int
51ser_windows_open (struct serial *scb, const char *name)
52{
53 HANDLE h;
54 struct ser_windows_state *state;
55 COMMTIMEOUTS timeouts;
56
57 /* Only allow COM ports. */
58 if (strncmp (name, "COM", 3) != 0)
59 {
60 errno = ENOENT;
61 return -1;
62 }
63
64 h = CreateFile (name, GENERIC_READ | GENERIC_WRITE, 0, NULL,
65 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
66 if (h == INVALID_HANDLE_VALUE)
67 {
68 errno = ENOENT;
69 return -1;
70 }
71
72 scb->fd = _open_osfhandle ((long) h, O_RDWR);
73 if (scb->fd < 0)
74 {
75 errno = ENOENT;
76 return -1;
77 }
78
79 if (!SetCommMask (h, EV_RXCHAR))
80 {
81 errno = EINVAL;
82 return -1;
83 }
84
85 timeouts.ReadIntervalTimeout = MAXDWORD;
86 timeouts.ReadTotalTimeoutConstant = 0;
87 timeouts.ReadTotalTimeoutMultiplier = 0;
88 timeouts.WriteTotalTimeoutConstant = 0;
89 timeouts.WriteTotalTimeoutMultiplier = 0;
90 if (!SetCommTimeouts (h, &timeouts))
91 {
92 errno = EINVAL;
93 return -1;
94 }
95
96 state = xmalloc (sizeof (struct ser_windows_state));
97 memset (state, 0, sizeof (struct ser_windows_state));
98 scb->state = state;
99
100 /* Create a manual reset event to watch the input buffer. */
101 state->ov.hEvent = CreateEvent (0, TRUE, FALSE, 0);
102
103 /* Create a (currently unused) handle to record exceptions. */
104 state->except_event = CreateEvent (0, TRUE, FALSE, 0);
105
106 return 0;
107}
108
109/* Wait for the output to drain away, as opposed to flushing (discarding)
110 it. */
111
112static int
113ser_windows_drain_output (struct serial *scb)
114{
115 HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
116
117 return (FlushFileBuffers (h) != 0) ? 0 : -1;
118}
119
120static int
121ser_windows_flush_output (struct serial *scb)
122{
123 HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
124
125 return (PurgeComm (h, PURGE_TXCLEAR) != 0) ? 0 : -1;
126}
127
128static int
129ser_windows_flush_input (struct serial *scb)
130{
131 HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
132
133 return (PurgeComm (h, PURGE_RXCLEAR) != 0) ? 0 : -1;
134}
135
136static int
137ser_windows_send_break (struct serial *scb)
138{
139 HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
140
141 if (SetCommBreak (h) == 0)
142 return -1;
143
144 /* Delay for 250 milliseconds. */
145 Sleep (250);
146
147 if (ClearCommBreak (h))
148 return -1;
149
150 return 0;
151}
152
153static void
154ser_windows_raw (struct serial *scb)
155{
156 HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
157 DCB state;
158
159 if (GetCommState (h, &state) == 0)
160 return;
161
162 state.fParity = FALSE;
163 state.fOutxCtsFlow = FALSE;
164 state.fOutxDsrFlow = FALSE;
165 state.fDtrControl = DTR_CONTROL_ENABLE;
166 state.fDsrSensitivity = FALSE;
167 state.fOutX = FALSE;
168 state.fInX = FALSE;
169 state.fNull = FALSE;
170 state.fAbortOnError = FALSE;
171 state.ByteSize = 8;
172 state.Parity = NOPARITY;
173
174 scb->current_timeout = 0;
175
176 if (SetCommState (h, &state) == 0)
177 warning (_("SetCommState failed\n"));
178}
179
180static int
181ser_windows_setstopbits (struct serial *scb, int num)
182{
183 HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
184 DCB state;
185
186 if (GetCommState (h, &state) == 0)
187 return -1;
188
189 switch (num)
190 {
191 case SERIAL_1_STOPBITS:
192 state.StopBits = ONESTOPBIT;
193 break;
194 case SERIAL_1_AND_A_HALF_STOPBITS:
195 state.StopBits = ONE5STOPBITS;
196 break;
197 case SERIAL_2_STOPBITS:
198 state.StopBits = TWOSTOPBITS;
199 break;
200 default:
201 return 1;
202 }
203
204 return (SetCommState (h, &state) != 0) ? 0 : -1;
205}
206
207static int
208ser_windows_setbaudrate (struct serial *scb, int rate)
209{
210 HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
211 DCB state;
212
213 if (GetCommState (h, &state) == 0)
214 return -1;
215
216 state.BaudRate = rate;
217
218 return (SetCommState (h, &state) != 0) ? 0 : -1;
219}
220
221static void
222ser_windows_close (struct serial *scb)
223{
224 struct ser_windows_state *state;
225
226 /* Stop any pending selects. */
227 CancelIo ((HANDLE) _get_osfhandle (scb->fd));
228 state = scb->state;
229 CloseHandle (state->ov.hEvent);
230 CloseHandle (state->except_event);
231
232 if (scb->fd < 0)
233 return;
234
235 close (scb->fd);
236 scb->fd = -1;
237
238 xfree (scb->state);
239}
240
241static void
242ser_windows_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
243{
244 struct ser_windows_state *state;
245 COMSTAT status;
246 DWORD errors;
247 HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
248
249 state = scb->state;
250
251 *except = state->except_event;
252 *read = state->ov.hEvent;
253
254 if (state->in_progress)
255 return;
256
257 /* Reset the mask - we are only interested in any characters which
258 arrive after this point, not characters which might have arrived
259 and already been read. */
260
261 /* This really, really shouldn't be necessary - just the second one.
262 But otherwise an internal flag for EV_RXCHAR does not get
263 cleared, and we get a duplicated event, if the last batch
264 of characters included at least two arriving close together. */
265 if (!SetCommMask (h, 0))
266 warning (_("ser_windows_wait_handle: reseting mask failed"));
267
268 if (!SetCommMask (h, EV_RXCHAR))
269 warning (_("ser_windows_wait_handle: reseting mask failed (2)"));
270
271 /* There's a potential race condition here; we must check cbInQue
272 and not wait if that's nonzero. */
273
274 ClearCommError (h, &errors, &status);
275 if (status.cbInQue > 0)
276 {
277 SetEvent (state->ov.hEvent);
278 return;
279 }
280
281 state->in_progress = 1;
282 ResetEvent (state->ov.hEvent);
283 state->lastCommMask = -2;
284 if (WaitCommEvent (h, &state->lastCommMask, &state->ov))
285 {
286 gdb_assert (state->lastCommMask & EV_RXCHAR);
287 SetEvent (state->ov.hEvent);
288 }
289 else
290 gdb_assert (GetLastError () == ERROR_IO_PENDING);
291}
292
293static int
294ser_windows_read_prim (struct serial *scb, size_t count)
295{
296 struct ser_windows_state *state;
297 OVERLAPPED ov;
298 DWORD bytes_read, bytes_read_tmp;
299 HANDLE h;
300 gdb_byte *p;
301
302 state = scb->state;
303 if (state->in_progress)
304 {
305 WaitForSingleObject (state->ov.hEvent, INFINITE);
306 state->in_progress = 0;
307 ResetEvent (state->ov.hEvent);
308 }
309
310 memset (&ov, 0, sizeof (OVERLAPPED));
311 ov.hEvent = CreateEvent (0, FALSE, FALSE, 0);
312 h = (HANDLE) _get_osfhandle (scb->fd);
313
314 if (!ReadFile (h, scb->buf, /* count */ 1, &bytes_read, &ov))
315 {
316 if (GetLastError () != ERROR_IO_PENDING
317 || !GetOverlappedResult (h, &ov, &bytes_read, TRUE))
318 bytes_read = -1;
319 }
320
321 CloseHandle (ov.hEvent);
322 return bytes_read;
323}
324
325static int
326ser_windows_write_prim (struct serial *scb, const void *buf, size_t len)
327{
328 struct ser_windows_state *state;
329 OVERLAPPED ov;
330 DWORD bytes_written;
331 HANDLE h;
332
333 memset (&ov, 0, sizeof (OVERLAPPED));
334 ov.hEvent = CreateEvent (0, FALSE, FALSE, 0);
335 h = (HANDLE) _get_osfhandle (scb->fd);
336 if (!WriteFile (h, buf, len, &bytes_written, &ov))
337 {
338 if (GetLastError () != ERROR_IO_PENDING
339 || !GetOverlappedResult (h, &ov, &bytes_written, TRUE))
340 bytes_written = -1;
341 }
342
343 CloseHandle (ov.hEvent);
344 return bytes_written;
345}
346
347struct ser_console_state
348{
349 HANDLE read_event;
350 HANDLE except_event;
351
352 HANDLE start_select;
353 HANDLE stop_select;
c3e2b812
DJ
354 HANDLE exit_select;
355 HANDLE have_stopped;
356
357 HANDLE thread;
0ea3f30e
DJ
358};
359
360static DWORD WINAPI
361console_select_thread (void *arg)
362{
363 struct serial *scb = arg;
c3e2b812
DJ
364 struct ser_console_state *state;
365 int event_index;
0ea3f30e
DJ
366 HANDLE h;
367
c3e2b812
DJ
368 state = scb->state;
369 h = (HANDLE) _get_osfhandle (scb->fd);
0ea3f30e
DJ
370
371 while (1)
372 {
373 HANDLE wait_events[2];
374 INPUT_RECORD record;
375 DWORD n_records;
376
c3e2b812
DJ
377 SetEvent (state->have_stopped);
378
0ea3f30e 379 wait_events[0] = state->start_select;
c3e2b812 380 wait_events[1] = state->exit_select;
0ea3f30e
DJ
381
382 if (WaitForMultipleObjects (2, wait_events, FALSE, INFINITE) != WAIT_OBJECT_0)
c3e2b812
DJ
383 return 0;
384
385 ResetEvent (state->have_stopped);
0ea3f30e
DJ
386
387 retry:
388 wait_events[0] = state->stop_select;
389 wait_events[1] = h;
390
391 event_index = WaitForMultipleObjects (2, wait_events, FALSE, INFINITE);
392
393 if (event_index == WAIT_OBJECT_0
394 || WaitForSingleObject (state->stop_select, 0) == WAIT_OBJECT_0)
c3e2b812 395 continue;
0ea3f30e
DJ
396
397 if (event_index != WAIT_OBJECT_0 + 1)
398 {
399 /* Wait must have failed; assume an error has occured, e.g.
400 the handle has been closed. */
401 SetEvent (state->except_event);
402 continue;
403 }
404
405 /* We've got a pending event on the console. See if it's
406 of interest. */
407 if (!PeekConsoleInput (h, &record, 1, &n_records) || n_records != 1)
408 {
409 /* Something went wrong. Maybe the console is gone. */
410 SetEvent (state->except_event);
411 continue;
412 }
413
414 if (record.EventType == KEY_EVENT && record.Event.KeyEvent.bKeyDown)
415 {
c3e2b812
DJ
416 WORD keycode = record.Event.KeyEvent.wVirtualKeyCode;
417
418 /* Ignore events containing only control keys. We must
419 recognize "enhanced" keys which we are interested in
420 reading via getch, if they do not map to ASCII. But we
421 do not want to report input available for e.g. the
422 control key alone. */
423
424 if (record.Event.KeyEvent.uChar.AsciiChar != 0
425 || keycode == VK_PRIOR
426 || keycode == VK_NEXT
427 || keycode == VK_END
428 || keycode == VK_HOME
429 || keycode == VK_LEFT
430 || keycode == VK_UP
431 || keycode == VK_RIGHT
432 || keycode == VK_DOWN
433 || keycode == VK_INSERT
434 || keycode == VK_DELETE)
435 {
436 /* This is really a keypress. */
437 SetEvent (state->read_event);
438 continue;
439 }
0ea3f30e
DJ
440 }
441
442 /* Otherwise discard it and wait again. */
443 ReadConsoleInput (h, &record, 1, &n_records);
444 goto retry;
445 }
446}
447
448static int
449fd_is_pipe (int fd)
450{
451 if (PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, NULL, NULL))
452 return 1;
453 else
454 return 0;
455}
456
457static DWORD WINAPI
458pipe_select_thread (void *arg)
459{
460 struct serial *scb = arg;
c3e2b812
DJ
461 struct ser_console_state *state;
462 int event_index;
0ea3f30e
DJ
463 HANDLE h;
464
c3e2b812
DJ
465 state = scb->state;
466 h = (HANDLE) _get_osfhandle (scb->fd);
0ea3f30e
DJ
467
468 while (1)
469 {
470 HANDLE wait_events[2];
471 DWORD n_avail;
472
c3e2b812
DJ
473 SetEvent (state->have_stopped);
474
0ea3f30e 475 wait_events[0] = state->start_select;
c3e2b812 476 wait_events[1] = state->exit_select;
0ea3f30e
DJ
477
478 if (WaitForMultipleObjects (2, wait_events, FALSE, INFINITE) != WAIT_OBJECT_0)
c3e2b812
DJ
479 return 0;
480
481 ResetEvent (state->have_stopped);
0ea3f30e
DJ
482
483 retry:
484 if (!PeekNamedPipe (h, NULL, 0, NULL, &n_avail, NULL))
485 {
486 SetEvent (state->except_event);
487 continue;
488 }
489
490 if (n_avail > 0)
491 {
492 SetEvent (state->read_event);
493 continue;
494 }
495
c3e2b812
DJ
496 /* Delay 10ms before checking again, but allow the stop event
497 to wake us. */
498 if (WaitForSingleObject (state->stop_select, 10) == WAIT_OBJECT_0)
499 continue;
0ea3f30e 500
0ea3f30e
DJ
501 goto retry;
502 }
503}
504
505static void
506ser_console_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
507{
508 struct ser_console_state *state = scb->state;
509
510 if (state == NULL)
511 {
512 DWORD threadId;
513 int is_tty;
514
515 is_tty = isatty (scb->fd);
516 if (!is_tty && !fd_is_pipe (scb->fd))
517 {
518 *read = NULL;
519 *except = NULL;
520 return;
521 }
522
523 state = xmalloc (sizeof (struct ser_console_state));
524 memset (state, 0, sizeof (struct ser_console_state));
525 scb->state = state;
526
c3e2b812
DJ
527 /* Create auto reset events to wake, stop, and exit the select
528 thread. */
0ea3f30e
DJ
529 state->start_select = CreateEvent (0, FALSE, FALSE, 0);
530 state->stop_select = CreateEvent (0, FALSE, FALSE, 0);
c3e2b812 531 state->exit_select = CreateEvent (0, FALSE, FALSE, 0);
0ea3f30e 532
c3e2b812
DJ
533 /* Create a manual reset event to signal whether the thread is
534 stopped. This must be manual reset, because we may wait on
535 it multiple times without ever starting the thread. */
536 state->have_stopped = CreateEvent (0, TRUE, FALSE, 0);
537
538 /* Create our own events to report read and exceptions separately. */
0ea3f30e
DJ
539 state->read_event = CreateEvent (0, FALSE, FALSE, 0);
540 state->except_event = CreateEvent (0, FALSE, FALSE, 0);
541
0ea3f30e 542 if (is_tty)
c3e2b812
DJ
543 state->thread = CreateThread (NULL, 0, console_select_thread, scb, 0,
544 &threadId);
0ea3f30e 545 else
c3e2b812
DJ
546 state->thread = CreateThread (NULL, 0, pipe_select_thread, scb, 0,
547 &threadId);
0ea3f30e
DJ
548 }
549
c3e2b812
DJ
550 *read = state->read_event;
551 *except = state->except_event;
552
553 /* Start from a blank state. */
0ea3f30e
DJ
554 ResetEvent (state->read_event);
555 ResetEvent (state->except_event);
c3e2b812
DJ
556 ResetEvent (state->stop_select);
557
558 /* First check for a key already in the buffer. If there is one,
559 we don't need a thread. This also catches the second key of
560 multi-character returns from getch, for instance for arrow
561 keys. The second half is in a C library internal buffer,
562 and PeekConsoleInput will not find it. */
563 if (_kbhit ())
564 {
565 SetEvent (state->read_event);
566 return;
567 }
0ea3f30e 568
c3e2b812 569 /* Otherwise, start the select thread. */
0ea3f30e 570 SetEvent (state->start_select);
c3e2b812 571}
0ea3f30e 572
c3e2b812
DJ
573static void
574ser_console_done_wait_handle (struct serial *scb)
575{
576 struct ser_console_state *state = scb->state;
577
578 if (state == NULL)
579 return;
580
581 SetEvent (state->stop_select);
582 WaitForSingleObject (state->have_stopped, INFINITE);
0ea3f30e
DJ
583}
584
585static void
586ser_console_close (struct serial *scb)
587{
588 struct ser_console_state *state = scb->state;
589
590 if (scb->state)
591 {
c3e2b812
DJ
592 SetEvent (state->exit_select);
593
594 WaitForSingleObject (state->thread, INFINITE);
595
596 CloseHandle (state->start_select);
597 CloseHandle (state->stop_select);
598 CloseHandle (state->exit_select);
599 CloseHandle (state->have_stopped);
0ea3f30e
DJ
600
601 CloseHandle (state->read_event);
602 CloseHandle (state->except_event);
603
604 xfree (scb->state);
605 }
606}
607
608struct ser_console_ttystate
609{
610 int is_a_tty;
611};
612
613static serial_ttystate
614ser_console_get_tty_state (struct serial *scb)
615{
616 if (isatty (scb->fd))
617 {
618 struct ser_console_ttystate *state;
619 state = (struct ser_console_ttystate *) xmalloc (sizeof *state);
620 state->is_a_tty = 1;
621 return state;
622 }
623 else
624 return NULL;
625}
626
5f1fb6dc
JB
627struct pipe_state
628{
629 /* Since we use the pipe_select_thread for our select emulation,
630 we need to place the state structure it requires at the front
631 of our state. */
632 struct ser_console_state wait;
633
634 /* The pex obj for our (one-stage) pipeline. */
635 struct pex_obj *pex;
636
637 /* Streams for the pipeline's input and output. */
638 FILE *input, *output;
639};
640
641static struct pipe_state *
642make_pipe_state (void)
643{
644 struct pipe_state *ps = XMALLOC (struct pipe_state);
645
646 memset (ps, 0, sizeof (*ps));
647 ps->wait.read_event = INVALID_HANDLE_VALUE;
648 ps->wait.except_event = INVALID_HANDLE_VALUE;
649 ps->wait.start_select = INVALID_HANDLE_VALUE;
650 ps->wait.stop_select = INVALID_HANDLE_VALUE;
651
652 return ps;
653}
654
655static void
656free_pipe_state (struct pipe_state *ps)
657{
658 int saved_errno = errno;
659
660 if (ps->wait.read_event != INVALID_HANDLE_VALUE)
774a49c0
DJ
661 {
662 SetEvent (ps->wait.exit_select);
663
664 WaitForSingleObject (ps->wait.thread, INFINITE);
5f1fb6dc 665
774a49c0
DJ
666 CloseHandle (ps->wait.start_select);
667 CloseHandle (ps->wait.stop_select);
668 CloseHandle (ps->wait.exit_select);
669 CloseHandle (ps->wait.have_stopped);
670
671 CloseHandle (ps->wait.read_event);
672 CloseHandle (ps->wait.except_event);
673 }
5f1fb6dc
JB
674
675 /* Close the pipe to the child. We must close the pipe before
676 calling pex_free because pex_free will wait for the child to exit
677 and the child will not exit until the pipe is closed. */
678 if (ps->input)
679 fclose (ps->input);
680 if (ps->pex)
681 pex_free (ps->pex);
682 /* pex_free closes ps->output. */
683
684 xfree (ps);
685
686 errno = saved_errno;
687}
688
689static void
690cleanup_pipe_state (void *untyped)
691{
692 struct pipe_state *ps = untyped;
693
694 free_pipe_state (ps);
695}
696
697static int
698pipe_windows_open (struct serial *scb, const char *name)
699{
700 char **argv = buildargv (name);
701 struct cleanup *back_to = make_cleanup_freeargv (argv);
702 if (! argv[0] || argv[0][0] == '\0')
703 error ("missing child command");
704
705 struct pipe_state *ps = make_pipe_state ();
706 make_cleanup (cleanup_pipe_state, ps);
707
708 ps->pex = pex_init (PEX_USE_PIPES, "target remote pipe", NULL);
709 if (! ps->pex)
710 goto fail;
711 ps->input = pex_input_pipe (ps->pex, 1);
712 if (! ps->input)
713 goto fail;
714
715 {
716 int err;
717 const char *err_msg
718 = pex_run (ps->pex, PEX_SEARCH | PEX_BINARY_INPUT | PEX_BINARY_OUTPUT,
719 argv[0], argv, NULL, NULL,
720 &err);
721
722 if (err_msg)
723 {
724 /* Our caller expects us to return -1, but all they'll do with
725 it generally is print the message based on errno. We have
726 all the same information here, plus err_msg provided by
727 pex_run, so we just raise the error here. */
728 if (err)
729 error ("error starting child process '%s': %s: %s",
730 name, err_msg, safe_strerror (err));
731 else
732 error ("error starting child process '%s': %s",
733 name, err_msg);
734 }
735 }
736
737 ps->output = pex_read_output (ps->pex, 1);
738 if (! ps->output)
739 goto fail;
740
741 scb->fd = fileno (ps->output);
742 scb->state = (void *) ps;
743
744 discard_cleanups (back_to);
745 return 0;
746
747 fail:
748 do_cleanups (back_to);
749 return -1;
750}
751
752
753static void
754pipe_windows_close (struct serial *scb)
755{
756 struct pipe_state *ps = scb->state;
757
758 /* In theory, we should try to kill the subprocess here, but the pex
759 interface doesn't give us enough information to do that. Usually
760 closing the input pipe will get the message across. */
761
762 free_pipe_state (ps);
763}
764
765
766static int
767pipe_windows_read (struct serial *scb, size_t count)
768{
769 HANDLE pipeline_out = (HANDLE) _get_osfhandle (scb->fd);
770 if (pipeline_out == INVALID_HANDLE_VALUE)
771 return -1;
772
773 DWORD available;
774 if (! PeekNamedPipe (pipeline_out, NULL, 0, NULL, &available, NULL))
775 return -1;
776
777 if (count > available)
778 count = available;
779
780 DWORD bytes_read;
781 if (! ReadFile (pipeline_out, scb->buf, count, &bytes_read, NULL))
782 return -1;
783
784 return bytes_read;
785}
786
787
788static int
789pipe_windows_write (struct serial *scb, const void *buf, size_t count)
790{
791 struct pipe_state *ps = scb->state;
792 int pipeline_in_fd = fileno (ps->input);
793 if (pipeline_in_fd < 0)
794 return -1;
795
796 HANDLE pipeline_in = (HANDLE) _get_osfhandle (pipeline_in_fd);
797 if (pipeline_in == INVALID_HANDLE_VALUE)
798 return -1;
799
800 DWORD written;
801 if (! WriteFile (pipeline_in, buf, count, &written, NULL))
802 return -1;
803
804 return written;
805}
806
807
808static void
809pipe_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
810{
811 struct pipe_state *ps = scb->state;
812
813 /* Have we allocated our events yet? */
814 if (ps->wait.read_event == INVALID_HANDLE_VALUE)
815 {
816 DWORD threadId;
817
774a49c0
DJ
818 /* Create auto reset events to wake, stop, and exit the select
819 thread. */
5f1fb6dc
JB
820 ps->wait.start_select = CreateEvent (0, FALSE, FALSE, 0);
821 ps->wait.stop_select = CreateEvent (0, FALSE, FALSE, 0);
774a49c0
DJ
822 ps->wait.exit_select = CreateEvent (0, FALSE, FALSE, 0);
823
824 /* Create a manual reset event to signal whether the thread is
825 stopped. This must be manual reset, because we may wait on
826 it multiple times without ever starting the thread. */
827 ps->wait.have_stopped = CreateEvent (0, TRUE, FALSE, 0);
5f1fb6dc
JB
828
829 /* Create our own events to report read and exceptions separately.
830 The exception event is currently never used. */
831 ps->wait.read_event = CreateEvent (0, FALSE, FALSE, 0);
832 ps->wait.except_event = CreateEvent (0, FALSE, FALSE, 0);
833
834 /* Start the select thread. */
835 CreateThread (NULL, 0, pipe_select_thread, scb, 0, &threadId);
836 }
837
774a49c0
DJ
838 *read = ps->wait.read_event;
839 *except = ps->wait.except_event;
840
841 /* Start from a blank state. */
5f1fb6dc
JB
842 ResetEvent (ps->wait.read_event);
843 ResetEvent (ps->wait.except_event);
774a49c0 844 ResetEvent (ps->wait.stop_select);
5f1fb6dc 845
774a49c0 846 /* Start the select thread. */
5f1fb6dc 847 SetEvent (ps->wait.start_select);
5f1fb6dc
JB
848}
849
774a49c0
DJ
850static void
851pipe_done_wait_handle (struct serial *scb)
852{
853 struct pipe_state *ps = scb->state;
854
855 /* Have we allocated our events yet? */
856 if (ps->wait.read_event == INVALID_HANDLE_VALUE)
857 return;
858
859 SetEvent (ps->wait.stop_select);
860 WaitForSingleObject (ps->wait.have_stopped, INFINITE);
861}
5f1fb6dc 862
0ea3f30e
DJ
863struct net_windows_state
864{
865 HANDLE read_event;
866 HANDLE except_event;
867
868 HANDLE start_select;
869 HANDLE stop_select;
c3e2b812
DJ
870 HANDLE exit_select;
871 HANDLE have_stopped;
872
0ea3f30e 873 HANDLE sock_event;
c3e2b812
DJ
874
875 HANDLE thread;
0ea3f30e
DJ
876};
877
878static DWORD WINAPI
879net_windows_select_thread (void *arg)
880{
881 struct serial *scb = arg;
882 struct net_windows_state *state, state_copy;
c3e2b812 883 int event_index;
0ea3f30e 884
c3e2b812 885 state = scb->state;
0ea3f30e
DJ
886
887 while (1)
888 {
889 HANDLE wait_events[2];
890 WSANETWORKEVENTS events;
891
c3e2b812
DJ
892 SetEvent (state->have_stopped);
893
0ea3f30e 894 wait_events[0] = state->start_select;
c3e2b812 895 wait_events[1] = state->exit_select;
0ea3f30e
DJ
896
897 if (WaitForMultipleObjects (2, wait_events, FALSE, INFINITE) != WAIT_OBJECT_0)
c3e2b812
DJ
898 return 0;
899
900 ResetEvent (state->have_stopped);
0ea3f30e
DJ
901
902 wait_events[0] = state->stop_select;
903 wait_events[1] = state->sock_event;
904
905 event_index = WaitForMultipleObjects (2, wait_events, FALSE, INFINITE);
906
907 if (event_index == WAIT_OBJECT_0
908 || WaitForSingleObject (state->stop_select, 0) == WAIT_OBJECT_0)
c3e2b812 909 continue;
0ea3f30e
DJ
910
911 if (event_index != WAIT_OBJECT_0 + 1)
912 {
913 /* Some error has occured. Assume that this is an error
914 condition. */
915 SetEvent (state->except_event);
916 continue;
917 }
918
919 /* Enumerate the internal network events, and reset the object that
920 signalled us to catch the next event. */
c3e2b812
DJ
921 WSAEnumNetworkEvents (scb->fd, state->sock_event, &events);
922
923 gdb_assert (events.lNetworkEvents & (FD_READ | FD_CLOSE));
0ea3f30e
DJ
924
925 if (events.lNetworkEvents & FD_READ)
926 SetEvent (state->read_event);
927
928 if (events.lNetworkEvents & FD_CLOSE)
929 SetEvent (state->except_event);
930 }
931}
932
933static void
934net_windows_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
935{
936 struct net_windows_state *state = scb->state;
937
c3e2b812 938 /* Start from a clean slate. */
0ea3f30e
DJ
939 ResetEvent (state->read_event);
940 ResetEvent (state->except_event);
c3e2b812 941 ResetEvent (state->stop_select);
0ea3f30e
DJ
942
943 *read = state->read_event;
944 *except = state->except_event;
c3e2b812
DJ
945
946 /* Check any pending events. This both avoids starting the thread
947 unnecessarily, and handles stray FD_READ events (see below). */
948 if (WaitForSingleObject (state->sock_event, 0) == WAIT_OBJECT_0)
949 {
950 WSANETWORKEVENTS events;
951 int any = 0;
952
953 /* Enumerate the internal network events, and reset the object that
954 signalled us to catch the next event. */
955 WSAEnumNetworkEvents (scb->fd, state->sock_event, &events);
956
957 /* You'd think that FD_READ or FD_CLOSE would be set here. But,
958 sometimes, neither is. I suspect that the FD_READ is set and
959 the corresponding event signalled while recv is running, and
960 the FD_READ is then lowered when recv consumes all the data,
961 but there's no way to un-signal the event. This isn't a
962 problem for the call in net_select_thread, since any new
963 events after this point will not have been drained by recv.
964 It just means that we can't have the obvious assert here. */
965
966 /* If there is a read event, it might be still valid, or it might
967 not be - it may have been signalled before we last called
968 recv. Double-check that there is data. */
969 if (events.lNetworkEvents & FD_READ)
970 {
971 unsigned long available;
972
973 if (ioctlsocket (scb->fd, FIONREAD, &available) == 0
974 && available > 0)
975 {
976 SetEvent (state->read_event);
977 any = 1;
978 }
979 else
980 /* Oops, no data. This call to recv will cause future
981 data to retrigger the event, e.g. while we are
982 in net_select_thread. */
983 recv (scb->fd, NULL, 0, 0);
984 }
985
986 /* If there's a close event, then record it - it is obviously
987 still valid, and it will not be resignalled. */
988 if (events.lNetworkEvents & FD_CLOSE)
989 {
990 SetEvent (state->except_event);
991 any = 1;
992 }
993
994 /* If we set either handle, there's no need to wake the thread. */
995 if (any)
996 return;
997 }
998
999 /* Start the select thread. */
1000 SetEvent (state->start_select);
1001}
1002
1003static void
1004net_windows_done_wait_handle (struct serial *scb)
1005{
1006 struct net_windows_state *state = scb->state;
1007
1008 SetEvent (state->stop_select);
1009 WaitForSingleObject (state->have_stopped, INFINITE);
0ea3f30e
DJ
1010}
1011
1012static int
1013net_windows_open (struct serial *scb, const char *name)
1014{
1015 struct net_windows_state *state;
1016 int ret;
1017 DWORD threadId;
1018
1019 ret = net_open (scb, name);
1020 if (ret != 0)
1021 return ret;
1022
1023 state = xmalloc (sizeof (struct net_windows_state));
1024 memset (state, 0, sizeof (struct net_windows_state));
1025 scb->state = state;
1026
c3e2b812
DJ
1027 /* Create auto reset events to wake, stop, and exit the select
1028 thread. */
0ea3f30e
DJ
1029 state->start_select = CreateEvent (0, FALSE, FALSE, 0);
1030 state->stop_select = CreateEvent (0, FALSE, FALSE, 0);
c3e2b812
DJ
1031 state->exit_select = CreateEvent (0, FALSE, FALSE, 0);
1032
1033 /* Create a manual reset event to signal whether the thread is
1034 stopped. This must be manual reset, because we may wait on
1035 it multiple times without ever starting the thread. */
1036 state->have_stopped = CreateEvent (0, TRUE, FALSE, 0);
0ea3f30e
DJ
1037
1038 /* Associate an event with the socket. */
1039 state->sock_event = CreateEvent (0, TRUE, FALSE, 0);
1040 WSAEventSelect (scb->fd, state->sock_event, FD_READ | FD_CLOSE);
1041
1042 /* Create our own events to report read and close separately. */
1043 state->read_event = CreateEvent (0, FALSE, FALSE, 0);
1044 state->except_event = CreateEvent (0, FALSE, FALSE, 0);
1045
1046 /* And finally start the select thread. */
c3e2b812
DJ
1047 state->thread = CreateThread (NULL, 0, net_windows_select_thread, scb, 0,
1048 &threadId);
0ea3f30e
DJ
1049
1050 return 0;
1051}
1052
1053
1054static void
1055net_windows_close (struct serial *scb)
1056{
1057 struct net_windows_state *state = scb->state;
1058
c3e2b812
DJ
1059 SetEvent (state->exit_select);
1060 WaitForSingleObject (state->thread, INFINITE);
0ea3f30e
DJ
1061
1062 CloseHandle (state->read_event);
1063 CloseHandle (state->except_event);
c3e2b812 1064
0ea3f30e 1065 CloseHandle (state->start_select);
c3e2b812
DJ
1066 CloseHandle (state->stop_select);
1067 CloseHandle (state->exit_select);
1068 CloseHandle (state->have_stopped);
1069
0ea3f30e
DJ
1070 CloseHandle (state->sock_event);
1071
1072 xfree (scb->state);
1073
1074 net_close (scb);
1075}
1076
1077void
1078_initialize_ser_windows (void)
1079{
1080 WSADATA wsa_data;
1081 struct serial_ops *ops;
1082
1083 /* First register the serial port driver. */
1084
1085 ops = XMALLOC (struct serial_ops);
1086 memset (ops, 0, sizeof (struct serial_ops));
1087 ops->name = "hardwire";
1088 ops->next = 0;
1089 ops->open = ser_windows_open;
1090 ops->close = ser_windows_close;
1091
1092 ops->flush_output = ser_windows_flush_output;
1093 ops->flush_input = ser_windows_flush_input;
1094 ops->send_break = ser_windows_send_break;
1095
1096 /* These are only used for stdin; we do not need them for serial
1097 ports, so supply the standard dummies. */
1098 ops->get_tty_state = ser_base_get_tty_state;
1099 ops->set_tty_state = ser_base_set_tty_state;
1100 ops->print_tty_state = ser_base_print_tty_state;
1101 ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
1102
1103 ops->go_raw = ser_windows_raw;
1104 ops->setbaudrate = ser_windows_setbaudrate;
1105 ops->setstopbits = ser_windows_setstopbits;
1106 ops->drain_output = ser_windows_drain_output;
1107 ops->readchar = ser_base_readchar;
1108 ops->write = ser_base_write;
1109 ops->async = ser_base_async;
1110 ops->read_prim = ser_windows_read_prim;
1111 ops->write_prim = ser_windows_write_prim;
1112 ops->wait_handle = ser_windows_wait_handle;
1113
1114 serial_add_interface (ops);
1115
1116 /* Next create the dummy serial driver used for terminals. We only
1117 provide the TTY-related methods. */
1118
1119 ops = XMALLOC (struct serial_ops);
1120 memset (ops, 0, sizeof (struct serial_ops));
1121
1122 ops->name = "terminal";
1123 ops->next = 0;
1124
1125 ops->close = ser_console_close;
1126 ops->get_tty_state = ser_console_get_tty_state;
1127 ops->set_tty_state = ser_base_set_tty_state;
1128 ops->print_tty_state = ser_base_print_tty_state;
1129 ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
1130 ops->drain_output = ser_base_drain_output;
1131 ops->wait_handle = ser_console_wait_handle;
c3e2b812 1132 ops->done_wait_handle = ser_console_done_wait_handle;
0ea3f30e
DJ
1133
1134 serial_add_interface (ops);
1135
5f1fb6dc
JB
1136 /* The pipe interface. */
1137
1138 ops = XMALLOC (struct serial_ops);
1139 memset (ops, 0, sizeof (struct serial_ops));
1140 ops->name = "pipe";
1141 ops->next = 0;
1142 ops->open = pipe_windows_open;
1143 ops->close = pipe_windows_close;
1144 ops->readchar = ser_base_readchar;
1145 ops->write = ser_base_write;
1146 ops->flush_output = ser_base_flush_output;
1147 ops->flush_input = ser_base_flush_input;
1148 ops->send_break = ser_base_send_break;
1149 ops->go_raw = ser_base_raw;
1150 ops->get_tty_state = ser_base_get_tty_state;
1151 ops->set_tty_state = ser_base_set_tty_state;
1152 ops->print_tty_state = ser_base_print_tty_state;
1153 ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
1154 ops->setbaudrate = ser_base_setbaudrate;
1155 ops->setstopbits = ser_base_setstopbits;
1156 ops->drain_output = ser_base_drain_output;
1157 ops->async = ser_base_async;
1158 ops->read_prim = pipe_windows_read;
1159 ops->write_prim = pipe_windows_write;
1160 ops->wait_handle = pipe_wait_handle;
774a49c0 1161 ops->done_wait_handle = pipe_done_wait_handle;
5f1fb6dc
JB
1162
1163 serial_add_interface (ops);
1164
0ea3f30e
DJ
1165 /* If WinSock works, register the TCP/UDP socket driver. */
1166
1167 if (WSAStartup (MAKEWORD (1, 0), &wsa_data) != 0)
1168 /* WinSock is unavailable. */
1169 return;
1170
1171 ops = XMALLOC (struct serial_ops);
1172 memset (ops, 0, sizeof (struct serial_ops));
1173 ops->name = "tcp";
1174 ops->next = 0;
1175 ops->open = net_windows_open;
1176 ops->close = net_windows_close;
1177 ops->readchar = ser_base_readchar;
1178 ops->write = ser_base_write;
1179 ops->flush_output = ser_base_flush_output;
1180 ops->flush_input = ser_base_flush_input;
1181 ops->send_break = ser_base_send_break;
1182 ops->go_raw = ser_base_raw;
1183 ops->get_tty_state = ser_base_get_tty_state;
1184 ops->set_tty_state = ser_base_set_tty_state;
1185 ops->print_tty_state = ser_base_print_tty_state;
1186 ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
1187 ops->setbaudrate = ser_base_setbaudrate;
1188 ops->setstopbits = ser_base_setstopbits;
1189 ops->drain_output = ser_base_drain_output;
1190 ops->async = ser_base_async;
1191 ops->read_prim = net_read_prim;
1192 ops->write_prim = net_write_prim;
1193 ops->wait_handle = net_windows_wait_handle;
c3e2b812 1194 ops->done_wait_handle = net_windows_done_wait_handle;
0ea3f30e
DJ
1195 serial_add_interface (ops);
1196}
This page took 0.14274 seconds and 4 git commands to generate.