Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(478)

Unified Diff: third_party/libusb/src/libusb/os/poll_windows.c

Issue 19490008: Recommit: Update libusb 1.0.9 to libusbx 1.0.16 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/libusb/src/libusb/os/poll_windows.h ('k') | third_party/libusb/src/libusb/os/threads_posix.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/libusb/src/libusb/os/poll_windows.c
diff --git a/third_party/libusb/src/libusb/os/poll_windows.c b/third_party/libusb/src/libusb/os/poll_windows.c
index 7f4d9c4e7e94def7a91a16624d16582a9f539a94..7ed19ba324f980658ae0940c88b9042e613b94ef 100644
--- a/third_party/libusb/src/libusb/os/poll_windows.c
+++ b/third_party/libusb/src/libusb/os/poll_windows.c
@@ -1,6 +1,7 @@
/*
* poll_windows: poll compatibility wrapper for Windows
- * Copyright (C) 2009-2010 Pete Batard <pbatard@gmail.com>
+ * Copyright © 2012-2013 RealVNC Ltd.
+ * Copyright © 2009-2010 Pete Batard <pete@akeo.ie>
* With contributions from Michael Plante, Orin Eman et al.
* Parts of poll implementation from libusb-win32, by Stephan Meyer et al.
*
@@ -21,7 +22,7 @@
*/
/*
- * poll() and pipe() Windows compatibility layer for libusb 1.0
+ * poll() and pipe() Windows compatibility layer for libusbx 1.0
*
* The way this layer works is by using OVERLAPPED with async I/O transfers, as
* OVERLAPPED have an associated event which is flagged for I/O completion.
@@ -31,7 +32,7 @@
* OVERLAPPED mode
* - call usbi_create_fd with this handle to obtain a custom fd.
* Note that if you need simultaneous R/W access, you need to call create_fd
- * twice, once in _O_RDONLY and once in _O_WRONLY mode to obtain 2 separate
+ * twice, once in RW_READ and once in RW_WRITE mode to obtain 2 separate
* pollable fds
* - leave the core functions call the poll routine and flag POLLIN/POLLOUT
*
@@ -40,12 +41,10 @@
* context.
*/
#include <errno.h>
-#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
-#include <io.h>
-#include <libusbi.h>
+#include "libusbi.h"
// Uncomment to debug the polling layer
//#define DEBUG_POLL_WINDOWS
@@ -53,8 +52,8 @@
#define poll_dbg usbi_dbg
#else
// MSVC++ < 2005 cannot use a variadic argument and non MSVC
-// compilers produce warnings if parenthesis are omitted.
-#if defined(_MSC_VER) && _MSC_VER < 1400
+// compilers produce warnings if parenthesis are ommitted.
+#if defined(_MSC_VER) && (_MSC_VER < 1400)
#define poll_dbg
#else
#define poll_dbg(...)
@@ -65,20 +64,10 @@
#pragma warning(disable:28719)
#endif
-#if defined(__CYGWIN__)
-// cygwin produces a warning unless these prototypes are defined
-extern int _open(char* name, int flags);
-extern int _close(int fd);
-extern int _snprintf(char *buffer, size_t count, const char *format, ...);
-#define NUL_DEVICE "/dev/null"
-#else
-#define NUL_DEVICE "NUL"
-#endif
-
#define CHECK_INIT_POLLING do {if(!is_polling_set) init_polling();} while(0)
// public fd data
-const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, RW_NONE};
+const struct winfd INVALID_WINFD = {-1, INVALID_HANDLE_VALUE, NULL, NULL, NULL, RW_NONE};
struct winfd poll_fd[MAX_FDS];
// internal fd data
struct {
@@ -93,12 +82,25 @@ BOOLEAN is_polling_set = FALSE;
LONG pipe_number = 0;
static volatile LONG compat_spinlock = 0;
+#if !defined(_WIN32_WCE)
// CancelIoEx, available on Vista and later only, provides the ability to cancel
// a single transfer (OVERLAPPED) when used. As it may not be part of any of the
// platform headers, we hook into the Kernel32 system DLL directly to seek it.
static BOOL (__stdcall *pCancelIoEx)(HANDLE, LPOVERLAPPED) = NULL;
-#define CancelIoEx_Available (pCancelIoEx != NULL)
-static __inline BOOL cancel_io(int _index)
+#define Use_Duplicate_Handles (pCancelIoEx == NULL)
+
+static inline void setup_cancel_io(void)
+{
+ HMODULE hKernel32 = GetModuleHandleA("KERNEL32");
+ if (hKernel32 != NULL) {
+ pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
+ GetProcAddress(hKernel32, "CancelIoEx");
+ }
+ usbi_dbg("Will use CancelIo%s for I/O cancellation",
+ Use_Duplicate_Handles?"":"Ex");
+}
+
+static inline BOOL cancel_io(int _index)
{
if ((_index < 0) || (_index >= MAX_FDS)) {
return FALSE;
@@ -108,7 +110,12 @@ static __inline BOOL cancel_io(int _index)
|| (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
return TRUE;
}
- if (CancelIoEx_Available) {
+ if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
+ // Cancel outstanding transfer via the specific callback
+ (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
+ return TRUE;
+ }
+ if (pCancelIoEx != NULL) {
return (*pCancelIoEx)(poll_fd[_index].handle, poll_fd[_index].overlapped);
}
if (_poll_fd[_index].thread_id == GetCurrentThreadId()) {
@@ -117,6 +124,30 @@ static __inline BOOL cancel_io(int _index)
usbi_warn(NULL, "Unable to cancel I/O that was started from another thread");
return FALSE;
}
+#else
+#define Use_Duplicate_Handles FALSE
+
+static __inline void setup_cancel_io()
+{
+ // No setup needed on WinCE
+}
+
+static __inline BOOL cancel_io(int _index)
+{
+ if ((_index < 0) || (_index >= MAX_FDS)) {
+ return FALSE;
+ }
+ if ( (poll_fd[_index].fd < 0) || (poll_fd[_index].handle == INVALID_HANDLE_VALUE)
+ || (poll_fd[_index].handle == 0) || (poll_fd[_index].overlapped == NULL) ) {
+ return TRUE;
+ }
+ if (poll_fd[_index].itransfer && poll_fd[_index].cancel_fn) {
+ // Cancel outstanding transfer via the specific callback
+ (*poll_fd[_index].cancel_fn)(poll_fd[_index].itransfer);
+ }
+ return TRUE;
+}
+#endif
// Init
void init_polling(void)
@@ -127,10 +158,7 @@ void init_polling(void)
SleepEx(0, TRUE);
}
if (!is_polling_set) {
- pCancelIoEx = (BOOL (__stdcall *)(HANDLE,LPOVERLAPPED))
- GetProcAddress(GetModuleHandleA("KERNEL32"), "CancelIoEx");
- usbi_dbg("Will use CancelIo%s for I/O cancellation",
- CancelIoEx_Available?"Ex":"");
+ setup_cancel_io();
for (i=0; i<MAX_FDS; i++) {
poll_fd[i] = INVALID_WINFD;
_poll_fd[i].original_handle = INVALID_HANDLE_VALUE;
@@ -139,15 +167,15 @@ void init_polling(void)
}
is_polling_set = TRUE;
}
- compat_spinlock = 0;
+ InterlockedExchange((LONG *)&compat_spinlock, 0);
}
// Internal function to retrieve the table index (and lock the fd mutex)
-int _fd_to_index_and_lock(int fd)
+static int _fd_to_index_and_lock(int fd)
{
int i;
- if (fd <= 0)
+ if (fd < 0)
return -1;
for (i=0; i<MAX_FDS; i++) {
@@ -164,7 +192,7 @@ int _fd_to_index_and_lock(int fd)
return -1;
}
-OVERLAPPED *create_overlapped(void)
+static OVERLAPPED *create_overlapped(void)
{
OVERLAPPED *overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED));
if (overlapped == NULL) {
@@ -178,7 +206,7 @@ OVERLAPPED *create_overlapped(void)
return overlapped;
}
-void free_overlapped(OVERLAPPED *overlapped)
+static void free_overlapped(OVERLAPPED *overlapped)
{
if (overlapped == NULL)
return;
@@ -190,20 +218,6 @@ void free_overlapped(OVERLAPPED *overlapped)
free(overlapped);
}
-void reset_overlapped(OVERLAPPED *overlapped)
-{
- HANDLE event_handle;
- if (overlapped == NULL)
- return;
-
- event_handle = overlapped->hEvent;
- if (event_handle != NULL) {
- ResetEvent(event_handle);
- }
- memset(overlapped, 0, sizeof(OVERLAPPED));
- overlapped->hEvent = event_handle;
-}
-
void exit_polling(void)
{
int i;
@@ -221,12 +235,8 @@ void exit_polling(void)
// terminating, and we should be able to access the fd
// mutex lock before too long
EnterCriticalSection(&_poll_fd[i].mutex);
- if ( (poll_fd[i].fd > 0) && (poll_fd[i].handle != INVALID_HANDLE_VALUE) && (poll_fd[i].handle != 0)
- && (GetFileType(poll_fd[i].handle) == FILE_TYPE_UNKNOWN) ) {
- _close(poll_fd[i].fd);
- }
free_overlapped(poll_fd[i].overlapped);
- if (!CancelIoEx_Available) {
+ if (Use_Duplicate_Handles) {
// Close duplicate handle
if (_poll_fd[i].original_handle != INVALID_HANDLE_VALUE) {
CloseHandle(poll_fd[i].handle);
@@ -237,12 +247,12 @@ void exit_polling(void)
DeleteCriticalSection(&_poll_fd[i].mutex);
}
}
- compat_spinlock = 0;
+ InterlockedExchange((LONG *)&compat_spinlock, 0);
}
/*
* Create a fake pipe.
- * As libusb only uses pipes for signaling, all we need from a pipe is an
+ * As libusbx only uses pipes for signaling, all we need from a pipe is an
* event. To that extent, we create a single wfd and overlapped as a means
* to access that event.
*/
@@ -253,7 +263,8 @@ int usbi_pipe(int filedes[2])
CHECK_INIT_POLLING;
- overlapped = (OVERLAPPED*) calloc(1, sizeof(OVERLAPPED));
+ overlapped = create_overlapped();
+
if (overlapped == NULL) {
return -1;
}
@@ -261,22 +272,6 @@ int usbi_pipe(int filedes[2])
overlapped->Internal = STATUS_PENDING;
overlapped->InternalHigh = 0;
- // Read end of the "pipe"
- filedes[0] = _open(NUL_DEVICE, _O_WRONLY);
- if (filedes[0] < 0) {
- usbi_err(NULL, "could not create pipe: errno %d", errno);
- goto out1;
- }
- // We can use the same handle for both ends
- filedes[1] = filedes[0];
- poll_dbg("pipe filedes = %d", filedes[0]);
-
- // Note: manual reset must be true (second param) as the reset occurs in read
- overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if(!overlapped->hEvent) {
- goto out2;
- }
-
for (i=0; i<MAX_FDS; i++) {
if (poll_fd[i].fd < 0) {
EnterCriticalSection(&_poll_fd[i].mutex);
@@ -286,7 +281,13 @@ int usbi_pipe(int filedes[2])
continue;
}
- poll_fd[i].fd = filedes[0];
+ // Use index as the unique fd number
+ poll_fd[i].fd = i;
+ // Read end of the "pipe"
+ filedes[0] = poll_fd[i].fd;
+ // We can use the same handle for both ends
+ filedes[1] = filedes[0];
+
poll_fd[i].handle = DUMMY_HANDLE;
poll_fd[i].overlapped = overlapped;
// There's no polling on the write end, so we just use READ for our needs
@@ -296,12 +297,7 @@ int usbi_pipe(int filedes[2])
return 0;
}
}
-
- CloseHandle(overlapped->hEvent);
-out2:
- _close(filedes[0]);
-out1:
- free(overlapped);
+ free_overlapped(overlapped);
return -1;
}
@@ -319,9 +315,9 @@ out1:
* read and one for write. Using a single R/W fd is unsupported and will
* produce unexpected results
*/
-struct winfd usbi_create_fd(HANDLE handle, int access_mode)
+struct winfd usbi_create_fd(HANDLE handle, int access_mode, struct usbi_transfer *itransfer, cancel_transfer *cancel_fn)
{
- int i, fd;
+ int i;
struct winfd wfd = INVALID_WINFD;
OVERLAPPED* overlapped = NULL;
@@ -331,27 +327,22 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode)
return INVALID_WINFD;
}
- if ((access_mode != _O_RDONLY) && (access_mode != _O_WRONLY)) {
- usbi_warn(NULL, "only one of _O_RDONLY or _O_WRONLY are supported.\n"
+ wfd.itransfer = itransfer;
+ wfd.cancel_fn = cancel_fn;
+
+ if ((access_mode != RW_READ) && (access_mode != RW_WRITE)) {
+ usbi_warn(NULL, "only one of RW_READ or RW_WRITE are supported.\n"
"If you want to poll for R/W simultaneously, create multiple fds from the same handle.");
return INVALID_WINFD;
}
- if (access_mode == _O_RDONLY) {
+ if (access_mode == RW_READ) {
wfd.rw = RW_READ;
} else {
wfd.rw = RW_WRITE;
}
- // Ensure that we get a non system conflicting unique fd, using
- // the same fd attribution system as the pipe ends
- fd = _open(NUL_DEVICE, _O_WRONLY);
- if (fd < 0) {
- return INVALID_WINFD;
- }
-
overlapped = create_overlapped();
if(overlapped == NULL) {
- _close(fd);
return INVALID_WINFD;
}
@@ -363,10 +354,11 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode)
LeaveCriticalSection(&_poll_fd[i].mutex);
continue;
}
- wfd.fd = fd;
+ // Use index as the unique fd number
+ wfd.fd = i;
// Attempt to emulate some of the CancelIoEx behaviour on platforms
// that don't have it
- if (!CancelIoEx_Available) {
+ if (Use_Duplicate_Handles) {
_poll_fd[i].thread_id = GetCurrentThreadId();
if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
&wfd.handle, 0, TRUE, DUPLICATE_SAME_ACCESS)) {
@@ -387,21 +379,15 @@ struct winfd usbi_create_fd(HANDLE handle, int access_mode)
}
}
free_overlapped(overlapped);
- _close(fd);
return INVALID_WINFD;
}
-void _free_index(int _index)
+static void _free_index(int _index)
{
// Cancel any async IO (Don't care about the validity of our handles for this)
cancel_io(_index);
- // close fake handle for devices
- if ( (poll_fd[_index].handle != INVALID_HANDLE_VALUE) && (poll_fd[_index].handle != 0)
- && (GetFileType(poll_fd[_index].handle) == FILE_TYPE_UNKNOWN) ) {
- _close(poll_fd[_index].fd);
- }
// close the duplicate handle (if we have an actual duplicate)
- if (!CancelIoEx_Available) {
+ if (Use_Duplicate_Handles) {
if (_poll_fd[_index].original_handle != INVALID_HANDLE_VALUE) {
CloseHandle(poll_fd[_index].handle);
}
@@ -417,17 +403,18 @@ void _free_index(int _index)
*
* Note that the associated Windows handle is not closed by this call
*/
-void usbi_free_fd(int fd)
+void usbi_free_fd(struct winfd *wfd)
{
int _index;
CHECK_INIT_POLLING;
- _index = _fd_to_index_and_lock(fd);
+ _index = _fd_to_index_and_lock(wfd->fd);
if (_index < 0) {
return;
}
_free_index(_index);
+ *wfd = INVALID_WINFD;
LeaveCriticalSection(&_poll_fd[_index].mutex);
}
@@ -651,15 +638,7 @@ int usbi_close(int fd)
if (_index < 0) {
errno = EBADF;
} else {
- if (poll_fd[_index].overlapped != NULL) {
- // Must be a different event for each end of the pipe
- CloseHandle(poll_fd[_index].overlapped->hEvent);
- free(poll_fd[_index].overlapped);
- }
- r = _close(poll_fd[_index].fd);
- if (r != 0) {
- errno = EIO;
- }
+ free_overlapped(poll_fd[_index].overlapped);
poll_fd[_index] = INVALID_WINFD;
LeaveCriticalSection(&_poll_fd[_index].mutex);
}
@@ -672,6 +651,7 @@ int usbi_close(int fd)
ssize_t usbi_write(int fd, const void *buf, size_t count)
{
int _index;
+ UNUSED(buf);
CHECK_INIT_POLLING;
@@ -708,6 +688,7 @@ ssize_t usbi_read(int fd, void *buf, size_t count)
{
int _index;
ssize_t r = -1;
+ UNUSED(buf);
CHECK_INIT_POLLING;
« no previous file with comments | « third_party/libusb/src/libusb/os/poll_windows.h ('k') | third_party/libusb/src/libusb/os/threads_posix.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698