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