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