1 /* 2 * poll_windows: poll compatibility wrapper for Windows 3 * Copyright 2012-2013 RealVNC Ltd. 4 * Copyright 2009-2010 Pete Batard <pete (at) akeo.ie> 5 * With contributions from Michael Plante, Orin Eman et al. 6 * Parts of poll implementation from libusb-win32, by Stephan Meyer et al. 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23 24 /* 25 * poll() and pipe() Windows compatibility layer for libusb 1.0 26 * 27 * The way this layer works is by using OVERLAPPED with async I/O transfers, as 28 * OVERLAPPED have an associated event which is flagged for I/O completion. 29 * 30 * For USB pollable async I/O, you would typically: 31 * - obtain a Windows HANDLE to a file or device that has been opened in 32 * OVERLAPPED mode 33 * - call usbi_create_fd with this handle to obtain a custom fd. 34 * Note that if you need simultaneous R/W access, you need to call create_fd 35 * twice, once in RW_READ and once in RW_WRITE mode to obtain 2 separate 36 * pollable fds 37 * - leave the core functions call the poll routine and flag POLLIN/POLLOUT 38 * 39 * The pipe pollable synchronous I/O works using the overlapped event associated 40 * with a fake pipe. The read/write functions are only meant to be used in that 41 * context. 42 */ 43 #include <config.h> 44 45 #include <errno.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 49 #include "libusbi.h" 50 51 // Uncomment to debug the polling layer 52 //#define DEBUG_POLL_WINDOWS 53 #if defined(DEBUG_POLL_WINDOWS) 54 #define poll_dbg usbi_dbg 55 #else 56 // MSVC++ < 2005 cannot use a variadic argument and non MSVC 57 // compilers produce warnings if parenthesis are omitted. 58 #if defined(_MSC_VER) && (_MSC_VER < 1400) 59 #define poll_dbg 60 #else 61 #define poll_dbg(...) 62 #endif 63 #endif 64 65 #if defined(_PREFAST_) 66 #pragma warning(disable:28719) 67 #endif 68 69 #define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0) 70 71 // public fd data 72 const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE}; 73 struct winfd poll_fd[MAX_FDS]; 74 // internal fd data 75 struct { 76 CRITICAL_SECTION mutex; // lock for fds 77 // Additional variables for XP CancelIoEx partial emulation 78 HANDLE original_handle; 79 DWORD thread_id; 80 } _poll_fd[MAX_FDS]; 81 82 // globals 83 BOOLEAN is_polling_set = FALSE; 84 LONG pipe_number = 0; 85 static volatile LONG compat_spinlock = 0; 86 87 #if !defined(_WIN32_WCE) 88 // CancelIoEx, available on Vista and later only, provides the ability to cancel 89 // a single transfer (OVERLAPPED) when used. As it may not be part of any of the 90 // platform headers, we hook into the Kernel32 system DLL directly to seek it. 91 static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL; 92 #define Use_Duplicate_Handles (pCancelIoEx == NULL) 93 94 static inline void setup_cancel_io(void) 95 { 96 HMODULE hKernel32 = GetModuleHandleA("KERNEL32"); 97 if (hKernel32 != NULL) { 98 pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED)) 99 GetProcAddress(hKernel32, "CancelIoEx"); 100 } 101 usbi_dbg("Will use CancelIo%s for I/O cancellation", 102 Use_Duplicate_Handles?"":"Ex"); 103 } 104 105 static inline BOOL cancel_io(int _index) 106 { 107 if ((_index < 0) || (_index >= MAX_FDS)) { 108 return FALSE; 109 } 110 111 if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) 112 || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) { 113 return TRUE; 114 } 115 if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) { 116 // Cancel outstanding transfer via the specific callback 117 (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer); 118 return TRUE; 119 } 120 if (pCancelIoEx != NULL) { 121 return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped); 122 } 123 if (_poll_fd[_index].thread_id == GetCurrentThreadId()) { 124 return CancelIo(poll_fd[_index].handle); 125 } 126 usbi_warn(NULL, "Unable to cancel I/O that was started from another thread"); 127 return FALSE; 128 } 129 #else 130 #define Use_Duplicate_Handles FALSE 131 132 static __inline void setup_cancel_io() 133 { 134 // No setup needed on WinCE 135 } 136 137 static __inline BOOL cancel_io(int _index) 138 { 139 if ((_index < 0) || (_index >= MAX_FDS)) { 140 return FALSE; 141 } 142 if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) 143 || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) { 144 return TRUE; 145 } 146 if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) { 147 // Cancel outstanding transfer via the specific callback 148 (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer); 149 } 150 return TRUE; 151 } 152 #endif 153 154 // Init 155 void init_polling(void) 156 { 157 int i; 158 159 while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { 160 SleepEx(0, TRUE); 161 } 162 if (!is_polling_set) { 163 setup_cancel_io(); 164 for (i=0; i<MAX_FDS; i++) { 165 poll_fd[i] = INVALID_WINFD; 166 _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; 167 _poll_fd[i].thread_id = 0; 168 InitializeCriticalSection(&_poll_fd[i].mutex); 169 } 170 is_polling_set = TRUE; 171 } 172 InterlockedExchange((LONG *)&compat_spinlock, 0); 173 } 174 175 // Internal function to retrieve the table index (and lock the fd mutex) 176 static int _fd_to_index_and_lock(int fd) 177 { 178 int i; 179 180 if (fd < 0) 181 return -1; 182 183 for (i=0; i<MAX_FDS; i++) { 184 if (poll_fd[i].fd == fd) { 185 EnterCriticalSection(&_poll_fd[i].mutex); 186 // fd might have changed before we got to critical 187 if (poll_fd[i].fd != fd) { 188 LeaveCriticalSection(&_poll_fd[i].mutex); 189 continue; 190 } 191 return i; 192 } 193 } 194 return -1; 195 } 196 197 static OVERLAPPED *create_overlapped(void) 198 { 199 OVERLAPPED *overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED)); 200 if (overlapped == NULL) { 201 return NULL; 202 } 203 overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 204 if(overlapped->hEvent == NULL) { 205 free (overlapped); 206 return NULL; 207 } 208 return overlapped; 209 } 210 211 static void free_overlapped(OVERLAPPED *overlapped) 212 { 213 if (overlapped == NULL) 214 return; 215 216 if ( (overlapped->hEvent != 0) 217 && (overlapped->hEvent != INVALID_HANDLE_VALUE) ) { 218 CloseHandle(overlapped->hEvent); 219 } 220 free(overlapped); 221 } 222 223 void exit_polling(void) 224 { 225 int i; 226 227 while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { 228 SleepEx(0, TRUE); 229 } 230 if (is_polling_set) { 231 is_polling_set = FALSE; 232 233 for (i=0; i<MAX_FDS; i++) { 234 // Cancel any async I/O (handle can be invalid) 235 cancel_io(i); 236 // If anything was pending on that I/O, it should be 237 // terminating, and we should be able to access the fd 238 // mutex lock before too long 239 EnterCriticalSection(&_poll_fd[i].mutex); 240 free_overlapped(poll_fd[i].overlapped); 241 if (Use_Duplicate_Handles) { 242 // Close duplicate handle 243 if (_poll_fd[i].original_handle != INVALID_HANDLE_VALUE) { 244 CloseHandle(poll_fd[i].handle); 245 } 246 } 247 poll_fd[i] = INVALID_WINFD; 248 LeaveCriticalSection(&_poll_fd[i].mutex); 249 DeleteCriticalSection(&_poll_fd[i].mutex); 250 } 251 } 252 InterlockedExchange((LONG *)&compat_spinlock, 0); 253 } 254 255 /* 256 * Create a fake pipe. 257 * As libusb only uses pipes for signaling, all we need from a pipe is an 258 * event. To that extent, we create a single wfd and overlapped as a means 259 * to access that event. 260 */ 261 int usbi_pipe(int filedes[2]) 262 { 263 int i; 264 OVERLAPPED* overlapped; 265 266 CHECK_INIT_POLLING; 267 268 overlapped = create_overlapped(); 269 270 if (overlapped == NULL) { 271 return -1; 272 } 273 // The overlapped must have status pending for signaling to work in poll 274 overlapped->Internal = STATUS_PENDING; 275 overlapped->InternalHigh = 0; 276 277 for (i=0; i<MAX_FDS; i++) { 278 if (poll_fd[i].fd < 0) { 279 EnterCriticalSection(&_poll_fd[i].mutex); 280 // fd might have been allocated before we got to critical 281 if (poll_fd[i].fd >= 0) { 282 LeaveCriticalSection(&_poll_fd[i].mutex); 283 continue; 284 } 285 286 // Use index as the unique fd number 287 poll_fd[i].fd = i; 288 // Read end of the "pipe" 289 filedes[0] = poll_fd[i].fd; 290 // We can use the same handle for both ends 291 filedes[1] = filedes[0]; 292 293 poll_fd[i].handle = DUMMY_HANDLE; 294 poll_fd[i].overlapped = overlapped; 295 // There's no polling on the write end, so we just use READ for our needs 296 poll_fd[i].rw = RW_READ; 297 _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; 298 LeaveCriticalSection(&_poll_fd[i].mutex); 299 return 0; 300 } 301 } 302 free_overlapped(overlapped); 303 return -1; 304 } 305 306 /* 307 * Create both an fd and an OVERLAPPED from an open Windows handle, so that 308 * it can be used with our polling function 309 * The handle MUST support overlapped transfers (usually requires CreateFile 310 * with FILE_FLAG_OVERLAPPED) 311 * Return a pollable file descriptor struct, or INVALID_WINFD on error 312 * 313 * Note that the fd returned by this function is a per-transfer fd, rather 314 * than a per-session fd and cannot be used for anything else but our 315 * custom functions (the fd itself points to the NUL: device) 316 * if you plan to do R/W on the same handle, you MUST create 2 fds: one for 317 * read and one for write. Using a single R/W fd is unsupported and will 318 * produce unexpected results 319 */ 320 struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn) 321 { 322 int i; 323 struct winfd wfd = INVALID_WINFD; 324 OVERLAPPED* overlapped = NULL; 325 326 CHECK_INIT_POLLING; 327 328 if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) { 329 return INVALID_WINFD; 330 } 331 332 wfd.itransfer = itransfer; 333 wfd.cancel_fn = cancel_fn; 334 335 if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) { 336 usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported. " 337 "If you want to poll for R/W simultaneously, create multiple fds from the same handle."); 338 return INVALID_WINFD; 339 } 340 if (access_mode == RW_READ) { 341 wfd.rw = RW_READ; 342 } else { 343 wfd.rw = RW_WRITE; 344 } 345 346 overlapped = create_overlapped(); 347 if(overlapped == NULL) { 348 return INVALID_WINFD; 349 } 350 351 for (i=0; i<MAX_FDS; i++) { 352 if (poll_fd[i].fd < 0) { 353 EnterCriticalSection(&_poll_fd[i].mutex); 354 // fd might have been removed before we got to critical 355 if (poll_fd[i].fd >= 0) { 356 LeaveCriticalSection(&_poll_fd[i].mutex); 357 continue; 358 } 359 // Use index as the unique fd number 360 wfd.fd = i; 361 // Attempt to emulate some of the CancelIoEx behaviour on platforms 362 // that don't have it 363 if (Use_Duplicate_Handles) { 364 _poll_fd[i].thread_id = GetCurrentThreadId(); 365 if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), 366 &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { 367 usbi_dbg("could not duplicate handle for CancelIo - using original one"); 368 wfd.handle = handle; 369 // Make sure we won't close the original handle on fd deletion then 370 _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; 371 } else { 372 _poll_fd[i].original_handle = handle; 373 } 374 } else { 375 wfd.handle = handle; 376 } 377 wfd.overlapped = overlapped; 378 memcpy(&poll_fd[i], &wfd, sizeof(struct winfd)); 379 LeaveCriticalSection(&_poll_fd[i].mutex); 380 return wfd; 381 } 382 } 383 free_overlapped(overlapped); 384 return INVALID_WINFD; 385 } 386 387 static void _free_index(int _index) 388 { 389 // Cancel any async IO (Don't care about the validity of our handles for this) 390 cancel_io(_index); 391 // close the duplicate handle (if we have an actual duplicate) 392 if (Use_Duplicate_Handles) { 393 if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) { 394 CloseHandle(poll_fd[_index].handle); 395 } 396 _poll_fd[_index].original_handle = INVALID_HANDLE_VALUE; 397 _poll_fd[_index].thread_id = 0; 398 } 399 free_overlapped(poll_fd[_index].overlapped); 400 poll_fd[_index] = INVALID_WINFD; 401 } 402 403 /* 404 * Release a pollable file descriptor. 405 * 406 * Note that the associated Windows handle is not closed by this call 407 */ 408 void usbi_free_fd(struct winfd *wfd) 409 { 410 int _index; 411 412 CHECK_INIT_POLLING; 413 414 _index = _fd_to_index_and_lock(wfd->fd); 415 if (_index < 0) { 416 return; 417 } 418 _free_index(_index); 419 *wfd = INVALID_WINFD; 420 LeaveCriticalSection(&_poll_fd[_index].mutex); 421 } 422 423 /* 424 * The functions below perform various conversions between fd, handle and OVERLAPPED 425 */ 426 struct winfd fd_to_winfd(int fd) 427 { 428 int i; 429 struct winfd wfd; 430 431 CHECK_INIT_POLLING; 432 433 if (fd < 0) 434 return INVALID_WINFD; 435 436 for (i=0; i<MAX_FDS; i++) { 437 if (poll_fd[i].fd == fd) { 438 EnterCriticalSection(&_poll_fd[i].mutex); 439 // fd might have been deleted before we got to critical 440 if (poll_fd[i].fd != fd) { 441 LeaveCriticalSection(&_poll_fd[i].mutex); 442 continue; 443 } 444 memcpy(&wfd, &poll_fd[i], sizeof(struct winfd)); 445 LeaveCriticalSection(&_poll_fd[i].mutex); 446 return wfd; 447 } 448 } 449 return INVALID_WINFD; 450 } 451 452 struct winfd handle_to_winfd(HANDLE handle) 453 { 454 int i; 455 struct winfd wfd; 456 457 CHECK_INIT_POLLING; 458 459 if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) 460 return INVALID_WINFD; 461 462 for (i=0; i<MAX_FDS; i++) { 463 if (poll_fd[i].handle == handle) { 464 EnterCriticalSection(&_poll_fd[i].mutex); 465 // fd might have been deleted before we got to critical 466 if (poll_fd[i].handle != handle) { 467 LeaveCriticalSection(&_poll_fd[i].mutex); 468 continue; 469 } 470 memcpy(&wfd, &poll_fd[i], sizeof(struct winfd)); 471 LeaveCriticalSection(&_poll_fd[i].mutex); 472 return wfd; 473 } 474 } 475 return INVALID_WINFD; 476 } 477 478 struct winfd overlapped_to_winfd(OVERLAPPED* overlapped) 479 { 480 int i; 481 struct winfd wfd; 482 483 CHECK_INIT_POLLING; 484 485 if (overlapped == NULL) 486 return INVALID_WINFD; 487 488 for (i=0; i<MAX_FDS; i++) { 489 if (poll_fd[i].overlapped == overlapped) { 490 EnterCriticalSection(&_poll_fd[i].mutex); 491 // fd might have been deleted before we got to critical 492 if (poll_fd[i].overlapped != overlapped) { 493 LeaveCriticalSection(&_poll_fd[i].mutex); 494 continue; 495 } 496 memcpy(&wfd, &poll_fd[i], sizeof(struct winfd)); 497 LeaveCriticalSection(&_poll_fd[i].mutex); 498 return wfd; 499 } 500 } 501 return INVALID_WINFD; 502 } 503 504 /* 505 * POSIX poll equivalent, using Windows OVERLAPPED 506 * Currently, this function only accepts one of POLLIN or POLLOUT per fd 507 * (but you can create multiple fds from the same handle for read and write) 508 */ 509 int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout) 510 { 511 unsigned i; 512 int _index, object_index, triggered; 513 HANDLE *handles_to_wait_on; 514 int *handle_to_index; 515 DWORD nb_handles_to_wait_on = 0; 516 DWORD ret; 517 518 CHECK_INIT_POLLING; 519 520 triggered = 0; 521 handles_to_wait_on = (HANDLE*) calloc(nfds+1, sizeof(HANDLE)); // +1 for fd_update 522 handle_to_index = (int*) calloc(nfds, sizeof(int)); 523 if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) { 524 errno = ENOMEM; 525 triggered = -1; 526 goto poll_exit; 527 } 528 529 for (i = 0; i < nfds; ++i) { 530 fds[i].revents = 0; 531 532 // Only one of POLLIN or POLLOUT can be selected with this version of poll (not both) 533 if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) { 534 fds[i].revents |= POLLERR; 535 errno = EACCES; 536 usbi_warn(NULL, "unsupported set of events"); 537 triggered = -1; 538 goto poll_exit; 539 } 540 541 _index = _fd_to_index_and_lock(fds[i].fd); 542 poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, poll_fd[_index].fd, poll_fd[_index].overlapped, fds[i].events); 543 544 if ( (_index < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) 545 || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL)) { 546 fds[i].revents |= POLLNVAL | POLLERR; 547 errno = EBADF; 548 if (_index >= 0) { 549 LeaveCriticalSection(&_poll_fd[_index].mutex); 550 } 551 usbi_warn(NULL, "invalid fd"); 552 triggered = -1; 553 goto poll_exit; 554 } 555 556 // IN or OUT must match our fd direction 557 if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) { 558 fds[i].revents |= POLLNVAL | POLLERR; 559 errno = EBADF; 560 usbi_warn(NULL, "attempted POLLIN on fd without READ access"); 561 LeaveCriticalSection(&_poll_fd[_index].mutex); 562 triggered = -1; 563 goto poll_exit; 564 } 565 566 if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) { 567 fds[i].revents |= POLLNVAL | POLLERR; 568 errno = EBADF; 569 usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access"); 570 LeaveCriticalSection(&_poll_fd[_index].mutex); 571 triggered = -1; 572 goto poll_exit; 573 } 574 575 // The following macro only works if overlapped I/O was reported pending 576 if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped)) 577 || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) { 578 poll_dbg(" completed"); 579 // checks above should ensure this works: 580 fds[i].revents = fds[i].events; 581 triggered++; 582 } else { 583 handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent; 584 handle_to_index[nb_handles_to_wait_on] = i; 585 nb_handles_to_wait_on++; 586 } 587 LeaveCriticalSection(&_poll_fd[_index].mutex); 588 } 589 590 // If nothing was triggered, wait on all fds that require it 591 if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) { 592 if (timeout < 0) { 593 poll_dbg("starting infinite wait for %u handles...", (unsigned int)nb_handles_to_wait_on); 594 } else { 595 poll_dbg("starting %d ms wait for %u handles...", timeout, (unsigned int)nb_handles_to_wait_on); 596 } 597 ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on, 598 FALSE, (timeout<0)?INFINITE:(DWORD)timeout); 599 object_index = ret-WAIT_OBJECT_0; 600 if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) { 601 poll_dbg(" completed after wait"); 602 i = handle_to_index[object_index]; 603 _index = _fd_to_index_and_lock(fds[i].fd); 604 fds[i].revents = fds[i].events; 605 triggered++; 606 if (_index >= 0) { 607 LeaveCriticalSection(&_poll_fd[_index].mutex); 608 } 609 } else if (ret == WAIT_TIMEOUT) { 610 poll_dbg(" timed out"); 611 triggered = 0; // 0 = timeout 612 } else { 613 errno = EIO; 614 triggered = -1; // error 615 } 616 } 617 618 poll_exit: 619 if (handles_to_wait_on != NULL) { 620 free(handles_to_wait_on); 621 } 622 if (handle_to_index != NULL) { 623 free(handle_to_index); 624 } 625 return triggered; 626 } 627 628 /* 629 * close a fake pipe fd 630 */ 631 int usbi_close(int fd) 632 { 633 int _index; 634 int r = -1; 635 636 CHECK_INIT_POLLING; 637 638 _index = _fd_to_index_and_lock(fd); 639 640 if (_index < 0) { 641 errno = EBADF; 642 } else { 643 free_overlapped(poll_fd[_index].overlapped); 644 poll_fd[_index] = INVALID_WINFD; 645 LeaveCriticalSection(&_poll_fd[_index].mutex); 646 } 647 return r; 648 } 649 650 /* 651 * synchronous write for fake "pipe" signaling 652 */ 653 ssize_t usbi_write(int fd, const void *buf, size_t count) 654 { 655 int _index; 656 UNUSED(buf); 657 658 CHECK_INIT_POLLING; 659 660 if (count != sizeof(unsigned char)) { 661 usbi_err(NULL, "this function should only used for signaling"); 662 return -1; 663 } 664 665 _index = _fd_to_index_and_lock(fd); 666 667 if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) { 668 errno = EBADF; 669 if (_index >= 0) { 670 LeaveCriticalSection(&_poll_fd[_index].mutex); 671 } 672 return -1; 673 } 674 675 poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId()); 676 SetEvent(poll_fd[_index].overlapped->hEvent); 677 poll_fd[_index].overlapped->Internal = STATUS_WAIT_0; 678 // If two threads write on the pipe at the same time, we need to 679 // process two separate reads => use the overlapped as a counter 680 poll_fd[_index].overlapped->InternalHigh++; 681 682 LeaveCriticalSection(&_poll_fd[_index].mutex); 683 return sizeof(unsigned char); 684 } 685 686 /* 687 * synchronous read for fake "pipe" signaling 688 */ 689 ssize_t usbi_read(int fd, void *buf, size_t count) 690 { 691 int _index; 692 ssize_t r = -1; 693 UNUSED(buf); 694 695 CHECK_INIT_POLLING; 696 697 if (count != sizeof(unsigned char)) { 698 usbi_err(NULL, "this function should only used for signaling"); 699 return -1; 700 } 701 702 _index = _fd_to_index_and_lock(fd); 703 704 if (_index < 0) { 705 errno = EBADF; 706 return -1; 707 } 708 709 if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) { 710 usbi_warn(NULL, "waiting for event failed: %u", (unsigned int)GetLastError()); 711 errno = EIO; 712 goto out; 713 } 714 715 poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, (unsigned int)GetCurrentThreadId()); 716 poll_fd[_index].overlapped->InternalHigh--; 717 // Don't reset unless we don't have any more events to process 718 if (poll_fd[_index].overlapped->InternalHigh <= 0) { 719 ResetEvent(poll_fd[_index].overlapped->hEvent); 720 poll_fd[_index].overlapped->Internal = STATUS_PENDING; 721 } 722 723 r = sizeof(unsigned char); 724 725 out: 726 LeaveCriticalSection(&_poll_fd[_index].mutex); 727 return r; 728 } 729