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