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