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