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