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