15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * poll_windows: poll compatibility wrapper for Windows 3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Copyright © 2012-2013 RealVNC Ltd. 4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Copyright © 2009-2010 Pete Batard <pete@akeo.ie> 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * With contributions from Michael Plante, Orin Eman et al. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Parts of poll implementation from libusb-win32, by Stephan Meyer et al. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This library is free software; you can redistribute it and/or 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * modify it under the terms of the GNU Lesser General Public 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * License as published by the Free Software Foundation; either 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * version 2.1 of the License, or (at your option) any later version. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This library is distributed in the hope that it will be useful, 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Lesser General Public License for more details. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * You should have received a copy of the GNU Lesser General Public 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * License along with this library; if not, write to the Free Software 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * poll() and pipe() Windows compatibility layer for libusbx 1.0 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The way this layer works is by using OVERLAPPED with async I/O transfers, as 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OVERLAPPED have an associated event which is flagged for I/O completion. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * For USB pollable async I/O, you would typically: 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - obtain a Windows HANDLE to a file or device that has been opened in 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OVERLAPPED mode 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - call usbi_create_fd with this handle to obtain a custom fd. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note that if you need simultaneous R/W access, you need to call create_fd 35ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * twice, once in RW_READ and once in RW_WRITE mode to obtain 2 separate 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * pollable fds 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - leave the core functions call the poll routine and flag POLLIN/POLLOUT 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The pipe pollable synchronous I/O works using the overlapped event associated 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * with a fake pipe. The read/write functions are only meant to be used in that 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * context. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 47ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "libusbi.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Uncomment to debug the polling layer 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//#define DEBUG_POLL_WINDOWS 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(DEBUG_POLL_WINDOWS) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define poll_dbg usbi_dbg 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// MSVC++ < 2005 cannot use a variadic argument and non MSVC 55ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// compilers produce warnings if parenthesis are ommitted. 56ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(_MSC_VER) && (_MSC_VER < 1400) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define poll_dbg 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define poll_dbg(...) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_PREFAST_) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(disable:28719) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// public fd data 70ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochconst struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE}; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winfd poll_fd[MAX_FDS]; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// internal fd data 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRITICAL_SECTION mutex; // lock for fds 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Additional variables for XP CancelIoEx partial emulation 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE original_handle; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD thread_id; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} _poll_fd[MAX_FDS]; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// globals 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOLEAN is_polling_set = FALSE; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LONG pipe_number = 0; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static volatile LONG compat_spinlock = 0; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if !defined(_WIN32_WCE) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CancelIoEx, available on Vista and later only, provides the ability to cancel 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a single transfer (OVERLAPPED) when used. As it may not be part of any of the 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// platform headers, we hook into the Kernel32 system DLL directly to seek it. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL; 90ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#define Use_Duplicate_Handles (pCancelIoEx == NULL) 91ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic inline void setup_cancel_io(void) 93ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 94ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch HMODULE hKernel32 = GetModuleHandleA("KERNEL32"); 95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (hKernel32 != NULL) { 96ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED)) 97ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch GetProcAddress(hKernel32, "CancelIoEx"); 98ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 99ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_dbg("Will use CancelIo%s for I/O cancellation", 100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch Use_Duplicate_Handles?"":"Ex"); 101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic inline BOOL cancel_io(int _index) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((_index < 0) || (_index >= MAX_FDS)) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) { 114ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Cancel outstanding transfer via the specific callback 115ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer); 116ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return TRUE; 117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (pCancelIoEx != NULL) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (_poll_fd[_index].thread_id == GetCurrentThreadId()) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CancelIo(poll_fd[_index].handle); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_warn(NULL, "Unable to cancel I/O that was started from another thread"); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 127ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#else 128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#define Use_Duplicate_Handles FALSE 129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 130ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic __inline void setup_cancel_io() 131ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // No setup needed on WinCE 133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic __inline BOOL cancel_io(int _index) 136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch{ 137ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if ((_index < 0) || (_index >= MAX_FDS)) { 138ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return FALSE; 139ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 140ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) 141ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) { 142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return TRUE; 143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 144ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) { 145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Cancel outstanding transfer via the specific callback 146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer); 147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 148ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return TRUE; 149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 150ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Init 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void init_polling(void) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SleepEx(0, TRUE); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_polling_set) { 161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch setup_cancel_io(); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=0; i<MAX_FDS; i++) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_fd[i] = INVALID_WINFD; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _poll_fd[i].thread_id = 0; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitializeCriticalSection(&_poll_fd[i].mutex); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_polling_set = TRUE; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch InterlockedExchange((LONG *)&compat_spinlock, 0); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Internal function to retrieve the table index (and lock the fd mutex) 174ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic int _fd_to_index_and_lock(int fd) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (fd < 0) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=0; i<MAX_FDS; i++) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[i].fd == fd) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnterCriticalSection(&_poll_fd[i].mutex); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fd might have changed before we got to critical 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[i].fd != fd) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[i].mutex); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic OVERLAPPED *create_overlapped(void) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch OVERLAPPED *overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED)); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (overlapped == NULL) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if(overlapped->hEvent == NULL) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free (overlapped); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return overlapped; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 209ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void free_overlapped(OVERLAPPED *overlapped) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (overlapped == NULL) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( (overlapped->hEvent != 0) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) && (overlapped->hEvent != INVALID_HANDLE_VALUE) ) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(overlapped->hEvent); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(overlapped); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void exit_polling(void) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (InterlockedExchange((LONG *)&compat_spinlock, 1) == 1) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SleepEx(0, TRUE); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_polling_set) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_polling_set = FALSE; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=0; i<MAX_FDS; i++) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel any async I/O (handle can be invalid) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancel_io(i); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If anything was pending on that I/O, it should be 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // terminating, and we should be able to access the fd 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mutex lock before too long 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnterCriticalSection(&_poll_fd[i].mutex); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free_overlapped(poll_fd[i].overlapped); 239ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (Use_Duplicate_Handles) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close duplicate handle 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (_poll_fd[i].original_handle != INVALID_HANDLE_VALUE) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(poll_fd[i].handle); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_fd[i] = INVALID_WINFD; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[i].mutex); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteCriticalSection(&_poll_fd[i].mutex); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 250ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch InterlockedExchange((LONG *)&compat_spinlock, 0); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Create a fake pipe. 255ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * As libusbx only uses pipes for signaling, all we need from a pipe is an 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * event. To that extent, we create a single wfd and overlapped as a means 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to access that event. 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int usbi_pipe(int filedes[2]) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OVERLAPPED* overlapped; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_INIT_POLLING; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 266ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch overlapped = create_overlapped(); 267ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (overlapped == NULL) { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The overlapped must have status pending for signaling to work in poll 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overlapped->Internal = STATUS_PENDING; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overlapped->InternalHigh = 0; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=0; i<MAX_FDS; i++) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[i].fd < 0) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnterCriticalSection(&_poll_fd[i].mutex); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fd might have been allocated before we got to critical 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[i].fd >= 0) { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[i].mutex); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Use index as the unique fd number 285ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch poll_fd[i].fd = i; 286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Read end of the "pipe" 287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch filedes[0] = poll_fd[i].fd; 288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // We can use the same handle for both ends 289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch filedes[1] = filedes[0]; 290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_fd[i].handle = DUMMY_HANDLE; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_fd[i].overlapped = overlapped; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There's no polling on the write end, so we just use READ for our needs 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_fd[i].rw = RW_READ; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[i].mutex); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch free_overlapped(overlapped); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Create both an fd and an OVERLAPPED from an open Windows handle, so that 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * it can be used with our polling function 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The handle MUST support overlapped transfers (usually requires CreateFile 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * with FILE_FLAG_OVERLAPPED) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return a pollable file descriptor struct, or INVALID_WINFD on error 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note that the fd returned by this function is a per-transfer fd, rather 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * than a per-session fd and cannot be used for anything else but our 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * custom functions (the fd itself points to the NUL: device) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * if you plan to do R/W on the same handle, you MUST create 2 fds: one for 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * read and one for write. Using a single R/W fd is unsupported and will 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * produce unexpected results 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstruct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int i; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct winfd wfd = INVALID_WINFD; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OVERLAPPED* overlapped = NULL; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_INIT_POLLING; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return INVALID_WINFD; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wfd.itransfer = itransfer; 331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wfd.cancel_fn = cancel_fn; 332ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 333ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) { 334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported.\n" 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If you want to poll for R/W simultaneously, create multiple fds from the same handle."); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return INVALID_WINFD; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (access_mode == RW_READ) { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wfd.rw = RW_READ; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wfd.rw = RW_WRITE; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overlapped = create_overlapped(); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if(overlapped == NULL) { 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return INVALID_WINFD; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=0; i<MAX_FDS; i++) { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[i].fd < 0) { 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnterCriticalSection(&_poll_fd[i].mutex); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fd might have been removed before we got to critical 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[i].fd >= 0) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[i].mutex); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 357ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Use index as the unique fd number 358ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch wfd.fd = i; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Attempt to emulate some of the CancelIoEx behaviour on platforms 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that don't have it 361ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (Use_Duplicate_Handles) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _poll_fd[i].thread_id = GetCurrentThreadId(); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_dbg("could not duplicate handle for CancelIo - using original one"); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wfd.handle = handle; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we won't close the original handle on fd deletion then 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _poll_fd[i].original_handle = INVALID_HANDLE_VALUE; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _poll_fd[i].original_handle = handle; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wfd.handle = handle; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wfd.overlapped = overlapped; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&poll_fd[i], &wfd, sizeof(struct winfd)); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[i].mutex); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return wfd; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free_overlapped(overlapped); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return INVALID_WINFD; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void _free_index(int _index) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel any async IO (Don't care about the validity of our handles for this) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cancel_io(_index); 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // close the duplicate handle (if we have an actual duplicate) 390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (Use_Duplicate_Handles) { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) { 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseHandle(poll_fd[_index].handle); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _poll_fd[_index].original_handle = INVALID_HANDLE_VALUE; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _poll_fd[_index].thread_id = 0; 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free_overlapped(poll_fd[_index].overlapped); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_fd[_index] = INVALID_WINFD; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Release a pollable file descriptor. 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note that the associated Windows handle is not closed by this call 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 406ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid usbi_free_fd(struct winfd *wfd) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int _index; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_INIT_POLLING; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 412ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch _index = _fd_to_index_and_lock(wfd->fd); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (_index < 0) { 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _free_index(_index); 417ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch *wfd = INVALID_WINFD; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[_index].mutex); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The functions below perform various conversions between fd, handle and OVERLAPPED 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winfd fd_to_winfd(int fd) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct winfd wfd; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_INIT_POLLING; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 43168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (fd < 0) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return INVALID_WINFD; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=0; i<MAX_FDS; i++) { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[i].fd == fd) { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnterCriticalSection(&_poll_fd[i].mutex); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fd might have been deleted before we got to critical 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[i].fd != fd) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[i].mutex); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&wfd, &poll_fd[i], sizeof(struct winfd)); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[i].mutex); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return wfd; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return INVALID_WINFD; 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winfd handle_to_winfd(HANDLE handle) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct winfd wfd; 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_INIT_POLLING; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((handle == 0) || (handle == INVALID_HANDLE_VALUE)) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return INVALID_WINFD; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=0; i<MAX_FDS; i++) { 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[i].handle == handle) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnterCriticalSection(&_poll_fd[i].mutex); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fd might have been deleted before we got to critical 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[i].handle != handle) { 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[i].mutex); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&wfd, &poll_fd[i], sizeof(struct winfd)); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[i].mutex); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return wfd; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return INVALID_WINFD; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winfd overlapped_to_winfd(OVERLAPPED* overlapped) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct winfd wfd; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_INIT_POLLING; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (overlapped == NULL) 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return INVALID_WINFD; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=0; i<MAX_FDS; i++) { 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[i].overlapped == overlapped) { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnterCriticalSection(&_poll_fd[i].mutex); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // fd might have been deleted before we got to critical 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[i].overlapped != overlapped) { 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[i].mutex); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(&wfd, &poll_fd[i], sizeof(struct winfd)); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[i].mutex); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return wfd; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return INVALID_WINFD; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * POSIX poll equivalent, using Windows OVERLAPPED 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Currently, this function only accepts one of POLLIN or POLLOUT per fd 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (but you can create multiple fds from the same handle for read and write) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned i; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int _index, object_index, triggered; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE *handles_to_wait_on; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int *handle_to_index; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD nb_handles_to_wait_on = 0; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD ret; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_INIT_POLLING; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) triggered = 0; 519eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch handles_to_wait_on = (HANDLE*) calloc(nfds+1, sizeof(HANDLE)); // +1 for fd_update 520eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch handle_to_index = (int*) calloc(nfds, sizeof(int)); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((handles_to_wait_on == NULL) || (handle_to_index == NULL)) { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = ENOMEM; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) triggered = -1; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto poll_exit; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < nfds; ++i) { 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fds[i].revents = 0; 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only one of POLLIN or POLLOUT can be selected with this version of poll (not both) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((fds[i].events & ~POLLIN) && (!(fds[i].events & POLLOUT))) { 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fds[i].revents |= POLLERR; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EACCES; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_warn(NULL, "unsupported set of events"); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) triggered = -1; 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto poll_exit; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _index = _fd_to_index_and_lock(fds[i].fd); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_dbg("fd[%d]=%d: (overlapped=%p) got events %04X", i, poll_fd[_index].fd, poll_fd[_index].overlapped, fds[i].events); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( (_index < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL)) { 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fds[i].revents |= POLLNVAL | POLLERR; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EBADF; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (_index >= 0) { 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[_index].mutex); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_warn(NULL, "invalid fd"); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) triggered = -1; 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto poll_exit; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IN or OUT must match our fd direction 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((fds[i].events & POLLIN) && (poll_fd[_index].rw != RW_READ)) { 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fds[i].revents |= POLLNVAL | POLLERR; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EBADF; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_warn(NULL, "attempted POLLIN on fd without READ access"); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[_index].mutex); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) triggered = -1; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto poll_exit; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((fds[i].events & POLLOUT) && (poll_fd[_index].rw != RW_WRITE)) { 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fds[i].revents |= POLLNVAL | POLLERR; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EBADF; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_warn(NULL, "attempted POLLOUT on fd without WRITE access"); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[_index].mutex); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) triggered = -1; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto poll_exit; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The following macro only works if overlapped I/O was reported pending 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( (HasOverlappedIoCompleted(poll_fd[_index].overlapped)) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) || (HasOverlappedIoCompletedSync(poll_fd[_index].overlapped)) ) { 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_dbg(" completed"); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // checks above should ensure this works: 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fds[i].revents = fds[i].events; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) triggered++; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handles_to_wait_on[nb_handles_to_wait_on] = poll_fd[_index].overlapped->hEvent; 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_to_index[nb_handles_to_wait_on] = i; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nb_handles_to_wait_on++; 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[_index].mutex); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If nothing was triggered, wait on all fds that require it 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((timeout != 0) && (triggered == 0) && (nb_handles_to_wait_on != 0)) { 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (timeout < 0) { 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_dbg("starting infinite wait for %d handles...", (int)nb_handles_to_wait_on); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_dbg("starting %d ms wait for %d handles...", timeout, (int)nb_handles_to_wait_on); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = WaitForMultipleObjects(nb_handles_to_wait_on, handles_to_wait_on, 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FALSE, (timeout<0)?INFINITE:(DWORD)timeout); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_index = ret-WAIT_OBJECT_0; 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((object_index >= 0) && ((DWORD)object_index < nb_handles_to_wait_on)) { 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_dbg(" completed after wait"); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = handle_to_index[object_index]; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _index = _fd_to_index_and_lock(fds[i].fd); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fds[i].revents = fds[i].events; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) triggered++; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (_index >= 0) { 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[_index].mutex); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (ret == WAIT_TIMEOUT) { 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_dbg(" timed out"); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) triggered = 0; // 0 = timeout 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EIO; 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) triggered = -1; // error 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)poll_exit: 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handles_to_wait_on != NULL) { 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(handles_to_wait_on); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (handle_to_index != NULL) { 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free(handle_to_index); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return triggered; 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * close a fake pipe fd 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int usbi_close(int fd) 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int _index; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r = -1; 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_INIT_POLLING; 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _index = _fd_to_index_and_lock(fd); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (_index < 0) { 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EBADF; 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 641ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch free_overlapped(poll_fd[_index].overlapped); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_fd[_index] = INVALID_WINFD; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[_index].mutex); 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return r; 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * synchronous write for fake "pipe" signaling 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssize_t usbi_write(int fd, const void *buf, size_t count) 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int _index; 654ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UNUSED(buf); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_INIT_POLLING; 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count != sizeof(unsigned char)) { 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err(NULL, "this function should only used for signaling"); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _index = _fd_to_index_and_lock(fd); 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( (_index < 0) || (poll_fd[_index].overlapped == NULL) ) { 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EBADF; 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (_index >= 0) { 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[_index].mutex); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_dbg("set pipe event (fd = %d, thread = %08X)", _index, GetCurrentThreadId()); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetEvent(poll_fd[_index].overlapped->hEvent); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_fd[_index].overlapped->Internal = STATUS_WAIT_0; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If two threads write on the pipe at the same time, we need to 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process two separate reads => use the overlapped as a counter 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_fd[_index].overlapped->InternalHigh++; 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[_index].mutex); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sizeof(unsigned char); 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * synchronous read for fake "pipe" signaling 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssize_t usbi_read(int fd, void *buf, size_t count) 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int _index; 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssize_t r = -1; 691ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch UNUSED(buf); 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_INIT_POLLING; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (count != sizeof(unsigned char)) { 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_err(NULL, "this function should only used for signaling"); 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _index = _fd_to_index_and_lock(fd); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (_index < 0) { 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EBADF; 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (WaitForSingleObject(poll_fd[_index].overlapped->hEvent, INFINITE) != WAIT_OBJECT_0) { 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usbi_warn(NULL, "waiting for event failed: %d", (int)GetLastError()); 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EIO; 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto out; 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_dbg("clr pipe event (fd = %d, thread = %08X)", _index, GetCurrentThreadId()); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_fd[_index].overlapped->InternalHigh--; 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't reset unless we don't have any more events to process 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (poll_fd[_index].overlapped->InternalHigh <= 0) { 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResetEvent(poll_fd[_index].overlapped->hEvent); 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) poll_fd[_index].overlapped->Internal = STATUS_PENDING; 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = sizeof(unsigned char); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)out: 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LeaveCriticalSection(&_poll_fd[_index].mutex); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return r; 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 727