15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Windows compat: POSIX compatibility wrapper 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)#pragma once 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_MSC_VER) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// disable /W4 MSVC warnings that are benign 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(disable:4127) // conditional expression is constant 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handle synchronous completion through the overlapped structure 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(STATUS_REPARSE) // reuse the REPARSE status code 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define STATUS_REPARSE ((LONG)0x00000104L) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define STATUS_COMPLETED_SYNCHRONOUSLY STATUS_REPARSE 35ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(_WIN32_WCE) 36ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// WinCE doesn't have a HasOverlappedIoCompleted() macro, so attempt to emulate it 37ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#define HasOverlappedIoCompleted(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) != STATUS_PENDING) 38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HasOverlappedIoCompletedSync(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) == STATUS_COMPLETED_SYNCHRONOUSLY) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum windows_version { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WINDOWS_UNSUPPORTED, 45ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch WINDOWS_CE, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WINDOWS_XP, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WINDOWS_2003, // also includes XP 64 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WINDOWS_VISTA_AND_LATER, 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern enum windows_version windows_version; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_FDS 256 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define POLLIN 0x0001 /* There is data to read */ 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define POLLPRI 0x0002 /* There is urgent data to read */ 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define POLLOUT 0x0004 /* Writing now will not block */ 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define POLLERR 0x0008 /* Error condition */ 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define POLLHUP 0x0010 /* Hung up */ 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define POLLNVAL 0x0020 /* Invalid request: fd not open */ 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstruct pollfd { 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int fd; /* file descriptor */ 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch short events; /* requested events */ 64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch short revents; /* returned events */ 65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// access modes 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum rw_type { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RW_NONE, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RW_READ, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RW_WRITE, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fd struct that can be used for polling on Windows 75ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochtypedef int cancel_transfer(struct usbi_transfer *itransfer); 76ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winfd { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd; // what's exposed to libusb core 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HANDLE handle; // what we need to attach overlapped to the I/O op, so we can poll it 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OVERLAPPED* overlapped; // what will report our I/O status 81ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct usbi_transfer *itransfer; // Associated transfer, or NULL if completed 82ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch cancel_transfer *cancel_fn; // Function pointer to cancel transfer API 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum rw_type rw; // I/O transfer direction: read *XOR* write (NOT BOTH) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const struct winfd INVALID_WINFD; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int usbi_pipe(int pipefd[2]); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int usbi_poll(struct pollfd *fds, unsigned int nfds, int timeout); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssize_t usbi_write(int fd, const void *buf, size_t count); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssize_t usbi_read(int fd, void *buf, size_t count); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int usbi_close(int fd); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void init_polling(void); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void exit_polling(void); 95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstruct winfd usbi_create_fd(HANDLE handle, int access_mode, 96ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch struct usbi_transfer *transfer, cancel_transfer *cancel_fn); 97ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid usbi_free_fd(struct winfd* winfd); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winfd fd_to_winfd(int fd); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winfd handle_to_winfd(HANDLE handle); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winfd overlapped_to_winfd(OVERLAPPED* overlapped); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Timeval operations 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(DDKBUILD) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winsock.h> // defines timeval functions on DDK 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(TIMESPEC_TO_TIMEVAL) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define TIMESPEC_TO_TIMEVAL(tv, ts) { \ 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (tv)->tv_sec = (long)(ts)->tv_sec; \ 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (tv)->tv_usec = (long)(ts)->tv_nsec / 1000; \ 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(timersub) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define timersub(a, b, result) \ 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)do { \ 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((result)->tv_usec < 0) { \ 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --(result)->tv_sec; \ 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (result)->tv_usec += 1000000; \ 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } \ 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} while (0) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 126