1/* 2 * Windows compat: POSIX compatibility wrapper 3 * Copyright © 2012-2013 RealVNC Ltd. 4 * Copyright © 2009-2010 Pete Batard <pete@akeo.ie> 5 * With contributions from Michael Plante, Orin Eman et al. 6 * Parts of poll implementation from libusb-win32, by Stephan Meyer et al. 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 * 22 */ 23#pragma once 24 25#if defined(_MSC_VER) 26// disable /W4 MSVC warnings that are benign 27#pragma warning(disable:4127) // conditional expression is constant 28#endif 29 30// Handle synchronous completion through the overlapped structure 31#if !defined(STATUS_REPARSE) // reuse the REPARSE status code 32#define STATUS_REPARSE ((LONG)0x00000104L) 33#endif 34#define STATUS_COMPLETED_SYNCHRONOUSLY STATUS_REPARSE 35#if defined(_WIN32_WCE) 36// WinCE doesn't have a HasOverlappedIoCompleted() macro, so attempt to emulate it 37#define HasOverlappedIoCompleted(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) != STATUS_PENDING) 38#endif 39#define HasOverlappedIoCompletedSync(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) == STATUS_COMPLETED_SYNCHRONOUSLY) 40 41#define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2) 42 43enum windows_version { 44 WINDOWS_UNSUPPORTED, 45 WINDOWS_CE, 46 WINDOWS_XP, 47 WINDOWS_2003, // also includes XP 64 48 WINDOWS_VISTA_AND_LATER, 49}; 50extern enum windows_version windows_version; 51 52#define MAX_FDS 256 53 54#define POLLIN 0x0001 /* There is data to read */ 55#define POLLPRI 0x0002 /* There is urgent data to read */ 56#define POLLOUT 0x0004 /* Writing now will not block */ 57#define POLLERR 0x0008 /* Error condition */ 58#define POLLHUP 0x0010 /* Hung up */ 59#define POLLNVAL 0x0020 /* Invalid request: fd not open */ 60 61struct pollfd { 62 int fd; /* file descriptor */ 63 short events; /* requested events */ 64 short revents; /* returned events */ 65}; 66 67// access modes 68enum rw_type { 69 RW_NONE, 70 RW_READ, 71 RW_WRITE, 72}; 73 74// fd struct that can be used for polling on Windows 75typedef int cancel_transfer(struct usbi_transfer *itransfer); 76 77struct winfd { 78 int fd; // what's exposed to libusb core 79 HANDLE handle; // what we need to attach overlapped to the I/O op, so we can poll it 80 OVERLAPPED* overlapped; // what will report our I/O status 81 struct usbi_transfer *itransfer; // Associated transfer, or NULL if completed 82 cancel_transfer *cancel_fn; // Function pointer to cancel transfer API 83 enum rw_type rw; // I/O transfer direction: read *XOR* write (NOT BOTH) 84}; 85extern const struct winfd INVALID_WINFD; 86 87int usbi_pipe(int pipefd[2]); 88int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout); 89ssize_t usbi_write(int fd, const void *buf, size_t count); 90ssize_t usbi_read(int fd, void *buf, size_t count); 91int usbi_close(int fd); 92 93void init_polling(void); 94void exit_polling(void); 95struct winfd usbi_create_fd(HANDLE handle, int access_mode, 96 struct usbi_transfer *transfer, cancel_transfer *cancel_fn); 97void usbi_free_fd(struct winfd* winfd); 98struct winfd fd_to_winfd(int fd); 99struct winfd handle_to_winfd(HANDLE handle); 100struct winfd overlapped_to_winfd(OVERLAPPED* overlapped); 101 102/* 103 * Timeval operations 104 */ 105#if defined(DDKBUILD) 106#include <winsock.h> // defines timeval functions on DDK 107#endif 108 109#if !defined(TIMESPEC_TO_TIMEVAL) 110#define TIMESPEC_TO_TIMEVAL(tv, ts) { \ 111 (tv)->tv_sec = (long)(ts)->tv_sec; \ 112 (tv)->tv_usec = (long)(ts)->tv_nsec / 1000; \ 113} 114#endif 115#if !defined(timersub) 116#define timersub(a, b, result) \ 117do { \ 118 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ 119 (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ 120 if ((result)->tv_usec < 0) { \ 121 --(result)->tv_sec; \ 122 (result)->tv_usec += 1000000; \ 123 } \ 124} while (0) 125#endif 126