summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Dickens <christopher.a.dickens@gmail.com>2020-02-07 15:47:55 -0800
committerChris Dickens <christopher.a.dickens@gmail.com>2020-02-07 15:47:55 -0800
commit9c28ad219b654011783a42ec888ca87dbda704a6 (patch)
treeb789d577d5547c0d7b247d165fe52dc96f5014c8
parent67e6816264e35a1f22b43a78b4be7481652bc51a (diff)
downloadlibusb-9c28ad219b654011783a42ec888ca87dbda704a6.tar.gz
Windows: Refactoring to consolidate and simplify common code
Both the UsbDk and WinUSB backends perform common steps when handling transfers in order to interact with the poll abstraction, both during submission and when processing transfer completion. With some rearranging of shared structures, this can be yanked from the individual backends and placed in the common area. This allows for several functions to be removed outright from each backend. The cancellation logic can also be simplified by attempting CancelIoEx() at the highest level and delegating to the backend if there are alternatives to try should CancelIoEx() fail. After some analysis of how Windows processes asychronous (OVERLAPPED) requests that the underlying driver completes synchronously, it is now evident that such requests need not be handled in any special fashion. Each function that called a driver function that was expected to complete asynchronously had logic to handle the case of a synchronous completion, so this has all been killed off. This significantly cleans up these call sites as now they must only check for an error condition. Finally, the initialization code for the WinUSB backend has been reworked to load the WinUSB DLL independent of the libusbK DLL. Previously when the libusbK DLL was present, all requests to devices using WinUSB would first be sent through the libusbK DLL where they would then be forwarded to the WinUSB DLL. This is slightly inefficient but is also limiting when using Windows 8.1 or later because support for isochronous transfers through WinUSB will be lost. Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
-rw-r--r--libusb/os/poll_windows.c3
-rw-r--r--libusb/os/poll_windows.h7
-rw-r--r--libusb/os/windows_common.c268
-rw-r--r--libusb/os/windows_common.h58
-rw-r--r--libusb/os/windows_usbdk.c224
-rw-r--r--libusb/os/windows_winusb.c1215
-rw-r--r--libusb/os/windows_winusb.h158
-rw-r--r--libusb/version_nano.h2
8 files changed, 829 insertions, 1106 deletions
diff --git a/libusb/os/poll_windows.c b/libusb/os/poll_windows.c
index f735245..490ee7f 100644
--- a/libusb/os/poll_windows.c
+++ b/libusb/os/poll_windows.c
@@ -392,8 +392,7 @@ int usbi_poll(struct pollfd *fds, usbi_nfds_t nfds, int timeout)
if (fd == NULL) {
fds[n].revents = POLLNVAL;
nready++;
- } else if (HasOverlappedIoCompleted(&fd->overlapped) &&
- (WaitForSingleObject(fd->overlapped.hEvent, 0) == WAIT_OBJECT_0)) {
+ } else if (HasOverlappedIoCompleted(&fd->overlapped)) {
fds[n].revents = fds[n].events;
nready++;
} else {
diff --git a/libusb/os/poll_windows.h b/libusb/os/poll_windows.h
index b2c94f9..a38e1da 100644
--- a/libusb/os/poll_windows.h
+++ b/libusb/os/poll_windows.h
@@ -25,13 +25,6 @@
#ifndef LIBUSB_POLL_WINDOWS_H
#define LIBUSB_POLL_WINDOWS_H
-// Handle synchronous completion through the overlapped structure
-#if !defined(STATUS_REPARSE) // reuse the REPARSE status code
-#define STATUS_REPARSE ((LONG)0x00000104L)
-#endif
-#define STATUS_COMPLETED_SYNCHRONOUSLY STATUS_REPARSE
-#define HasOverlappedIoCompletedSync(lpOverlapped) (((DWORD)(lpOverlapped)->Internal) == STATUS_COMPLETED_SYNCHRONOUSLY)
-
#define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2)
#define POLLIN 0x0001 /* There is data to read */
diff --git a/libusb/os/windows_common.c b/libusb/os/windows_common.c
index a2c9beb..3a11c56 100644
--- a/libusb/os/windows_common.c
+++ b/libusb/os/windows_common.c
@@ -33,12 +33,14 @@
#define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime
+#define STATUS_SUCCESS ((ULONG_PTR)0UL)
+
// Public
enum windows_version windows_version = WINDOWS_UNDEFINED;
// Global variables for init/exit
-static unsigned int init_count = 0;
-static bool usbdk_available = false;
+static unsigned int init_count;
+static bool usbdk_available;
// Global variables for clock_gettime mechanism
static uint64_t hires_ticks_to_ps;
@@ -114,7 +116,7 @@ typedef struct htab_entry {
char *str;
} htab_entry;
-static htab_entry *htab_table = NULL;
+static htab_entry *htab_table;
static usbi_mutex_t htab_mutex;
static unsigned long htab_filled;
@@ -125,7 +127,7 @@ static unsigned long htab_filled;
static bool htab_create(struct libusb_context *ctx)
{
if (htab_table != NULL) {
- usbi_err(ctx, "hash table already allocated");
+ usbi_err(ctx, "program assertion falied - hash table already allocated");
return true;
}
@@ -173,7 +175,7 @@ unsigned long htab_hash(const char *str)
{
unsigned long hval, hval2;
unsigned long idx;
- unsigned long r = 5381;
+ unsigned long r = 5381UL;
int c;
const char *sz = str;
@@ -204,7 +206,7 @@ unsigned long htab_hash(const char *str)
usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str);
// Second hash function, as suggested in [Knuth]
- hval2 = 1 + hval % (HTAB_SIZE - 2);
+ hval2 = 1UL + hval % (HTAB_SIZE - 2);
do {
// Because size is prime this guarantees to step through all available indexes
@@ -228,14 +230,14 @@ unsigned long htab_hash(const char *str)
// If the table is full return an error
if (htab_filled >= HTAB_SIZE) {
usbi_err(NULL, "hash table is full (%lu entries)", HTAB_SIZE);
- idx = 0;
+ idx = 0UL;
goto out_unlock;
}
htab_table[idx].str = _strdup(str);
if (htab_table[idx].str == NULL) {
usbi_err(NULL, "could not duplicate string for hash table");
- idx = 0;
+ idx = 0UL;
goto out_unlock;
}
@@ -248,13 +250,33 @@ out_unlock:
return idx;
}
+enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status)
+{
+ if (USBD_SUCCESS(status))
+ return LIBUSB_TRANSFER_COMPLETED;
+
+ switch (status) {
+ case USBD_STATUS_TIMEOUT:
+ return LIBUSB_TRANSFER_TIMED_OUT;
+ case USBD_STATUS_CANCELED:
+ return LIBUSB_TRANSFER_CANCELLED;
+ case USBD_STATUS_ENDPOINT_HALTED:
+ return LIBUSB_TRANSFER_STALL;
+ case USBD_STATUS_DEVICE_GONE:
+ return LIBUSB_TRANSFER_NO_DEVICE;
+ default:
+ usbi_dbg("USBD_STATUS 0x%08lx translated to LIBUSB_TRANSFER_ERROR", ULONG_CAST(status));
+ return LIBUSB_TRANSFER_ERROR;
+ }
+}
+
/*
* Make a transfer complete synchronously
*/
void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size)
{
- overlapped->Internal = STATUS_COMPLETED_SYNCHRONOUSLY;
- overlapped->InternalHigh = size;
+ overlapped->Internal = (ULONG_PTR)STATUS_SUCCESS;
+ overlapped->InternalHigh = (ULONG_PTR)size;
SetEvent(overlapped->hEvent);
}
@@ -294,7 +316,7 @@ static void get_windows_version(void)
const char *arch, *w = NULL;
unsigned major, minor, version;
ULONGLONG major_equal, minor_equal;
- BOOL ws;
+ bool ws;
windows_version = WINDOWS_UNDEFINED;
@@ -378,16 +400,17 @@ static void get_windows_version(void)
}
static void windows_transfer_callback(const struct windows_backend *backend,
- struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size)
+ struct usbi_transfer *itransfer, DWORD error, DWORD bytes_transferred)
{
- int status, istatus;
+ struct windows_transfer_priv *transfer_priv = get_transfer_priv(itransfer);
+ enum libusb_transfer_status status, istatus;
- usbi_dbg("handling I/O completion with errcode %lu, size %lu",
- ULONG_CAST(io_result), ULONG_CAST(io_size));
+ usbi_dbg("handling I/O completion with errcode %lu, length %lu",
+ ULONG_CAST(error), ULONG_CAST(bytes_transferred));
- switch (io_result) {
+ switch (error) {
case NO_ERROR:
- status = backend->copy_transfer_data(itransfer, (uint32_t)io_size);
+ status = backend->copy_transfer_data(itransfer, bytes_transferred);
break;
case ERROR_GEN_FAILURE:
usbi_dbg("detected endpoint stall");
@@ -398,9 +421,9 @@ static void windows_transfer_callback(const struct windows_backend *backend,
status = LIBUSB_TRANSFER_TIMED_OUT;
break;
case ERROR_OPERATION_ABORTED:
- istatus = backend->copy_transfer_data(itransfer, (uint32_t)io_size);
+ istatus = backend->copy_transfer_data(itransfer, bytes_transferred);
if (istatus != LIBUSB_TRANSFER_COMPLETED)
- usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus);
+ usbi_dbg("failed to copy partial data in aborted operation: %d", (int)istatus);
usbi_dbg("detected operation aborted");
status = LIBUSB_TRANSFER_CANCELLED;
@@ -412,57 +435,45 @@ static void windows_transfer_callback(const struct windows_backend *backend,
break;
default:
usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %lu: %s",
- ULONG_CAST(io_result), windows_error_str(io_result));
+ ULONG_CAST(error), windows_error_str(error));
status = LIBUSB_TRANSFER_ERROR;
break;
}
- backend->clear_transfer_priv(itransfer); // Cancel polling
+
+ // Cancel polling
+ usbi_close(transfer_priv->pollable_fd.fd);
+ transfer_priv->pollable_fd = INVALID_WINFD;
+ transfer_priv->handle = NULL;
+
+ // Backend-specific cleanup
+ backend->clear_transfer_priv(itransfer);
+
if (status == LIBUSB_TRANSFER_CANCELLED)
usbi_handle_transfer_cancellation(itransfer);
else
- usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status);
-}
-
-static void windows_handle_callback(const struct windows_backend *backend,
- struct usbi_transfer *itransfer, DWORD io_result, DWORD io_size)
-{
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-
- switch (transfer->type) {
- case LIBUSB_TRANSFER_TYPE_CONTROL:
- case LIBUSB_TRANSFER_TYPE_BULK:
- case LIBUSB_TRANSFER_TYPE_INTERRUPT:
- case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
- windows_transfer_callback(backend, itransfer, io_result, io_size);
- break;
- case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
- usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform");
- break;
- default:
- usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
- }
+ usbi_handle_transfer_completion(itransfer, status);
}
static int windows_init(struct libusb_context *ctx)
{
struct windows_context_priv *priv = _context_priv(ctx);
- HANDLE semaphore;
- char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
+ char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
+ HANDLE mutex;
int r = LIBUSB_ERROR_OTHER;
bool winusb_backend_init = false;
- sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
- semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
- if (semaphore == NULL) {
- usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0));
+ sprintf(mutex_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFFU));
+ mutex = CreateMutexA(NULL, FALSE, mutex_name);
+ if (mutex == NULL) {
+ usbi_err(ctx, "could not create mutex: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_MEM;
}
- // A successful wait brings our semaphore count to 0 (unsignaled)
- // => any concurent wait stalls until the semaphore's release
- if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
- usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0));
- CloseHandle(semaphore);
+ // A successful wait gives this thread ownership of the mutex
+ // => any concurent wait stalls until the mutex is released
+ if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
+ usbi_err(ctx, "failure to access mutex: %s", windows_error_str(0));
+ CloseHandle(mutex);
return LIBUSB_ERROR_NO_MEM;
}
@@ -511,26 +522,26 @@ init_exit: // Holds semaphore here
--init_count;
}
- ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
- CloseHandle(semaphore);
+ ReleaseMutex(mutex);
+ CloseHandle(mutex);
return r;
}
static void windows_exit(struct libusb_context *ctx)
{
- HANDLE semaphore;
- char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
- UNUSED(ctx);
+ char mutex_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
+ HANDLE mutex;
- sprintf(sem_name, "libusb_init%08lX", (GetCurrentProcessId() & 0xFFFFFFFFUL));
- semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name);
- if (semaphore == NULL)
+ sprintf(mutex_name, "libusb_init%08lX", (GetCurrentProcessId() & 0xFFFFFFFFU));
+ mutex = CreateMutexA(NULL, FALSE, mutex_name);
+ if (mutex == NULL)
return;
- // A successful wait brings our semaphore count to 0 (unsignaled)
- // => any concurent wait stalls until the semaphore release
- if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) {
- CloseHandle(semaphore);
+ // A successful wait gives this thread ownership of the mutex
+ // => any concurent wait stalls until the mutex is released
+ if (WaitForSingleObject(mutex, INFINITE) != WAIT_OBJECT_0) {
+ usbi_err(ctx, "failed to access mutex: %s", windows_error_str(0));
+ CloseHandle(mutex);
return;
}
@@ -544,8 +555,8 @@ static void windows_exit(struct libusb_context *ctx)
htab_destroy();
}
- ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
- CloseHandle(semaphore);
+ ReleaseMutex(mutex);
+ CloseHandle(mutex);
}
static int windows_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
@@ -567,7 +578,6 @@ static int windows_set_option(struct libusb_context *ctx, enum libusb_option opt
default:
return LIBUSB_ERROR_NOT_SUPPORTED;
}
-
}
static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
@@ -671,29 +681,103 @@ static void windows_destroy_device(struct libusb_device *dev)
static int windows_submit_transfer(struct usbi_transfer *itransfer)
{
- struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer));
- return priv->backend->submit_transfer(itransfer);
+ struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
+ struct libusb_context *ctx = TRANSFER_CTX(transfer);
+ struct windows_context_priv *priv = _context_priv(ctx);
+ struct windows_transfer_priv *transfer_priv = get_transfer_priv(itransfer);
+ short events;
+ int r;
+
+ switch (transfer->type) {
+ case LIBUSB_TRANSFER_TYPE_CONTROL:
+ events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT;
+ break;
+ case LIBUSB_TRANSFER_TYPE_BULK:
+ case LIBUSB_TRANSFER_TYPE_INTERRUPT:
+ case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
+ events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
+ break;
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
+ usbi_warn(ctx, "bulk stream transfers are not yet supported on this platform");
+ return LIBUSB_ERROR_NOT_SUPPORTED;
+ default:
+ usbi_err(ctx, "unknown endpoint type %d", transfer->type);
+ return LIBUSB_ERROR_INVALID_PARAM;
+ }
+
+ // Because a Windows OVERLAPPED is used for poll emulation,
+ // a pollable fd is created and stored with each transfer
+ transfer_priv->pollable_fd = usbi_create_fd();
+ if (transfer_priv->pollable_fd.fd < 0) {
+ usbi_err(ctx, "failed to create pollable fd");
+ return LIBUSB_ERROR_NO_MEM;
+ }
+
+ if (transfer_priv->handle != NULL) {
+ usbi_err(ctx, "program assertion failed - transfer HANDLE is not NULL");
+ transfer_priv->handle = NULL;
+ }
+
+ r = priv->backend->submit_transfer(itransfer);
+ if (r != LIBUSB_SUCCESS) {
+ // Always call the backend's clear_transfer_priv() function on failure
+ priv->backend->clear_transfer_priv(itransfer);
+ // Release the pollable fd since it won't be used
+ usbi_close(transfer_priv->pollable_fd.fd);
+ transfer_priv->pollable_fd = INVALID_WINFD;
+ transfer_priv->handle = NULL;
+ return r;
+ }
+
+ // The backend should set the HANDLE used for each submitted transfer
+ // by calling set_transfer_priv_handle()
+ if (transfer_priv->handle == NULL)
+ usbi_err(ctx, "program assertion failed - transfer HANDLE is NULL after transfer was submitted");
+
+ // We don't want to start monitoring the pollable fd before the transfer
+ // has been submitted, so start monitoring it now. Note that if the
+ // usbi_add_pollfd() function fails, the user will never get notified
+ // that the transfer has completed. We don't attempt any cleanup if this
+ // happens because the transfer is already in progress and could even have
+ // completed
+ if (usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, events))
+ usbi_err(ctx, "failed to add pollable fd %d for transfer %p",
+ transfer_priv->pollable_fd.fd, transfer);
+
+ return r;
}
static int windows_cancel_transfer(struct usbi_transfer *itransfer)
{
struct windows_context_priv *priv = _context_priv(ITRANSFER_CTX(itransfer));
- return priv->backend->cancel_transfer(itransfer);
+ struct windows_transfer_priv *transfer_priv = get_transfer_priv(itransfer);
+
+ // Try CancelIoEx() on the transfer
+ // If that fails, fall back to the backend's cancel_transfer()
+ // function if it is available
+ if (CancelIoEx(transfer_priv->handle, transfer_priv->pollable_fd.overlapped))
+ return LIBUSB_SUCCESS;
+ else if (GetLastError() == ERROR_NOT_FOUND)
+ return LIBUSB_ERROR_NOT_FOUND;
+
+ if (priv->backend->cancel_transfer)
+ return priv->backend->cancel_transfer(itransfer);
+
+ usbi_warn(ITRANSFER_CTX(itransfer), "cancellation not supported for this transfer's driver");
+ return LIBUSB_ERROR_NOT_SUPPORTED;
}
static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, usbi_nfds_t nfds, int num_ready)
{
struct windows_context_priv *priv = _context_priv(ctx);
struct usbi_transfer *itransfer;
- DWORD io_size, io_result;
+ struct windows_transfer_priv *transfer_priv;
+ DWORD result, bytes_transferred;
usbi_nfds_t i;
- bool found;
- int transfer_fd;
int r = LIBUSB_SUCCESS;
usbi_mutex_lock(&ctx->open_devs_lock);
for (i = 0; i < nfds && num_ready > 0; i++) {
-
usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents);
if (!fds[i].revents)
@@ -701,34 +785,30 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds,
num_ready--;
- // Because a Windows OVERLAPPED is used for poll emulation,
- // a pollable fd is created and stored with each transfer
- found = false;
- transfer_fd = -1;
+ transfer_priv = NULL;
usbi_mutex_lock(&ctx->flying_transfers_lock);
list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) {
- transfer_fd = priv->backend->get_transfer_fd(itransfer);
- if (transfer_fd == fds[i].fd) {
- found = true;
+ transfer_priv = get_transfer_priv(itransfer);
+ if (transfer_priv->pollable_fd.fd == fds[i].fd)
break;
- }
+ transfer_priv = NULL;
}
usbi_mutex_unlock(&ctx->flying_transfers_lock);
- if (found) {
- priv->backend->get_overlapped_result(itransfer, &io_result, &io_size);
-
- usbi_remove_pollfd(ctx, transfer_fd);
-
- // let handle_callback free the event using the transfer wfd
- // If you don't use the transfer wfd, you run a risk of trying to free a
- // newly allocated wfd that took the place of the one from the transfer.
- windows_handle_callback(priv->backend, itransfer, io_result, io_size);
- } else {
+ if (transfer_priv == NULL) {
usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i].fd);
r = LIBUSB_ERROR_NOT_FOUND;
break;
}
+
+ usbi_remove_pollfd(ctx, transfer_priv->pollable_fd.fd);
+
+ if (GetOverlappedResult(transfer_priv->handle, transfer_priv->pollable_fd.overlapped, &bytes_transferred, FALSE))
+ result = NO_ERROR;
+ else
+ result = GetLastError();
+
+ windows_transfer_callback(priv->backend, itransfer, result, bytes_transferred);
}
usbi_mutex_unlock(&ctx->open_devs_lock);
@@ -814,5 +894,5 @@ const struct usbi_os_backend usbi_backend = {
sizeof(struct windows_context_priv),
sizeof(union windows_device_priv),
sizeof(union windows_device_handle_priv),
- sizeof(union windows_transfer_priv),
+ sizeof(struct windows_transfer_priv),
};
diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h
index 93ea23e..63d3183 100644
--- a/libusb/os/windows_common.h
+++ b/libusb/os/windows_common.h
@@ -68,13 +68,13 @@
#define DLL_HANDLE_NAME(name) __dll_##name##_handle
#define DLL_DECLARE_HANDLE(name) \
- static HMODULE DLL_HANDLE_NAME(name) = NULL
+ static HMODULE DLL_HANDLE_NAME(name)
#define DLL_GET_HANDLE(name) \
do { \
DLL_HANDLE_NAME(name) = DLL_LOAD_LIBRARY(name); \
if (!DLL_HANDLE_NAME(name)) \
- return FALSE; \
+ return false; \
} while (0)
#define DLL_FREE_HANDLE(name) \
@@ -92,7 +92,7 @@
#define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args) \
typedef ret (api * DLL_FUNC_NAME(name))args; \
- static DLL_FUNC_NAME(name) prefixname = NULL
+ static DLL_FUNC_NAME(name) prefixname
#define DLL_DECLARE_FUNC(api, ret, name, args) \
DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, name, args)
@@ -115,7 +115,7 @@
if (prefixname) \
break; \
if (ret_on_failure) \
- return FALSE; \
+ return false; \
} while (0)
#define DLL_LOAD_FUNC(dll, name, ret_on_failure) \
@@ -271,16 +271,13 @@ struct winusb_device_handle_priv {
struct usbdk_transfer_priv {
USB_DK_TRANSFER_REQUEST request;
- struct winfd pollable_fd;
- HANDLE system_handle;
PULONG64 IsochronousPacketsArray;
PUSB_DK_ISO_TRANSFER_RESULT IsochronousResultsArray;
};
struct winusb_transfer_priv {
- struct winfd pollable_fd;
- HANDLE handle;
uint8_t interface_number;
+
uint8_t *hid_buffer; // 1 byte extended data buffer, required for HID
uint8_t *hid_dest; // transfer buffer destination, required for HID
size_t hid_expected_size;
@@ -322,10 +319,7 @@ struct windows_backend {
int (*submit_transfer)(struct usbi_transfer *itransfer);
int (*cancel_transfer)(struct usbi_transfer *itransfer);
void (*clear_transfer_priv)(struct usbi_transfer *itransfer);
- int (*copy_transfer_data)(struct usbi_transfer *itransfer, uint32_t io_size);
- int (*get_transfer_fd)(struct usbi_transfer *itransfer);
- void (*get_overlapped_result)(struct usbi_transfer *itransfer,
- DWORD *io_result, DWORD *io_size);
+ enum libusb_transfer_status (*copy_transfer_data)(struct usbi_transfer *itransfer, DWORD length);
};
struct windows_context_priv {
@@ -342,15 +336,49 @@ union windows_device_handle_priv {
struct winusb_device_handle_priv winusb_priv;
};
-union windows_transfer_priv {
- struct usbdk_transfer_priv usbdk_priv;
- struct winusb_transfer_priv winusb_priv;
+struct windows_transfer_priv {
+ struct winfd pollable_fd;
+ HANDLE handle;
+ union {
+ struct usbdk_transfer_priv usbdk_priv;
+ struct winusb_transfer_priv winusb_priv;
+ };
};
+static inline struct windows_transfer_priv *get_transfer_priv(struct usbi_transfer *itransfer)
+{
+ return (struct windows_transfer_priv *)usbi_transfer_get_os_priv(itransfer);
+}
+
+static inline OVERLAPPED *get_transfer_priv_overlapped(struct usbi_transfer *itransfer)
+{
+ struct windows_transfer_priv *transfer_priv = get_transfer_priv(itransfer);
+ return transfer_priv->pollable_fd.overlapped;
+}
+
+static inline void set_transfer_priv_handle(struct usbi_transfer *itransfer, HANDLE handle)
+{
+ struct windows_transfer_priv *transfer_priv = get_transfer_priv(itransfer);
+ transfer_priv->handle = handle;
+}
+
+static inline struct usbdk_transfer_priv *get_usbdk_transfer_priv(struct usbi_transfer *itransfer)
+{
+ struct windows_transfer_priv *transfer_priv = get_transfer_priv(itransfer);
+ return &transfer_priv->usbdk_priv;
+}
+
+static inline struct winusb_transfer_priv *get_winusb_transfer_priv(struct usbi_transfer *itransfer)
+{
+ struct windows_transfer_priv *transfer_priv = get_transfer_priv(itransfer);
+ return &transfer_priv->winusb_priv;
+}
+
extern const struct windows_backend usbdk_backend;
extern const struct windows_backend winusb_backend;
unsigned long htab_hash(const char *str);
+enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status);
void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size);
#if defined(ENABLE_LOGGING)
diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c
index bbec3d8..46935a6 100644
--- a/libusb/os/windows_usbdk.c
+++ b/libusb/os/windows_usbdk.c
@@ -48,11 +48,6 @@ static inline struct usbdk_device_priv *_usbdk_device_priv(struct libusb_device
return (struct usbdk_device_priv *)dev->os_priv;
}
-static inline struct usbdk_transfer_priv *_usbdk_transfer_priv(struct usbi_transfer *itransfer)
-{
- return (struct usbdk_transfer_priv *)usbi_transfer_get_os_priv(itransfer);
-}
-
static struct {
HMODULE module;
@@ -423,7 +418,7 @@ static int usbdk_open(struct libusb_device_handle *dev_handle)
priv->redirector_handle = usbdk_helper.StartRedirect(&priv->info.ID);
if (priv->redirector_handle == INVALID_HANDLE_VALUE) {
- usbi_err(DEVICE_CTX(dev_handle->dev), "Redirector startup failed");
+ usbi_err(HANDLE_CTX(dev_handle), "Redirector startup failed");
return LIBUSB_ERROR_OTHER;
}
@@ -463,11 +458,10 @@ static int usbdk_claim_interface(struct libusb_device_handle *dev_handle, int if
static int usbdk_set_interface_altsetting(struct libusb_device_handle *dev_handle, int iface, int altsetting)
{
- struct libusb_context *ctx = HANDLE_CTX(dev_handle);
struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
if (!usbdk_helper.SetAltsetting(priv->redirector_handle, iface, altsetting)) {
- usbi_err(ctx, "SetAltsetting failed: %s", windows_error_str(0));
+ usbi_err(HANDLE_CTX(dev_handle), "SetAltsetting failed: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_DEVICE;
}
@@ -483,11 +477,10 @@ static int usbdk_release_interface(struct libusb_device_handle *dev_handle, int
static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned char endpoint)
{
- struct libusb_context *ctx = HANDLE_CTX(dev_handle);
struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
if (!usbdk_helper.ResetPipe(priv->redirector_handle, endpoint)) {
- usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0));
+ usbi_err(HANDLE_CTX(dev_handle), "ResetPipe failed: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_DEVICE;
}
@@ -496,11 +489,10 @@ static int usbdk_clear_halt(struct libusb_device_handle *dev_handle, unsigned ch
static int usbdk_reset_device(struct libusb_device_handle *dev_handle)
{
- struct libusb_context *ctx = HANDLE_CTX(dev_handle);
struct usbdk_device_priv *priv = _usbdk_device_priv(dev_handle->dev);
if (!usbdk_helper.ResetDevice(priv->redirector_handle)) {
- usbi_err(ctx, "ResetDevice failed: %s", windows_error_str(0));
+ usbi_err(HANDLE_CTX(dev_handle), "ResetDevice failed: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_DEVICE;
}
@@ -517,13 +509,9 @@ static void usbdk_destroy_device(struct libusb_device *dev)
static void usbdk_clear_transfer_priv(struct usbi_transfer *itransfer)
{
- struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
+ struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- usbi_close(transfer_priv->pollable_fd.fd);
- transfer_priv->pollable_fd = INVALID_WINFD;
- transfer_priv->system_handle = NULL;
-
if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
safe_free(transfer_priv->IsochronousPacketsArray);
safe_free(transfer_priv->IsochronousResultsArray);
@@ -534,9 +522,8 @@ static int usbdk_do_control_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
- struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
- struct libusb_context *ctx = TRANSFER_CTX(transfer);
- OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped;
+ struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
+ OVERLAPPED *overlapped = get_transfer_priv_overlapped(itransfer);
TransferResult transResult;
transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
@@ -555,10 +542,12 @@ static int usbdk_do_control_transfer(struct usbi_transfer *itransfer)
case TransferSuccessAsync:
break;
case TransferFailure:
- usbi_err(ctx, "ControlTransfer failed: %s", windows_error_str(0));
+ usbi_err(TRANSFER_CTX(transfer), "ControlTransfer failed: %s", windows_error_str(0));
return LIBUSB_ERROR_IO;
}
+ set_transfer_priv_handle(itransfer, priv->system_handle);
+
return LIBUSB_SUCCESS;
}
@@ -566,9 +555,8 @@ static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
- struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
- struct libusb_context *ctx = TRANSFER_CTX(transfer);
- OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped;
+ struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
+ OVERLAPPED *overlapped = get_transfer_priv_overlapped(itransfer);
TransferResult transferRes;
transfer_priv->request.Buffer = (PVOID64)transfer->buffer;
@@ -582,9 +570,6 @@ static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer)
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
transfer_priv->request.TransferType = InterruptTransferType;
break;
- default:
- usbi_err(ctx, "Wrong transfer type (%d) in usbdk_do_bulk_transfer", transfer->type);
- return LIBUSB_ERROR_INVALID_PARAM;
}
if (IS_XFERIN(transfer))
@@ -599,10 +584,12 @@ static int usbdk_do_bulk_transfer(struct usbi_transfer *itransfer)
case TransferSuccessAsync:
break;
case TransferFailure:
- usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
+ usbi_err(TRANSFER_CTX(transfer), "ReadPipe/WritePipe failed: %s", windows_error_str(0));
return LIBUSB_ERROR_IO;
}
+ set_transfer_priv_handle(itransfer, priv->system_handle);
+
return LIBUSB_SUCCESS;
}
@@ -610,9 +597,8 @@ static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
- struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
- struct libusb_context *ctx = TRANSFER_CTX(transfer);
- OVERLAPPED *overlapped = transfer_priv->pollable_fd.overlapped;
+ struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
+ OVERLAPPED *overlapped = get_transfer_priv_overlapped(itransfer);
TransferResult transferRes;
int i;
@@ -624,14 +610,14 @@ static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer)
transfer_priv->IsochronousPacketsArray = malloc(transfer->num_iso_packets * sizeof(ULONG64));
transfer_priv->request.IsochronousPacketsArray = (PVOID64)transfer_priv->IsochronousPacketsArray;
if (!transfer_priv->IsochronousPacketsArray) {
- usbi_err(ctx, "Allocation of IsochronousPacketsArray failed");
+ usbi_err(TRANSFER_CTX(transfer), "Allocation of IsochronousPacketsArray failed");
return LIBUSB_ERROR_NO_MEM;
}
transfer_priv->IsochronousResultsArray = malloc(transfer->num_iso_packets * sizeof(USB_DK_ISO_TRANSFER_RESULT));
transfer_priv->request.Result.IsochronousResultsArray = (PVOID64)transfer_priv->IsochronousResultsArray;
if (!transfer_priv->IsochronousResultsArray) {
- usbi_err(ctx, "Allocation of isochronousResultsArray failed");
+ usbi_err(TRANSFER_CTX(transfer), "Allocation of isochronousResultsArray failed");
return LIBUSB_ERROR_NO_MEM;
}
@@ -653,39 +639,7 @@ static int usbdk_do_iso_transfer(struct usbi_transfer *itransfer)
return LIBUSB_ERROR_IO;
}
- return LIBUSB_SUCCESS;
-}
-
-static int usbdk_do_submit_transfer(struct usbi_transfer *itransfer,
- short events, int (*transfer_fn)(struct usbi_transfer *))
-{
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct libusb_context *ctx = TRANSFER_CTX(transfer);
- struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
- struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
- struct winfd wfd;
- int r;
-
- wfd = usbi_create_fd();
- if (wfd.fd < 0)
- return LIBUSB_ERROR_NO_MEM;
-
- r = usbi_add_pollfd(ctx, wfd.fd, events);
- if (r) {
- usbi_close(wfd.fd);
- return r;
- }
-
- // Use transfer_priv to store data needed for async polling
- transfer_priv->pollable_fd = wfd;
- transfer_priv->system_handle = priv->system_handle;
-
- r = transfer_fn(itransfer);
- if (r != LIBUSB_SUCCESS) {
- usbi_remove_pollfd(ctx, wfd.fd);
- usbdk_clear_transfer_priv(itransfer);
- return r;
- }
+ set_transfer_priv_handle(itransfer, priv->system_handle);
return LIBUSB_SUCCESS;
}
@@ -693,129 +647,55 @@ static int usbdk_do_submit_transfer(struct usbi_transfer *itransfer,
static int usbdk_submit_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- int (*transfer_fn)(struct usbi_transfer *);
- short events;
switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_CONTROL:
- events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT;
- transfer_fn = usbdk_do_control_transfer;
- break;
+ return usbdk_do_control_transfer(itransfer);
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
return LIBUSB_ERROR_NOT_SUPPORTED; //TODO: Check whether we can support this in UsbDk
- events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
- transfer_fn = usbdk_do_bulk_transfer;
- break;
+ return usbdk_do_bulk_transfer(itransfer);
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
- events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
- transfer_fn = usbdk_do_iso_transfer;
- break;
+ return usbdk_do_iso_transfer(itransfer);
default:
- usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
- return LIBUSB_ERROR_INVALID_PARAM;
+ // Should not get here since windows_submit_transfer() validates
+ // the transfer->type field
+ usbi_err(TRANSFER_CTX(transfer), "unsupported endpoint type %d", transfer->type);
+ return LIBUSB_ERROR_NOT_SUPPORTED;
}
-
- return usbdk_do_submit_transfer(itransfer, events, transfer_fn);
}
-static int usbdk_abort_transfers(struct usbi_transfer *itransfer)
+static enum libusb_transfer_status usbdk_copy_transfer_data(struct usbi_transfer *itransfer, DWORD length)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct libusb_context *ctx = TRANSFER_CTX(transfer);
- struct usbdk_device_priv *priv = _usbdk_device_priv(transfer->dev_handle->dev);
- struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
- struct winfd *pollable_fd = &transfer_priv->pollable_fd;
-
- // Use CancelIoEx to cancel just a single transfer
- if (CancelIoEx(priv->system_handle, pollable_fd->overlapped))
- return LIBUSB_SUCCESS;
+ struct usbdk_transfer_priv *transfer_priv = get_usbdk_transfer_priv(itransfer);
- usbi_warn(ctx, "CancelIoEx failed: %s", windows_error_str(0));
- return LIBUSB_ERROR_NOT_FOUND;
-}
+ UNUSED(length);
-static int usbdk_cancel_transfer(struct usbi_transfer *itransfer)
-{
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-
- switch (transfer->type) {
- case LIBUSB_TRANSFER_TYPE_CONTROL:
- // Control transfers cancelled by IoCancelXXX() API
- // No special treatment needed
- return LIBUSB_SUCCESS;
- case LIBUSB_TRANSFER_TYPE_BULK:
- case LIBUSB_TRANSFER_TYPE_INTERRUPT:
- case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
- return usbdk_abort_transfers(itransfer);
- default:
- usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
- return LIBUSB_ERROR_INVALID_PARAM;
- }
-}
-
-static int usbdk_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
-{
- itransfer->transferred += io_size;
- return LIBUSB_TRANSFER_COMPLETED;
-}
-
-static int usbdk_get_transfer_fd(struct usbi_transfer *itransfer)
-{
- struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
- return transfer_priv->pollable_fd.fd;
-}
-
-static DWORD usbdk_translate_usbd_status(USBD_STATUS UsbdStatus)
-{
- if (USBD_SUCCESS(UsbdStatus))
- return NO_ERROR;
-
- switch (UsbdStatus) {
- case USBD_STATUS_TIMEOUT:
- return ERROR_SEM_TIMEOUT;
- case USBD_STATUS_CANCELED:
- return ERROR_OPERATION_ABORTED;
- default:
- return ERROR_GEN_FAILURE;
- }
-}
-
-static void usbdk_get_overlapped_result(struct usbi_transfer *itransfer, DWORD *io_result, DWORD *io_size)
-{
- struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
- struct winfd *pollable_fd = &transfer_priv->pollable_fd;
-
- if (HasOverlappedIoCompletedSync(pollable_fd->overlapped) // Handle async requests that completed synchronously first
- || GetOverlappedResult(transfer_priv->system_handle, pollable_fd->overlapped, io_size, FALSE)) { // Regular async overlapped
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-
- if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
- ULONG64 i;
- for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) {
- struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
-
- switch (transfer_priv->IsochronousResultsArray[i].TransferResult) {
- case STATUS_SUCCESS:
- case STATUS_CANCELLED:
- case STATUS_REQUEST_CANCELED:
- lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS
- break;
- default:
- lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION;
- break;
- }
-
- lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength;
+ if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
+ ULONG64 i;
+
+ for (i = 0; i < transfer_priv->request.IsochronousPacketsArraySize; i++) {
+ struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
+
+ switch (transfer_priv->IsochronousResultsArray[i].TransferResult) {
+ case STATUS_SUCCESS:
+ case STATUS_CANCELLED:
+ case STATUS_REQUEST_CANCELED:
+ lib_desc->status = LIBUSB_TRANSFER_COMPLETED; // == ERROR_SUCCESS
+ break;
+ default:
+ lib_desc->status = LIBUSB_TRANSFER_ERROR; // ERROR_UNKNOWN_EXCEPTION;
+ break;
}
- }
- *io_size = (DWORD)transfer_priv->request.Result.GenResult.BytesTransferred;
- *io_result = usbdk_translate_usbd_status((USBD_STATUS)transfer_priv->request.Result.GenResult.UsbdStatus);
- } else {
- *io_result = GetLastError();
+ lib_desc->actual_length = (unsigned int)transfer_priv->IsochronousResultsArray[i].ActualLength;
+ }
}
+
+ itransfer->transferred += (int)transfer_priv->request.Result.GenResult.BytesTransferred;
+ return usbd_status_to_libusb_transfer_status((USBD_STATUS)transfer_priv->request.Result.GenResult.UsbdStatus);
}
const struct windows_backend usbdk_backend = {
@@ -837,9 +717,7 @@ const struct windows_backend usbdk_backend = {
usbdk_reset_device,
usbdk_destroy_device,
usbdk_submit_transfer,
- usbdk_cancel_transfer,
+ NULL, /* cancel_transfer */
usbdk_clear_transfer_priv,
usbdk_copy_transfer_data,
- usbdk_get_transfer_fd,
- usbdk_get_overlapped_result,
};
diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c
index 7cb17be..ce4d3a1 100644
--- a/libusb/os/windows_winusb.c
+++ b/libusb/os/windows_winusb.c
@@ -42,13 +42,7 @@
#define HANDLE_VALID(h) (((h) != NULL) && ((h) != INVALID_HANDLE_VALUE))
-// The 2 macros below are used in conjunction with safe loops.
-#define LOOP_CHECK(fcall) \
- { \
- r = fcall; \
- if (r != LIBUSB_SUCCESS) \
- continue; \
- }
+// The below macro is used in conjunction with safe loops.
#define LOOP_BREAK(err) \
{ \
r = err; \
@@ -56,7 +50,7 @@
}
// WinUSB-like API prototypes
-static int winusbx_init(struct libusb_context *ctx);
+static bool winusbx_init(struct libusb_context *ctx);
static void winusbx_exit(void);
static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle);
static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle);
@@ -68,12 +62,11 @@ static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_ha
static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer);
static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
-static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
-static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer);
+static int winusbx_cancel_transfer(int sub_api, struct usbi_transfer *itransfer);
static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
-static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
+static enum libusb_transfer_status winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length);
// HID API prototypes
-static int hid_init(struct libusb_context *ctx);
+static bool hid_init(struct libusb_context *ctx);
static void hid_exit(void);
static int hid_open(int sub_api, struct libusb_device_handle *dev_handle);
static void hid_close(int sub_api, struct libusb_device_handle *dev_handle);
@@ -83,9 +76,8 @@ static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle
static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer);
static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
-static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
-static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
+static enum libusb_transfer_status hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length);
// Composite API prototypes
static int composite_open(int sub_api, struct libusb_device_handle *dev_handle);
static void composite_close(int sub_api, struct libusb_device_handle *dev_handle);
@@ -96,28 +88,25 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *
static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer);
static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer);
static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint);
-static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer);
-static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer);
+static int composite_cancel_transfer(int sub_api, struct usbi_transfer *itransfer);
static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle);
-static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
+static enum libusb_transfer_status composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length);
static usbi_mutex_t autoclaim_lock;
// API globals
-static HMODULE WinUSBX_handle = NULL;
static struct winusb_interface WinUSBX[SUB_API_MAX];
#define CHECK_WINUSBX_AVAILABLE(sub_api) \
do { \
if (sub_api == SUB_API_NOTSET) \
sub_api = priv->sub_api; \
- if (!WinUSBX[sub_api].initialized) \
+ if (WinUSBX[sub_api].hDll == NULL) \
return LIBUSB_ERROR_ACCESS; \
} while (0)
-static bool api_hid_available = false;
#define CHECK_HID_AVAILABLE \
do { \
- if (!api_hid_available) \
+ if (DLL_HANDLE_NAME(hid) == NULL) \
return LIBUSB_ERROR_ACCESS; \
} while (0)
@@ -183,40 +172,40 @@ static char *sanitize_path(const char *path)
/*
* Cfgmgr32, AdvAPI32, OLE32 and SetupAPI DLL functions
*/
-static BOOL init_dlls(void)
+static bool init_dlls(void)
{
DLL_GET_HANDLE(Cfgmgr32);
- DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, TRUE);
- DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, TRUE);
+ DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Parent, true);
+ DLL_LOAD_FUNC(Cfgmgr32, CM_Get_Child, true);
// Prefixed to avoid conflict with header files
DLL_GET_HANDLE(AdvAPI32);
- DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, TRUE);
- DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, TRUE);
+ DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegQueryValueExW, true);
+ DLL_LOAD_FUNC_PREFIXED(AdvAPI32, p, RegCloseKey, true);
DLL_GET_HANDLE(OLE32);
- DLL_LOAD_FUNC_PREFIXED(OLE32, p, IIDFromString, TRUE);
+ DLL_LOAD_FUNC_PREFIXED(OLE32, p, IIDFromString, true);
DLL_GET_HANDLE(SetupAPI);
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, TRUE);
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, TRUE);
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, TRUE);
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInstanceIdA, TRUE);
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, TRUE);
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, TRUE);
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, TRUE);
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, TRUE);
- DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, TRUE);
-
- return TRUE;
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetClassDevsA, true);
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInfo, true);
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiEnumDeviceInterfaces, true);
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInstanceIdA, true);
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceInterfaceDetailA, true);
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiGetDeviceRegistryPropertyA, true);
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiDestroyDeviceInfoList, true);
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDevRegKey, true);
+ DLL_LOAD_FUNC_PREFIXED(SetupAPI, p, SetupDiOpenDeviceInterfaceRegKey, true);
+
+ return true;
}
static void exit_dlls(void)
{
- DLL_FREE_HANDLE(Cfgmgr32);
- DLL_FREE_HANDLE(AdvAPI32);
- DLL_FREE_HANDLE(OLE32);
DLL_FREE_HANDLE(SetupAPI);
+ DLL_FREE_HANDLE(OLE32);
+ DLL_FREE_HANDLE(AdvAPI32);
+ DLL_FREE_HANDLE(Cfgmgr32);
}
/*
@@ -391,13 +380,13 @@ static SP_DEVICE_INTERFACE_DETAIL_DATA_A *get_interface_details_filter(struct li
goto err_exit;
}
} else {
- usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong.");
+ usbi_err(ctx, "program assertion failed - http://msdn.microsoft.com/en-us/library/ms792901.aspx is wrong");
goto err_exit;
}
- dev_interface_details = calloc(1, size);
+ dev_interface_details = malloc(size);
if (dev_interface_details == NULL) {
- usbi_err(ctx, "could not allocate interface data for index %u.", _index);
+ usbi_err(ctx, "could not allocate interface data for index %u", _index);
goto err_exit;
}
@@ -468,7 +457,8 @@ static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc,
{
const struct libusb_interface *intf;
const struct libusb_interface_descriptor *intf_desc;
- int i, j, k;
+ uint8_t i, k;
+ int j;
for (i = 0; i < conf_desc->bNumInterfaces; i++) {
intf = &conf_desc->interface[i];
@@ -492,15 +482,14 @@ static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc,
*/
static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int iface, int altsetting)
{
- int i, r;
struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
struct libusb_config_descriptor *conf_desc;
const struct libusb_interface_descriptor *if_desc;
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+ int i, r;
r = libusb_get_active_config_descriptor(dev_handle->dev, &conf_desc);
if (r != LIBUSB_SUCCESS) {
- usbi_warn(ctx, "could not read config descriptor: error %d", r);
+ usbi_warn(HANDLE_CTX(dev_handle), "could not read config descriptor: error %d", r);
return r;
}
@@ -541,10 +530,10 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int
// return -1 if not found, driver match number otherwise
static int get_sub_api(char *driver, int api)
{
- int i;
const char sep_str[2] = {LIST_SEPARATOR, 0};
char *tok, *tmp_str;
size_t len = strlen(driver);
+ int i;
if (len == 0)
return SUB_API_NOTSET;
@@ -573,7 +562,6 @@ static int get_sub_api(char *driver, int api)
*/
static int auto_claim(struct libusb_transfer *transfer, int *interface_number, int api_type)
{
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(
transfer->dev_handle);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
@@ -596,13 +584,13 @@ static int auto_claim(struct libusb_transfer *transfer, int *interface_number, i
&& (libusb_claim_interface(transfer->dev_handle, current_interface) == LIBUSB_SUCCESS)) {
usbi_dbg("auto-claimed interface %d for control request", current_interface);
if (handle_priv->autoclaim_count[current_interface] != 0)
- usbi_warn(ctx, "program assertion failed - autoclaim_count was nonzero");
+ usbi_err(TRANSFER_CTX(transfer), "program assertion failed - autoclaim_count was nonzero");
handle_priv->autoclaim_count[current_interface]++;
break;
}
}
if (current_interface == USB_MAXINTERFACES) {
- usbi_err(ctx, "could not auto-claim any interface");
+ usbi_err(TRANSFER_CTX(transfer), "could not auto-claim any interface");
r = LIBUSB_ERROR_NOT_FOUND;
}
} else {
@@ -619,7 +607,7 @@ static int auto_claim(struct libusb_transfer *transfer, int *interface_number, i
static void auto_release(struct usbi_transfer *itransfer)
{
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
libusb_device_handle *dev_handle = transfer->dev_handle;
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
@@ -647,9 +635,6 @@ static int winusb_init(struct libusb_context *ctx)
{
int i;
- // We need a lock for proper auto-release
- usbi_mutex_init(&autoclaim_lock);
-
// Load DLL imports
if (!init_dlls()) {
usbi_err(ctx, "could not resolve DLL functions");
@@ -658,11 +643,14 @@ static int winusb_init(struct libusb_context *ctx)
// Initialize the low level APIs (we don't care about errors at this stage)
for (i = 0; i < USB_API_MAX; i++) {
- if (usb_api_backend[i].init && usb_api_backend[i].init(ctx))
+ if (usb_api_backend[i].init && !usb_api_backend[i].init(ctx))
usbi_warn(ctx, "error initializing %s backend",
usb_api_backend[i].designation);
}
+ // We need a lock for proper auto-release
+ usbi_mutex_init(&autoclaim_lock);
+
return LIBUSB_SUCCESS;
}
@@ -675,13 +663,14 @@ static void winusb_exit(struct libusb_context *ctx)
UNUSED(ctx);
+ usbi_mutex_destroy(&autoclaim_lock);
+
for (i = 0; i < USB_API_MAX; i++) {
if (usb_api_backend[i].exit)
usb_api_backend[i].exit();
}
exit_dlls();
- usbi_mutex_destroy(&autoclaim_lock);
}
/*
@@ -701,6 +690,8 @@ static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handl
if (dev->num_configurations == 0)
return;
+ assert(sizeof(USB_DESCRIPTOR_REQUEST) == USB_DESCRIPTOR_REQUEST_SIZE);
+
priv->config_descriptor = calloc(dev->num_configurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
if (priv->config_descriptor == NULL) {
usbi_err(ctx, "could not allocate configuration descriptor array for '%s'", priv->dev_id);
@@ -714,7 +705,7 @@ static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handl
break;
size = sizeof(cd_buf_short);
- memset(&cd_buf_short, 0, size);
+ memset(&cd_buf_short.desc, 0, sizeof(cd_buf_short.desc));
cd_buf_short.req.ConnectionIndex = (ULONG)dev->port_number;
cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
@@ -758,7 +749,7 @@ static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handl
continue;
}
- cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + sizeof(USB_DESCRIPTOR_REQUEST));
+ cd_data = (PUSB_CONFIGURATION_DESCRIPTOR)((UCHAR *)cd_buf_actual + USB_DESCRIPTOR_REQUEST_SIZE);
if ((size != ret_size) || (cd_data->wTotalLength != cd_buf_short.desc.wTotalLength)) {
usbi_err(ctx, "unexpected configuration descriptor %u size (actual) for '%s'", i, priv->dev_id);
@@ -774,12 +765,8 @@ static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handl
i, cd_data->bConfigurationValue, cd_data->wTotalLength);
// Cache the descriptor
- priv->config_descriptor[i] = malloc(cd_data->wTotalLength);
- if (priv->config_descriptor[i] != NULL) {
- memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength);
- } else {
- usbi_err(ctx, "could not allocate configuration descriptor %u buffer for '%s'", i, priv->dev_id);
- }
+ priv->config_descriptor[i] = cd_data;
+ cd_buf_actual = NULL;
}
}
@@ -853,7 +840,6 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
return LIBUSB_ERROR_ACCESS;
}
- memset(&conn_info, 0, sizeof(conn_info));
conn_info.ConnectionIndex = (ULONG)port_number;
// coverity[tainted_data_argument]
ginfotimeout = 20;
@@ -873,31 +859,28 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
}
memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR));
- dev->num_configurations = priv->dev_descriptor.bNumConfigurations;
+ dev->num_configurations = conn_info.DeviceDescriptor.bNumConfigurations;
priv->active_config = conn_info.CurrentConfigurationValue;
if (priv->active_config == 0) {
- usbi_dbg("0x%x:0x%x found %u configurations (active conf: %u) \n",
+ usbi_dbg("0x%x:0x%x found %u configurations (not configured)",
priv->dev_descriptor.idVendor,
priv->dev_descriptor.idProduct,
- dev->num_configurations,
- priv->active_config);
+ dev->num_configurations);
+ SleepEx(50, TRUE);
}
- if (priv->active_config == 0)
- Sleep(50);
} while (priv->active_config == 0 && --ginfotimeout >= 0);
if (priv->active_config == 0) {
- usbi_dbg("after try 0x%x:0x%x found %u configurations (active conf: %u) \n",
+ usbi_info(ctx, "0x%x:0x%x found %u configurations but device isn't configured, "
+ "forcing current configuration to 1",
priv->dev_descriptor.idVendor,
priv->dev_descriptor.idProduct,
- dev->num_configurations,
- priv->active_config);
- usbi_dbg("Force this device active config to 1 in libusb! \nNOTICE: Should not reach this place!!!!!! \n");
+ dev->num_configurations);
priv->active_config = 1;
+ } else {
+ usbi_dbg("found %u configurations (current config: %u)", dev->num_configurations, priv->active_config);
}
- usbi_dbg("found %u configurations (active conf: %u)", dev->num_configurations, priv->active_config);
-
// Cache as many config descriptors as we can
cache_config_descriptors(dev, hub_handle);
@@ -964,7 +947,7 @@ static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id
session_id = (unsigned long)child_devinst;
dev = usbi_get_device_by_session_id(ctx, session_id);
if (dev == NULL) {
- usbi_warn(ctx, "program assertion failed - HCD '%s' child not found", dev_id);
+ usbi_err(ctx, "program assertion failed - HCD '%s' child not found", dev_id);
return LIBUSB_SUCCESS;
}
@@ -1093,20 +1076,20 @@ static int set_composite_interface(struct libusb_context *ctx, struct libusb_dev
static int set_hid_interface(struct libusb_context *ctx, struct libusb_device *dev,
char *dev_interface_path)
{
- int i;
struct winusb_device_priv *priv = _device_priv(dev);
+ uint8_t i;
if (priv->hid == NULL) {
- usbi_err(ctx, "program assertion failed: parent is not HID");
+ usbi_err(ctx, "program assertion failed - parent is not HID");
return LIBUSB_ERROR_NO_DEVICE;
} else if (priv->hid->nb_interfaces == USB_MAXINTERFACES) {
- usbi_err(ctx, "program assertion failed: max USB interfaces reached for HID device");
+ usbi_err(ctx, "program assertion failed - max USB interfaces reached for HID device");
return LIBUSB_ERROR_NO_DEVICE;
}
for (i = 0; i < priv->hid->nb_interfaces; i++) {
if ((priv->usb_interface[i].path != NULL) && strcmp(priv->usb_interface[i].path, dev_interface_path) == 0) {
- usbi_dbg("interface[%d] already set to %s", i, dev_interface_path);
+ usbi_dbg("interface[%u] already set to %s", i, dev_interface_path);
return LIBUSB_ERROR_ACCESS;
}
}
@@ -1182,7 +1165,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
guid_list[DEV_PASS] = &GUID_DEVINTERFACE_USB_DEVICE;
guid_list[HCD_PASS] = &GUID_DEVINTERFACE_USB_HOST_CONTROLLER;
guid_list[GEN_PASS] = NULL;
- if (api_hid_available) {
+ if (HidD_GetHidGuid != NULL) {
HidD_GetHidGuid(&hid_guid);
guid_list[HID_PASS] = &hid_guid;
} else {
@@ -1228,7 +1211,7 @@ static int winusb_get_device_list(struct libusb_context *ctx, struct discovered_
break;
if ((pass == HCD_PASS) && (i == UINT8_MAX)) {
- usbi_warn(ctx, "program assertion failed - found more than %u buses, skipping the rest.", UINT8_MAX);
+ usbi_warn(ctx, "program assertion failed - found more than %u buses, skipping the rest", UINT8_MAX);
break;
}
@@ -1741,14 +1724,11 @@ static void winusb_destroy_device(struct libusb_device *dev)
static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer)
{
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
int sub_api = priv->sub_api;
- usbi_close(transfer_priv->pollable_fd.fd);
- transfer_priv->pollable_fd = INVALID_WINFD;
- transfer_priv->handle = NULL;
safe_free(transfer_priv->hid_buffer);
if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS && sub_api == SUB_API_WINUSB) {
@@ -1756,7 +1736,7 @@ static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer)
if (WinUSBX[sub_api].UnregisterIsochBuffer(transfer_priv->isoch_buffer_handle)) {
transfer_priv->isoch_buffer_handle = NULL;
} else {
- usbi_dbg("Couldn't unregister isoch buffer!");
+ usbi_warn(TRANSFER_CTX(transfer), "failed to unregister WinUSB isoch buffer: %s", windows_error_str(0));
}
}
}
@@ -1767,64 +1747,28 @@ static void winusb_clear_transfer_priv(struct usbi_transfer *itransfer)
auto_release(itransfer);
}
-static int do_submit_transfer(struct usbi_transfer *itransfer, short events,
- int (*transfer_fn)(int, struct usbi_transfer *))
-{
- struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
- struct winfd wfd;
- int r;
-
- wfd = usbi_create_fd();
- if (wfd.fd < 0)
- return LIBUSB_ERROR_NO_MEM;
-
- r = usbi_add_pollfd(ctx, wfd.fd, events);
- if (r) {
- usbi_close(wfd.fd);
- return r;
- }
-
- // Use transfer_priv to store data needed for async polling
- transfer_priv->pollable_fd = wfd;
-
- r = transfer_fn(SUB_API_NOTSET, itransfer);
-
- if ((r != LIBUSB_SUCCESS) && (r != LIBUSB_ERROR_OVERFLOW)) {
- usbi_remove_pollfd(ctx, wfd.fd);
- usbi_close(wfd.fd);
- transfer_priv->pollable_fd = INVALID_WINFD;
- }
-
- return r;
-}
-
static int winusb_submit_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
int (*transfer_fn)(int, struct usbi_transfer *);
- short events;
switch (transfer->type) {
case LIBUSB_TRANSFER_TYPE_CONTROL:
- events = (transfer->buffer[0] & LIBUSB_ENDPOINT_IN) ? POLLIN : POLLOUT;
transfer_fn = priv->apib->submit_control_transfer;
break;
case LIBUSB_TRANSFER_TYPE_BULK:
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
if (IS_XFEROUT(transfer) && (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
return LIBUSB_ERROR_NOT_SUPPORTED;
- events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
transfer_fn = priv->apib->submit_bulk_transfer;
break;
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
- events = IS_XFERIN(transfer) ? POLLIN : POLLOUT;
transfer_fn = priv->apib->submit_iso_transfer;
break;
- case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
- return LIBUSB_ERROR_NOT_SUPPORTED;
default:
+ // Should not get here since windows_submit_transfer() validates
+ // the transfer->type field
usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
return LIBUSB_ERROR_INVALID_PARAM;
}
@@ -1836,76 +1780,30 @@ static int winusb_submit_transfer(struct usbi_transfer *itransfer)
return LIBUSB_ERROR_NOT_SUPPORTED;
}
- return do_submit_transfer(itransfer, events, transfer_fn);
+ return transfer_fn(SUB_API_NOTSET, itransfer);
}
-static int windows_abort_control(struct usbi_transfer *itransfer)
+static int winusb_cancel_transfer(struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
- CHECK_SUPPORTED_API(priv->apib, abort_control);
+ CHECK_SUPPORTED_API(priv->apib, cancel_transfer);
- return priv->apib->abort_control(SUB_API_NOTSET, itransfer);
+ return priv->apib->cancel_transfer(SUB_API_NOTSET, itransfer);
}
-static int windows_abort_transfers(struct usbi_transfer *itransfer)
+static enum libusb_transfer_status winusb_copy_transfer_data(struct usbi_transfer *itransfer, DWORD length)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
- CHECK_SUPPORTED_API(priv->apib, abort_transfers);
-
- return priv->apib->abort_transfers(SUB_API_NOTSET, itransfer);
-}
-
-static int winusb_cancel_transfer(struct usbi_transfer *itransfer)
-{
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
-
- switch (transfer->type) {
- case LIBUSB_TRANSFER_TYPE_CONTROL:
- return windows_abort_control(itransfer);
- case LIBUSB_TRANSFER_TYPE_BULK:
- case LIBUSB_TRANSFER_TYPE_INTERRUPT:
- case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
- return windows_abort_transfers(itransfer);
- case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
- return LIBUSB_ERROR_NOT_SUPPORTED;
- default:
- usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
- return LIBUSB_ERROR_INVALID_PARAM;
+ if (priv->apib->copy_transfer_data == NULL) {
+ usbi_err(TRANSFER_CTX(transfer), "program assertion failed - no function to copy transfer data");
+ return LIBUSB_TRANSFER_ERROR;
}
-}
-static int winusb_copy_transfer_data(struct usbi_transfer *itransfer, uint32_t io_size)
-{
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
- return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, io_size);
-}
-
-static int winusb_get_transfer_fd(struct usbi_transfer *itransfer)
-{
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
- return transfer_priv->pollable_fd.fd;
-}
-
-static void winusb_get_overlapped_result(struct usbi_transfer *itransfer,
- DWORD *io_result, DWORD *io_size)
-{
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
- struct winfd *pollable_fd = &transfer_priv->pollable_fd;
-
- if (HasOverlappedIoCompletedSync(pollable_fd->overlapped)) {
- *io_result = NO_ERROR;
- *io_size = (DWORD)pollable_fd->overlapped->InternalHigh;
- } else if (GetOverlappedResult(transfer_priv->handle, pollable_fd->overlapped, io_size, FALSE)) {
- // Regular async overlapped
- *io_result = NO_ERROR;
- } else {
- *io_result = GetLastError();
- }
+ return priv->apib->copy_transfer_data(SUB_API_NOTSET, itransfer, length);
}
// NB: MSVC6 does not support named initializers.
@@ -1931,8 +1829,6 @@ const struct windows_backend winusb_backend = {
winusb_cancel_transfer,
winusb_clear_transfer_priv,
winusb_copy_transfer_data,
- winusb_get_transfer_fd,
- winusb_get_overlapped_result,
};
/*
@@ -1971,8 +1867,7 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
composite_submit_bulk_transfer,
composite_submit_iso_transfer,
composite_submit_control_transfer,
- composite_abort_control,
- composite_abort_transfers,
+ composite_cancel_transfer,
composite_copy_transfer_data,
},
{
@@ -1993,8 +1888,7 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
winusbx_submit_bulk_transfer,
winusbx_submit_iso_transfer,
winusbx_submit_control_transfer,
- winusbx_abort_control,
- winusbx_abort_transfers,
+ winusbx_cancel_transfer,
winusbx_copy_transfer_data,
},
{
@@ -2015,8 +1909,7 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
hid_submit_bulk_transfer,
NULL, /* submit_iso_transfer */
hid_submit_control_transfer,
- hid_abort_transfers,
- hid_abort_transfers,
+ NULL, /* cancel_transfer */
hid_copy_transfer_data,
},
};
@@ -2025,105 +1918,159 @@ const struct windows_usb_api_backend usb_api_backend[USB_API_MAX] = {
/*
* WinUSB-like (WinUSB, libusb0/libusbK through libusbk DLL) API functions
*/
-#define WinUSBX_Set(fn) \
+#define WinUSB_Set(h, fn, required) \
do { \
- if (native_winusb) \
- WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \
- else \
- pLibK_GetProcAddress((PVOID *)&WinUSBX[i].fn, i, KUSB_FNID_##fn); \
+ WinUSBX[SUB_API_WINUSB].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \
+ if (required && (WinUSBX[SUB_API_WINUSB].fn == NULL)) { \
+ usbi_err(ctx, "GetProcAddress() failed for WinUsb_%s", #fn); \
+ goto cleanup_winusb; \
+ } \
} while (0)
-#define NativeWinUSBOnly_Set(fn) \
+#define libusbK_Set(sub_api, fn, required) \
do { \
- if (native_winusb) \
- WinUSBX[i].fn = (WinUsb_##fn##_t)GetProcAddress(h, "WinUsb_" #fn); \
- else \
- WinUSBX[i].fn = NULL; \
+ pLibK_GetProcAddress((PVOID *)&WinUSBX[sub_api].fn, sub_api, KUSB_FNID_##fn); \
+ if (required && (WinUSBX[sub_api].fn == NULL)) { \
+ usbi_err(ctx, "LibK_GetProcAddress() failed for LibK_%s", #fn); \
+ goto cleanup_libusbk; \
+ } \
} while (0)
-static int winusbx_init(struct libusb_context *ctx)
+static bool winusbx_init(struct libusb_context *ctx)
{
- HMODULE h;
- bool native_winusb;
- int i;
- KLIB_VERSION LibK_Version;
- LibK_GetProcAddress_t pLibK_GetProcAddress = NULL;
- LibK_GetVersion_t pLibK_GetVersion;
+ HMODULE hWinUSB, hlibusbK;
+
+ hWinUSB = LoadLibraryA("WinUSB");
+ if (hWinUSB != NULL) {
+ WinUSB_Set(hWinUSB, AbortPipe, true);
+ WinUSB_Set(hWinUSB, ControlTransfer, true);
+ WinUSB_Set(hWinUSB, FlushPipe, true);
+ WinUSB_Set(hWinUSB, Free, true);
+ WinUSB_Set(hWinUSB, GetAssociatedInterface, true);
+ WinUSB_Set(hWinUSB, Initialize, true);
+ WinUSB_Set(hWinUSB, ReadPipe, true);
+ WinUSB_Set(hWinUSB, ResetPipe, true);
+ WinUSB_Set(hWinUSB, SetCurrentAlternateSetting, true);
+ WinUSB_Set(hWinUSB, SetPipePolicy, true);
+ WinUSB_Set(hWinUSB, WritePipe, true);
+
+ // Check for isochronous transfers support (available starting with Windows 8.1)
+ WinUSB_Set(hWinUSB, ReadIsochPipeAsap, false);
+ if (WinUSBX[SUB_API_WINUSB].ReadIsochPipeAsap != NULL) {
+ WinUSB_Set(hWinUSB, QueryPipeEx, true);
+ WinUSB_Set(hWinUSB, RegisterIsochBuffer, true);
+ WinUSB_Set(hWinUSB, UnregisterIsochBuffer, true);
+ WinUSB_Set(hWinUSB, WriteIsochPipeAsap, true);
+ }
- h = LoadLibraryA("libusbK");
+ WinUSBX[SUB_API_WINUSB].hDll = hWinUSB;
- if (h == NULL) {
- usbi_info(ctx, "libusbK DLL is not available, will use native WinUSB");
- h = LoadLibraryA("WinUSB");
+ usbi_info(ctx, "WinUSB DLL available (%s isoch support)",
+ (WinUSBX[SUB_API_WINUSB].ReadIsochPipeAsap != NULL) ? "with" : "without");
- if (h == NULL) {
- usbi_warn(ctx, "WinUSB DLL is not available either, "
- "you will not be able to access devices outside of enumeration");
- return LIBUSB_ERROR_NOT_FOUND;
+cleanup_winusb:
+ if (WinUSBX[SUB_API_WINUSB].hDll == NULL) {
+ usbi_err(ctx, "failed to initialize WinUSB");
+ memset(&WinUSBX[SUB_API_WINUSB], 0, sizeof(WinUSBX[SUB_API_WINUSB]));
+ FreeLibrary(hWinUSB);
+ hWinUSB = NULL;
}
} else {
- usbi_dbg("using libusbK DLL for universal access");
- pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(h, "LibK_GetVersion");
+ usbi_info(ctx, "WinUSB DLL is not available");
+ }
+
+ hlibusbK = LoadLibraryA("libusbK");
+ if (hlibusbK != NULL) {
+ LibK_GetVersion_t pLibK_GetVersion;
+ LibK_GetProcAddress_t pLibK_GetProcAddress;
+ int sub_api = 0;
+
+ pLibK_GetVersion = (LibK_GetVersion_t)GetProcAddress(hlibusbK, "LibK_GetVersion");
if (pLibK_GetVersion != NULL) {
+ KLIB_VERSION LibK_Version;
+
pLibK_GetVersion(&LibK_Version);
- usbi_dbg("libusbK version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor,
+ usbi_dbg("libusbK DLL found, version: %d.%d.%d.%d", LibK_Version.Major, LibK_Version.Minor,
LibK_Version.Micro, LibK_Version.Nano);
+ } else {
+ usbi_dbg("libusbK DLL found, version unknown");
}
- pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(h, "LibK_GetProcAddress");
+
+ pLibK_GetProcAddress = (LibK_GetProcAddress_t)GetProcAddress(hlibusbK, "LibK_GetProcAddress");
if (pLibK_GetProcAddress == NULL) {
usbi_err(ctx, "LibK_GetProcAddress() not found in libusbK DLL");
- FreeLibrary(h);
- return LIBUSB_ERROR_NOT_FOUND;
+ goto cleanup_libusbk;
}
- }
- native_winusb = (pLibK_GetProcAddress == NULL);
- for (i = 0; i < SUB_API_MAX; i++) {
- WinUSBX_Set(AbortPipe);
- WinUSBX_Set(ControlTransfer);
- WinUSBX_Set(FlushPipe);
- WinUSBX_Set(Free);
- WinUSBX_Set(GetAssociatedInterface);
- WinUSBX_Set(Initialize);
- WinUSBX_Set(ReadPipe);
- if (!native_winusb)
- WinUSBX_Set(ResetDevice);
- WinUSBX_Set(ResetPipe);
- WinUSBX_Set(SetCurrentAlternateSetting);
- WinUSBX_Set(SetPipePolicy);
- WinUSBX_Set(WritePipe);
- WinUSBX_Set(IsoReadPipe);
- WinUSBX_Set(IsoWritePipe);
- NativeWinUSBOnly_Set(RegisterIsochBuffer);
- NativeWinUSBOnly_Set(UnregisterIsochBuffer);
- NativeWinUSBOnly_Set(WriteIsochPipeAsap);
- NativeWinUSBOnly_Set(ReadIsochPipeAsap);
- NativeWinUSBOnly_Set(QueryPipeEx);
-
- if (WinUSBX[i].Initialize != NULL) {
- WinUSBX[i].initialized = true;
- // Assume driver supports CancelIoEx()
- WinUSBX[i].CancelIoEx_supported = true;
- usbi_dbg("initalized sub API %s", winusbx_driver_names[i]);
- } else {
- usbi_warn(ctx, "Failed to initalize sub API %s", winusbx_driver_names[i]);
- WinUSBX[i].initialized = false;
+ // NB: The below for loop works because the sub_api value for WinUSB
+ // is a higher value than that of libusbK and libusb0
+ for (; sub_api < SUB_API_WINUSB; sub_api++) {
+ libusbK_Set(sub_api, AbortPipe, true);
+ libusbK_Set(sub_api, ControlTransfer, true);
+ libusbK_Set(sub_api, FlushPipe, true);
+ libusbK_Set(sub_api, Free, true);
+ libusbK_Set(sub_api, GetAssociatedInterface, true);
+ libusbK_Set(sub_api, Initialize, true);
+ libusbK_Set(sub_api, ReadPipe, true);
+ libusbK_Set(sub_api, ResetPipe, true);
+ libusbK_Set(sub_api, SetCurrentAlternateSetting, true);
+ libusbK_Set(sub_api, SetPipePolicy, true);
+ libusbK_Set(sub_api, WritePipe, true);
+
+ // Optional isochronous support
+ libusbK_Set(sub_api, IsoReadPipe, false);
+ if (WinUSBX[sub_api].IsoReadPipe != NULL)
+ libusbK_Set(sub_api, IsoWritePipe, true);
+
+ // Optional device reset support
+ libusbK_Set(sub_api, ResetDevice, false);
+
+ WinUSBX[sub_api].hDll = hlibusbK;
+ }
+
+cleanup_libusbk:
+ if (sub_api < SUB_API_WINUSB) {
+ usbi_err(ctx, "failed to initialize libusbK");
+ while (sub_api >= 0) {
+ memset(&WinUSBX[sub_api], 0, sizeof(WinUSBX[sub_api]));
+ sub_api--;
+ }
+ FreeLibrary(hlibusbK);
+ hlibusbK = NULL;
}
+ } else {
+ usbi_info(ctx, "libusbK DLL is not available");
}
- WinUSBX_handle = h;
- return LIBUSB_SUCCESS;
+ if ((hWinUSB == NULL) && (hlibusbK == NULL)) {
+ usbi_warn(ctx, "neither WinUSB nor libusbK DLLs were found, "
+ "you will not be able to access devices outside of enumeration");
+ return false;
+ }
+
+ return true;
}
static void winusbx_exit(void)
{
- if (WinUSBX_handle != NULL) {
- FreeLibrary(WinUSBX_handle);
- WinUSBX_handle = NULL;
+ bool loaded = false;
+ HMODULE hDll;
- /* Reset the WinUSBX API structures */
- memset(&WinUSBX, 0, sizeof(WinUSBX));
+ hDll = WinUSBX[SUB_API_LIBUSBK].hDll;
+ if (hDll != NULL) {
+ FreeLibrary(hDll);
+ loaded = true;
+ }
+
+ hDll = WinUSBX[SUB_API_WINUSB].hDll;
+ if (hDll != NULL) {
+ FreeLibrary(hDll);
+ loaded = true;
}
+
+ // Reset the WinUSBX API structures if something was loaded
+ if (loaded)
+ memset(&WinUSBX, 0, sizeof(WinUSBX));
}
// NB: open and close must ensure that they only handle interface of
@@ -2131,7 +2078,6 @@ static void winusbx_exit(void)
// composite_open(), with interfaces belonging to different APIs
static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
{
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
HANDLE file_handle;
@@ -2144,9 +2090,9 @@ static int winusbx_open(int sub_api, struct libusb_device_handle *dev_handle)
if ((priv->usb_interface[i].path != NULL)
&& (priv->usb_interface[i].apib->id == USB_API_WINUSBX)) {
file_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
+ NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (file_handle == INVALID_HANDLE_VALUE) {
- usbi_err(ctx, "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0));
+ usbi_err(HANDLE_CTX(dev_handle), "could not open device %s (interface %d): %s", priv->usb_interface[i].path, i, windows_error_str(0));
switch (GetLastError()) {
case ERROR_FILE_NOT_FOUND: // The device was disconnected
return LIBUSB_ERROR_NO_DEVICE;
@@ -2173,7 +2119,7 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
if (sub_api == SUB_API_NOTSET)
sub_api = priv->sub_api;
- if (!WinUSBX[sub_api].initialized)
+ if (WinUSBX[sub_api].hDll == NULL)
return;
if (priv->apib->id == USB_API_COMPOSITE) {
@@ -2220,7 +2166,7 @@ static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle
CHECK_WINUSBX_AVAILABLE(sub_api);
- // With handle and enpoints set (in parent), we can setup the default pipe properties
+ // With handle and endpoints set (in parent), we can setup the default pipe properties
// see http://download.microsoft.com/download/D/1/D/D1DD7745-426B-4CC3-A269-ABBBE427C0EF/DVC-T705_DDC08.pptx
for (i = -1; i < priv->usb_interface[iface].nb_endpoints; i++) {
endpoint_address = (i == -1) ? 0 : priv->usb_interface[iface].endpoint[i];
@@ -2263,7 +2209,7 @@ static int winusbx_configure_endpoints(int sub_api, struct libusb_device_handle
static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
{
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
+ struct libusb_context *ctx = HANDLE_CTX(dev_handle);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
bool is_using_usbccgp = (priv->apib->id == USB_API_COMPOSITE);
@@ -2313,7 +2259,7 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
if (strncmp(dev_path_no_guid, priv->usb_interface[iface].path, strlen(dev_path_no_guid)) == 0) {
file_handle = CreateFileA(filter_path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
+ NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (file_handle != INVALID_HANDLE_VALUE) {
if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
// Replace the existing file handle with the working one
@@ -2467,12 +2413,11 @@ static int interface_by_endpoint(struct winusb_device_priv *priv,
static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
PWINUSB_SETUP_PACKET setup = (PWINUSB_SETUP_PACKET)transfer->buffer;
- ULONG size, transferred;
+ ULONG size;
HANDLE winusb_handle;
OVERLAPPED *overlapped;
int current_interface;
@@ -2497,26 +2442,25 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it
usbi_dbg("will use interface %d", current_interface);
- transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
- overlapped = transfer_priv->pollable_fd.overlapped;
+ winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
+ set_transfer_priv_handle(itransfer, handle_priv->interface_handle[current_interface].dev_handle);
+ overlapped = get_transfer_priv_overlapped(itransfer);
// Sending of set configuration control requests from WinUSB creates issues, except when using libusb0.sys
if (sub_api != SUB_API_LIBUSB0
&& (LIBUSB_REQ_TYPE(setup->RequestType) == LIBUSB_REQUEST_TYPE_STANDARD)
&& (setup->Request == LIBUSB_REQUEST_SET_CONFIGURATION)) {
if (setup->Value != priv->active_config) {
- usbi_warn(ctx, "cannot set configuration other than the default one");
+ usbi_warn(TRANSFER_CTX(transfer), "cannot set configuration other than the default one");
return LIBUSB_ERROR_INVALID_PARAM;
}
windows_force_sync_completion(overlapped, 0);
} else {
- if (!WinUSBX[sub_api].ControlTransfer(winusb_handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, &transferred, overlapped)) {
+ if (!WinUSBX[sub_api].ControlTransfer(winusb_handle, *setup, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, size, NULL, overlapped)) {
if (GetLastError() != ERROR_IO_PENDING) {
- usbi_warn(ctx, "ControlTransfer failed: %s", windows_error_str(0));
+ usbi_warn(TRANSFER_CTX(transfer), "ControlTransfer failed: %s", windows_error_str(0));
return LIBUSB_ERROR_IO;
}
- } else {
- windows_force_sync_completion(overlapped, transferred);
}
}
@@ -2527,7 +2471,6 @@ static int winusbx_submit_control_transfer(int sub_api, struct usbi_transfer *it
static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
{
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
HANDLE winusb_handle;
@@ -2539,37 +2482,18 @@ static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_ha
winusb_handle = handle_priv->interface_handle[iface].api_handle;
if (!HANDLE_VALID(winusb_handle)) {
- usbi_err(ctx, "interface must be claimed first");
+ usbi_err(HANDLE_CTX(dev_handle), "interface must be claimed first");
return LIBUSB_ERROR_NOT_FOUND;
}
if (!WinUSBX[sub_api].SetCurrentAlternateSetting(winusb_handle, (UCHAR)altsetting)) {
- usbi_err(ctx, "SetCurrentAlternateSetting failed: %s", windows_error_str(0));
+ usbi_err(HANDLE_CTX(dev_handle), "SetCurrentAlternateSetting failed: %s", windows_error_str(0));
return LIBUSB_ERROR_IO;
}
return LIBUSB_SUCCESS;
}
-static enum libusb_transfer_status usbd_status_to_libusb_transfer_status(USBD_STATUS status)
-{
- if (USBD_SUCCESS(status))
- return LIBUSB_TRANSFER_COMPLETED;
-
- switch (status) {
- case USBD_STATUS_TIMEOUT:
- return LIBUSB_TRANSFER_TIMED_OUT;
- case USBD_STATUS_CANCELED:
- return LIBUSB_TRANSFER_CANCELLED;
- case USBD_STATUS_ENDPOINT_HALTED:
- return LIBUSB_TRANSFER_STALL;
- case USBD_STATUS_DEVICE_GONE:
- return LIBUSB_TRANSFER_NO_DEVICE;
- default:
- usbi_dbg("USBD_STATUS 0x%08lx translated to LIBUSB_TRANSFER_ERROR", ULONG_CAST(status));
- return LIBUSB_TRANSFER_ERROR;
- }
-}
static void WINAPI winusbx_native_iso_transfer_continue_stream_callback(struct libusb_transfer *transfer)
{
@@ -2578,27 +2502,24 @@ static void WINAPI winusbx_native_iso_transfer_continue_stream_callback(struct l
// The role of this callback is to fallback to ContinueStream = FALSE if the transfer
// did not succeed.
- struct winusb_transfer_priv *transfer_priv = (struct winusb_transfer_priv *)
- usbi_transfer_get_os_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer));
- BOOL fallback = (transfer->status != LIBUSB_TRANSFER_COMPLETED);
+ struct winusb_transfer_priv *transfer_priv =
+ get_winusb_transfer_priv(LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer));
+ bool fallback = (transfer->status != LIBUSB_TRANSFER_COMPLETED);
int idx;
// Restore the user callback
transfer->callback = transfer_priv->iso_user_callback;
- for (idx = 0; idx < transfer->num_iso_packets && !fallback; ++idx) {
- if (transfer->iso_packet_desc[idx].status != LIBUSB_TRANSFER_COMPLETED) {
- fallback = TRUE;
- }
+ for (idx = 0; idx < transfer->num_iso_packets && !fallback; idx++) {
+ if (transfer->iso_packet_desc[idx].status != LIBUSB_TRANSFER_COMPLETED)
+ fallback = true;
}
if (!fallback) {
// If the transfer was successful, we restore the user callback and call it.
- if (transfer->callback) {
+ if (transfer->callback)
transfer->callback(transfer);
- }
- }
- else {
+ } else {
// If the transfer wasn't successful we reschedule the transfer while forcing it
// not to continue the stream. This might results in a 5-ms delay.
transfer_priv->iso_break_stream = TRUE;
@@ -2608,27 +2529,27 @@ static void WINAPI winusbx_native_iso_transfer_continue_stream_callback(struct l
static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
HANDLE winusb_handle;
OVERLAPPED *overlapped;
- bool ret;
+ BOOL ret;
int current_interface;
CHECK_WINUSBX_AVAILABLE(sub_api);
current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
if (current_interface < 0) {
- usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
+ usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
return LIBUSB_ERROR_NOT_FOUND;
- } else {
- usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
}
- transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
- overlapped = transfer_priv->pollable_fd.overlapped;
+ usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
+
+ winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
+ set_transfer_priv_handle(itransfer, handle_priv->interface_handle[current_interface].dev_handle);
+ overlapped = get_transfer_priv_overlapped(itransfer);
if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) {
int i;
@@ -2636,6 +2557,11 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
size_t iso_ctx_size;
PKISO_CONTEXT iso_context;
+ if (WinUSBX[sub_api].IsoReadPipe == NULL) {
+ usbi_warn(TRANSFER_CTX(transfer), "libusbK DLL does not support isoch transfers");
+ return LIBUSB_ERROR_NOT_SUPPORTED;
+ }
+
iso_ctx_size = sizeof(KISO_CONTEXT) + (transfer->num_iso_packets * sizeof(KISO_PACKET));
transfer_priv->iso_context = iso_context = calloc(1, iso_ctx_size);
if (transfer_priv->iso_context == NULL)
@@ -2660,42 +2586,29 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
ret = WinUSBX[sub_api].IsoWritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, overlapped, iso_context);
}
- if (!ret) {
- if (GetLastError() != ERROR_IO_PENDING) {
- usbi_err(ctx, "IsoReadPipe/IsoWritePipe failed: %s", windows_error_str(0));
- return LIBUSB_ERROR_IO;
- }
- } else {
- windows_force_sync_completion(overlapped, (ULONG)transfer->length);
+ if (!ret && GetLastError() != ERROR_IO_PENDING) {
+ usbi_err(TRANSFER_CTX(transfer), "IsoReadPipe/IsoWritePipe failed: %s", windows_error_str(0));
+ return LIBUSB_ERROR_IO;
}
transfer_priv->interface_number = (uint8_t)current_interface;
return LIBUSB_SUCCESS;
- }
- else if (sub_api == SUB_API_WINUSB) {
+ } else if (sub_api == SUB_API_WINUSB) {
WINUSB_PIPE_INFORMATION_EX pipe_info_ex = { 0 };
WINUSB_ISOCH_BUFFER_HANDLE buffer_handle;
ULONG iso_transfer_size_multiple;
int out_transfer_length = 0;
int idx;
-# define WINUSBX_CHECK_API_SUPPORTED(API) \
- if (WinUSBX[sub_api].API == NULL) \
- { \
- usbi_dbg(#API " isn't available"); \
- return LIBUSB_ERROR_NOT_SUPPORTED; \
- }
-
// Depending on the version of Microsoft WinUSB, isochronous transfers may not be supported.
- WINUSBX_CHECK_API_SUPPORTED(RegisterIsochBuffer);
- WINUSBX_CHECK_API_SUPPORTED(ReadIsochPipeAsap);
- WINUSBX_CHECK_API_SUPPORTED(WriteIsochPipeAsap);
- WINUSBX_CHECK_API_SUPPORTED(UnregisterIsochBuffer);
- WINUSBX_CHECK_API_SUPPORTED(QueryPipeEx);
+ if (WinUSBX[sub_api].ReadIsochPipeAsap == NULL) {
+ usbi_warn(TRANSFER_CTX(transfer), "WinUSB DLL does not support isoch transfers");
+ return LIBUSB_ERROR_NOT_SUPPORTED;
+ }
if (sizeof(struct libusb_iso_packet_descriptor) != sizeof(USBD_ISO_PACKET_DESCRIPTOR)) {
- usbi_dbg("The size of Microsoft WinUsb and libusb isochronous packet descriptor doesn't match.");
+ usbi_err(TRANSFER_CTX(transfer), "size of WinUsb and libusb isoch packet descriptors don't match");
return LIBUSB_ERROR_NOT_SUPPORTED;
}
@@ -2703,18 +2616,17 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
for (idx = 0; idx < priv->usb_interface[current_interface].nb_endpoints; ++idx) {
ret = WinUSBX[sub_api].QueryPipeEx(winusb_handle, (UINT8)priv->usb_interface[current_interface].current_altsetting, (UCHAR)idx, &pipe_info_ex);
if (!ret) {
- usbi_dbg("Couldn't query interface settings for USB pipe with index %d. Error: %s", idx, windows_error_str(0));
+ usbi_err(TRANSFER_CTX(transfer), "couldn't query interface settings for USB pipe with index %d. Error: %s", idx, windows_error_str(0));
return LIBUSB_ERROR_NOT_FOUND;
}
- if (pipe_info_ex.PipeId == transfer->endpoint && pipe_info_ex.PipeType == UsbdPipeTypeIsochronous) {
+ if (pipe_info_ex.PipeId == transfer->endpoint && pipe_info_ex.PipeType == UsbdPipeTypeIsochronous)
break;
- }
}
// Make sure we found the index.
- if (idx >= priv->usb_interface[current_interface].nb_endpoints) {
- usbi_dbg("Couldn't find the isochronous endpoint %02x.", transfer->endpoint);
+ if (idx == priv->usb_interface[current_interface].nb_endpoints) {
+ usbi_err(TRANSFER_CTX(transfer), "couldn't find isoch endpoint 0x%02x", transfer->endpoint);
return LIBUSB_ERROR_NOT_FOUND;
}
@@ -2722,27 +2634,25 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
int interval = pipe_info_ex.Interval;
// For high-speed and SuperSpeed device, the interval is 2**(bInterval-1).
- if (libusb_get_device_speed(libusb_get_device(transfer->dev_handle)) >= LIBUSB_SPEED_HIGH) {
+ if (transfer->dev_handle->dev->speed >= LIBUSB_SPEED_HIGH)
interval = (1 << (pipe_info_ex.Interval - 1));
- }
- // WinUSB only supports isochronous transfers spanning a full USB frames. Later, we might be smarter about this
+ // WinUSB only supports isoch transfers spanning a full USB frames. Later, we might be smarter about this
// and allocate a temporary buffer. However, this is harder than it seems as its destruction would depend on overlapped
// IO...
iso_transfer_size_multiple = (pipe_info_ex.MaximumBytesPerInterval * 8) / interval;
if (transfer->length % iso_transfer_size_multiple != 0) {
- usbi_dbg("The length of isochronous buffer must be a multiple of the MaximumBytesPerInterval * 8 / Interval");
+ usbi_err(TRANSFER_CTX(transfer), "length of isoch buffer must be a multiple of the MaximumBytesPerInterval * 8 / Interval");
return LIBUSB_ERROR_INVALID_PARAM;
}
- }
- else {
- // If this is an OUT transfer, we make sure the isochronous packets are contiguous as this isn't supported otherwise.
- BOOL size_should_be_zero = FALSE;
- out_transfer_length = 0;
+ } else {
+ // If this is an OUT transfer, we make sure the isoch packets are contiguous as this isn't supported otherwise.
+ bool size_should_be_zero = false;
+
for (idx = 0; idx < transfer->num_iso_packets; ++idx) {
if ((size_should_be_zero && transfer->iso_packet_desc[idx].length != 0) ||
(transfer->iso_packet_desc[idx].length != pipe_info_ex.MaximumBytesPerInterval && idx + 1 < transfer->num_iso_packets && transfer->iso_packet_desc[idx + 1].length > 0)) {
- usbi_dbg("Isochronous packets for OUT transfer with Microsoft WinUSB must be contiguous in memory.");
+ usbi_err(TRANSFER_CTX(transfer), "isoch packets for OUT transfer with WinUSB must be contiguous in memory");
return LIBUSB_ERROR_INVALID_PARAM;
}
@@ -2755,15 +2665,15 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
if (WinUSBX[sub_api].UnregisterIsochBuffer(transfer_priv->isoch_buffer_handle)) {
transfer_priv->isoch_buffer_handle = NULL;
} else {
- usbi_dbg("Couldn't unregister the Microsoft WinUSB isochronous buffer: %s", windows_error_str(0));
+ usbi_err(TRANSFER_CTX(transfer), "failed to unregister WinUSB isoch buffer: %s", windows_error_str(0));
return LIBUSB_ERROR_OTHER;
}
}
- // Register the isochronous buffer to the operating system.
+ // Register the isoch buffer to the operating system.
ret = WinUSBX[sub_api].RegisterIsochBuffer(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, &buffer_handle);
if (!ret) {
- usbi_dbg("Microsoft WinUSB refused to allocate an isochronous buffer.");
+ usbi_err(TRANSFER_CTX(transfer), "failed to register WinUSB isoch buffer: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_MEM;
}
@@ -2780,36 +2690,22 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
}
// Initiate the transfers.
- if (IS_XFERIN(transfer)) {
+ if (IS_XFERIN(transfer))
ret = WinUSBX[sub_api].ReadIsochPipeAsap(buffer_handle, 0, transfer->length, !transfer_priv->iso_break_stream, transfer->num_iso_packets, (PUSBD_ISO_PACKET_DESCRIPTOR)transfer->iso_packet_desc, overlapped);
- }
- else {
+ else
ret = WinUSBX[sub_api].WriteIsochPipeAsap(buffer_handle, 0, out_transfer_length, !transfer_priv->iso_break_stream, overlapped);
+
+ if (!ret && GetLastError() != ERROR_IO_PENDING) {
+ usbi_err(TRANSFER_CTX(transfer), "ReadIsochPipeAsap/WriteIsochPipeAsap failed: %s", windows_error_str(0));
+ if (!WinUSBX[sub_api].UnregisterIsochBuffer(buffer_handle))
+ usbi_warn(TRANSFER_CTX(transfer), "failed to unregister WinUSB isoch buffer: %s", windows_error_str(0));
+ return LIBUSB_ERROR_IO;
}
// Restore the ContinueStream parameter to TRUE.
transfer_priv->iso_break_stream = FALSE;
- if (!ret) {
- if (GetLastError() == ERROR_IO_PENDING) {
- transfer_priv->isoch_buffer_handle = buffer_handle;
- } else {
- usbi_err(ctx, "ReadIsochPipeAsap/WriteIsochPipeAsap failed: %s", windows_error_str(0));
- if (WinUSBX[sub_api].UnregisterIsochBuffer(buffer_handle)) {
- transfer_priv->isoch_buffer_handle = NULL;
- return LIBUSB_ERROR_IO;
- } else {
- usbi_dbg("Couldn't unregister the Microsoft WinUSB isochronous buffer: %s", windows_error_str(0));
- return LIBUSB_ERROR_OTHER;
- }
- }
- } else {
- windows_force_sync_completion(overlapped, (ULONG)transfer->length);
- if (!WinUSBX[sub_api].UnregisterIsochBuffer(buffer_handle)) {
- usbi_dbg("Couldn't unregister the Microsoft WinUSB isochronous buffer: %s", windows_error_str(0));
- return LIBUSB_ERROR_OTHER;
- }
- }
+ transfer_priv->isoch_buffer_handle = buffer_handle;
transfer_priv->interface_number = (uint8_t)current_interface;
@@ -2823,27 +2719,27 @@ static int winusbx_submit_iso_transfer(int sub_api, struct usbi_transfer *itrans
static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
HANDLE winusb_handle;
OVERLAPPED *overlapped;
- bool ret;
+ BOOL ret;
int current_interface;
CHECK_WINUSBX_AVAILABLE(sub_api);
current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
if (current_interface < 0) {
- usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
+ usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
return LIBUSB_ERROR_NOT_FOUND;
}
usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
- transfer_priv->handle = winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
- overlapped = transfer_priv->pollable_fd.overlapped;
+ winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
+ set_transfer_priv_handle(itransfer, handle_priv->interface_handle[current_interface].dev_handle);
+ overlapped = get_transfer_priv_overlapped(itransfer);
if (IS_XFERIN(transfer)) {
usbi_dbg("reading %d bytes", transfer->length);
@@ -2853,13 +2749,9 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran
ret = WinUSBX[sub_api].WritePipe(winusb_handle, transfer->endpoint, transfer->buffer, transfer->length, NULL, overlapped);
}
- if (!ret) {
- if (GetLastError() != ERROR_IO_PENDING) {
- usbi_err(ctx, "ReadPipe/WritePipe failed: %s", windows_error_str(0));
- return LIBUSB_ERROR_IO;
- }
- } else {
- windows_force_sync_completion(overlapped, (ULONG)transfer->length);
+ if (!ret && GetLastError() != ERROR_IO_PENDING) {
+ usbi_err(TRANSFER_CTX(transfer), "ReadPipe/WritePipe failed: %s", windows_error_str(0));
+ return LIBUSB_ERROR_IO;
}
transfer_priv->interface_number = (uint8_t)current_interface;
@@ -2869,7 +2761,6 @@ static int winusbx_submit_bulk_transfer(int sub_api, struct usbi_transfer *itran
static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
{
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
HANDLE winusb_handle;
@@ -2879,7 +2770,7 @@ static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_hand
current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
if (current_interface < 0) {
- usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
+ usbi_err(HANDLE_CTX(dev_handle), "unable to match endpoint to an open interface - cannot clear");
return LIBUSB_ERROR_NOT_FOUND;
}
@@ -2887,62 +2778,29 @@ static int winusbx_clear_halt(int sub_api, struct libusb_device_handle *dev_hand
winusb_handle = handle_priv->interface_handle[current_interface].api_handle;
if (!WinUSBX[sub_api].ResetPipe(winusb_handle, endpoint)) {
- usbi_err(ctx, "ResetPipe failed: %s", windows_error_str(0));
+ usbi_err(HANDLE_CTX(dev_handle), "ResetPipe failed: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_DEVICE;
}
return LIBUSB_SUCCESS;
}
-/*
- * from http://www.winvistatips.com/winusb-bugchecks-t335323.html (confirmed
- * through testing as well):
- * "You can not call WinUsb_AbortPipe on control pipe. You can possibly cancel
- * the control transfer using CancelIo"
- */
-static int winusbx_abort_control(int sub_api, struct usbi_transfer *itransfer)
-{
- UNUSED(sub_api);
- UNUSED(itransfer);
- // Cancelling of the I/O is done in the parent
- return LIBUSB_SUCCESS;
-}
-
-static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
+static int winusbx_cancel_transfer(int sub_api, struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
+ int current_interface = transfer_priv->interface_number;
HANDLE handle;
- int current_interface;
CHECK_WINUSBX_AVAILABLE(sub_api);
- current_interface = transfer_priv->interface_number;
- if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
- usbi_err(ctx, "program assertion failed: invalid interface_number");
- return LIBUSB_ERROR_NOT_FOUND;
- }
usbi_dbg("will use interface %d", current_interface);
- if (WinUSBX[sub_api].CancelIoEx_supported) {
- // Try to use CancelIoEx if available to cancel just a single transfer
- handle = handle_priv->interface_handle[current_interface].dev_handle;
- if (CancelIoEx(handle, transfer_priv->pollable_fd.overlapped))
- return LIBUSB_SUCCESS;
- else if (GetLastError() == ERROR_NOT_FOUND)
- return LIBUSB_ERROR_NOT_FOUND;
-
- // Not every driver implements the necessary functionality for CancelIoEx
- usbi_warn(ctx, "CancelIoEx not supported for sub API %s", winusbx_driver_names[sub_api]);
- WinUSBX[sub_api].CancelIoEx_supported = false;
- }
-
handle = handle_priv->interface_handle[current_interface].api_handle;
if (!WinUSBX[sub_api].AbortPipe(handle, transfer->endpoint)) {
- usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0));
+ usbi_err(TRANSFER_CTX(transfer), "AbortPipe failed: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_DEVICE;
}
@@ -2960,7 +2818,6 @@ static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
// TODO: (post hotplug): see if we can force eject the device and redetect it (reuse hotplug?)
static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
{
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
HANDLE winusb_handle;
@@ -2975,24 +2832,24 @@ static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_ha
for (j = 0; j < priv->usb_interface[i].nb_endpoints; j++) {
usbi_dbg("resetting ep %02X", priv->usb_interface[i].endpoint[j]);
if (!WinUSBX[sub_api].AbortPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))
- usbi_err(ctx, "AbortPipe (pipe address %02X) failed: %s",
+ usbi_err(HANDLE_CTX(dev_handle), "AbortPipe (pipe address %02X) failed: %s",
priv->usb_interface[i].endpoint[j], windows_error_str(0));
// FlushPipe seems to fail on OUT pipes
if (IS_EPIN(priv->usb_interface[i].endpoint[j])
&& (!WinUSBX[sub_api].FlushPipe(winusb_handle, priv->usb_interface[i].endpoint[j])))
- usbi_err(ctx, "FlushPipe (pipe address %02X) failed: %s",
+ usbi_err(HANDLE_CTX(dev_handle), "FlushPipe (pipe address %02X) failed: %s",
priv->usb_interface[i].endpoint[j], windows_error_str(0));
if (!WinUSBX[sub_api].ResetPipe(winusb_handle, priv->usb_interface[i].endpoint[j]))
- usbi_err(ctx, "ResetPipe (pipe address %02X) failed: %s",
+ usbi_err(HANDLE_CTX(dev_handle), "ResetPipe (pipe address %02X) failed: %s",
priv->usb_interface[i].endpoint[j], windows_error_str(0));
}
}
}
// libusbK & libusb0 have the ability to issue an actual device reset
- if (WinUSBX[sub_api].ResetDevice != NULL) {
+ if ((sub_api != SUB_API_WINUSB) && (WinUSBX[sub_api].ResetDevice != NULL)) {
winusb_handle = handle_priv->interface_handle[0].api_handle;
if (HANDLE_VALID(winusb_handle))
WinUSBX[sub_api].ResetDevice(winusb_handle);
@@ -3001,21 +2858,17 @@ static int winusbx_reset_device(int sub_api, struct libusb_device_handle *dev_ha
return LIBUSB_SUCCESS;
}
-static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
+static enum libusb_transfer_status winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
- PKISO_CONTEXT iso_context;
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
int i;
if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS) {
- CHECK_WINUSBX_AVAILABLE(sub_api);
-
// for isochronous, need to copy the individual iso packet actual_lengths and statuses
if ((sub_api == SUB_API_LIBUSBK) || (sub_api == SUB_API_LIBUSB0)) {
// iso only supported on libusbk-based backends for now
- iso_context = transfer_priv->iso_context;
+ PKISO_CONTEXT iso_context = transfer_priv->iso_context;
for (i = 0; i < transfer->num_iso_packets; i++) {
transfer->iso_packet_desc[i].actual_length = iso_context->IsoPackets[i].actual_length;
// TODO translate USDB_STATUS codes http://msdn.microsoft.com/en-us/library/ff539136(VS.85).aspx to libusb_transfer_status
@@ -3026,31 +2879,28 @@ static int winusbx_copy_transfer_data(int sub_api, struct usbi_transfer *itransf
/* Convert isochronous packet descriptor between Windows and libusb representation.
* Both representation are guaranteed to have the same length in bytes.*/
PUSBD_ISO_PACKET_DESCRIPTOR usbd_iso_packet_desc = (PUSBD_ISO_PACKET_DESCRIPTOR)transfer->iso_packet_desc;
- for (i = 0; i < transfer->num_iso_packets; ++i)
- {
- int length = (i < transfer->num_iso_packets - 1) ? (usbd_iso_packet_desc[i + 1].Offset - usbd_iso_packet_desc[i].Offset) : usbd_iso_packet_desc[i].Length;
- int actual_length = usbd_iso_packet_desc[i].Length;
+ for (i = 0; i < transfer->num_iso_packets; i++) {
+ unsigned int packet_length = (i < transfer->num_iso_packets - 1) ? (usbd_iso_packet_desc[i + 1].Offset - usbd_iso_packet_desc[i].Offset) : usbd_iso_packet_desc[i].Length;
+ unsigned int actual_length = usbd_iso_packet_desc[i].Length;
USBD_STATUS status = usbd_iso_packet_desc[i].Status;
- transfer->iso_packet_desc[i].length = length;
+ transfer->iso_packet_desc[i].length = packet_length;
transfer->iso_packet_desc[i].actual_length = actual_length;
transfer->iso_packet_desc[i].status = usbd_status_to_libusb_transfer_status(status);
}
- }
- else {
- for (i = 0; i < transfer->num_iso_packets; ++i)
- {
+ } else {
+ for (i = 0; i < transfer->num_iso_packets; i++) {
transfer->iso_packet_desc[i].status = LIBUSB_TRANSFER_COMPLETED;
}
}
} else {
// This should only occur if backend is not set correctly or other backend isoc is partially implemented
PRINT_UNSUPPORTED_API(copy_transfer_data);
- return LIBUSB_ERROR_NOT_SUPPORTED;
+ return LIBUSB_TRANSFER_ERROR;
}
}
- itransfer->transferred += io_size;
+ itransfer->transferred += (int)length;
return LIBUSB_TRANSFER_COMPLETED;
}
@@ -3072,7 +2922,7 @@ static int _hid_wcslen(WCHAR *str)
return i;
}
-static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
+static int _hid_get_device_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
{
struct libusb_device_descriptor d;
@@ -3083,12 +2933,12 @@ static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, s
d.bDeviceSubClass = 0;
d.bDeviceProtocol = 0;
d.bMaxPacketSize0 = 64; /* fix this! */
- d.idVendor = (uint16_t)dev->vid;
- d.idProduct = (uint16_t)dev->pid;
+ d.idVendor = (uint16_t)hid_priv->vid;
+ d.idProduct = (uint16_t)hid_priv->pid;
d.bcdDevice = 0x0100;
- d.iManufacturer = dev->string_index[0];
- d.iProduct = dev->string_index[1];
- d.iSerialNumber = dev->string_index[2];
+ d.iManufacturer = hid_priv->string_index[0];
+ d.iProduct = hid_priv->string_index[1];
+ d.iSerialNumber = hid_priv->string_index[2];
d.bNumConfigurations = 1;
if (*size > LIBUSB_DT_DEVICE_SIZE)
@@ -3098,7 +2948,7 @@ static int _hid_get_device_descriptor(struct hid_device_priv *dev, void *data, s
return LIBUSB_COMPLETED;
}
-static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
+static int _hid_get_config_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
{
char num_endpoints = 0;
size_t config_total_len = 0;
@@ -3109,9 +2959,9 @@ static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, s
struct libusb_endpoint_descriptor *ed;
size_t tmp_size;
- if (dev->input_report_size)
+ if (hid_priv->input_report_size)
num_endpoints++;
- if (dev->output_report_size)
+ if (hid_priv->output_report_size)
num_endpoints++;
config_total_len = LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE
@@ -3145,24 +2995,24 @@ static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, s
id->iInterface = 0;
tmp_size = LIBUSB_DT_HID_SIZE;
- _hid_get_hid_descriptor(dev, hd, &tmp_size);
+ _hid_get_hid_descriptor(hid_priv, hd, &tmp_size);
- if (dev->input_report_size) {
+ if (hid_priv->input_report_size) {
ed->bLength = LIBUSB_DT_ENDPOINT_SIZE;
ed->bDescriptorType = LIBUSB_DT_ENDPOINT;
ed->bEndpointAddress = HID_IN_EP;
ed->bmAttributes = 3;
- ed->wMaxPacketSize = dev->input_report_size - 1;
+ ed->wMaxPacketSize = hid_priv->input_report_size - 1;
ed->bInterval = 10;
ed = (struct libusb_endpoint_descriptor *)((char *)ed + LIBUSB_DT_ENDPOINT_SIZE);
}
- if (dev->output_report_size) {
+ if (hid_priv->output_report_size) {
ed->bLength = LIBUSB_DT_ENDPOINT_SIZE;
ed->bDescriptorType = LIBUSB_DT_ENDPOINT;
ed->bEndpointAddress = HID_OUT_EP;
ed->bmAttributes = 3;
- ed->wMaxPacketSize = dev->output_report_size - 1;
+ ed->wMaxPacketSize = hid_priv->output_report_size - 1;
ed->bInterval = 10;
}
@@ -3173,7 +3023,7 @@ static int _hid_get_config_descriptor(struct hid_device_priv *dev, void *data, s
return LIBUSB_COMPLETED;
}
-static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index,
+static int _hid_get_string_descriptor(struct hid_device_priv *hid_priv, int _index,
void *data, size_t *size, HANDLE hid_handle)
{
void *tmp = NULL;
@@ -3184,17 +3034,14 @@ static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index,
/* language ID, EN-US */
char string_langid[] = {0x09, 0x04};
- if ((*size < 2) || (*size > 255))
- return LIBUSB_ERROR_OVERFLOW;
-
if (_index == 0) {
tmp = string_langid;
tmp_size = sizeof(string_langid) + 2;
} else {
for (i = 0; i < 3; i++) {
- if (_index == (dev->string_index[i])) {
- tmp = dev->string[i];
- tmp_size = (_hid_wcslen(dev->string[i]) + 1) * sizeof(WCHAR);
+ if (_index == (hid_priv->string_index[i])) {
+ tmp = hid_priv->string[i];
+ tmp_size = (_hid_wcslen(hid_priv->string[i]) + 1) * sizeof(WCHAR);
break;
}
}
@@ -3221,13 +3068,13 @@ static int _hid_get_string_descriptor(struct hid_device_priv *dev, int _index,
return LIBUSB_COMPLETED;
}
-static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
+static int _hid_get_hid_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
{
struct libusb_hid_descriptor d;
uint8_t tmp[MAX_HID_DESCRIPTOR_SIZE];
size_t report_len = MAX_HID_DESCRIPTOR_SIZE;
- _hid_get_report_descriptor(dev, tmp, &report_len);
+ _hid_get_report_descriptor(hid_priv, tmp, &report_len);
d.bLength = LIBUSB_DT_HID_SIZE;
d.bDescriptorType = LIBUSB_DT_HID;
@@ -3244,19 +3091,19 @@ static int _hid_get_hid_descriptor(struct hid_device_priv *dev, void *data, size
return LIBUSB_COMPLETED;
}
-static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, size_t *size)
+static int _hid_get_report_descriptor(struct hid_device_priv *hid_priv, void *data, size_t *size)
{
uint8_t d[MAX_HID_DESCRIPTOR_SIZE];
size_t i = 0;
/* usage page */
- d[i++] = 0x06; d[i++] = dev->usagePage & 0xFF; d[i++] = dev->usagePage >> 8;
+ d[i++] = 0x06; d[i++] = hid_priv->usagePage & 0xFF; d[i++] = hid_priv->usagePage >> 8;
/* usage */
- d[i++] = 0x09; d[i++] = (uint8_t)dev->usage;
+ d[i++] = 0x09; d[i++] = (uint8_t)hid_priv->usage;
/* start collection (application) */
d[i++] = 0xA1; d[i++] = 0x01;
/* input report */
- if (dev->input_report_size) {
+ if (hid_priv->input_report_size) {
/* usage (vendor defined) */
d[i++] = 0x09; d[i++] = 0x01;
/* logical minimum (0) */
@@ -3266,12 +3113,12 @@ static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, s
/* report size (8 bits) */
d[i++] = 0x75; d[i++] = 0x08;
/* report count */
- d[i++] = 0x95; d[i++] = (uint8_t)dev->input_report_size - 1;
+ d[i++] = 0x95; d[i++] = (uint8_t)hid_priv->input_report_size - 1;
/* input (data, variable, absolute) */
d[i++] = 0x81; d[i++] = 0x00;
}
/* output report */
- if (dev->output_report_size) {
+ if (hid_priv->output_report_size) {
/* usage (vendor defined) */
d[i++] = 0x09; d[i++] = 0x02;
/* logical minimum (0) */
@@ -3281,12 +3128,12 @@ static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, s
/* report size (8 bits) */
d[i++] = 0x75; d[i++] = 0x08;
/* report count */
- d[i++] = 0x95; d[i++] = (uint8_t)dev->output_report_size - 1;
+ d[i++] = 0x95; d[i++] = (uint8_t)hid_priv->output_report_size - 1;
/* output (data, variable, absolute) */
d[i++] = 0x91; d[i++] = 0x00;
}
/* feature report */
- if (dev->feature_report_size) {
+ if (hid_priv->feature_report_size) {
/* usage (vendor defined) */
d[i++] = 0x09; d[i++] = 0x03;
/* logical minimum (0) */
@@ -3296,7 +3143,7 @@ static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, s
/* report size (8 bits) */
d[i++] = 0x75; d[i++] = 0x08;
/* report count */
- d[i++] = 0x95; d[i++] = (uint8_t)dev->feature_report_size - 1;
+ d[i++] = 0x95; d[i++] = (uint8_t)hid_priv->feature_report_size - 1;
/* feature (data, variable, absolute) */
d[i++] = 0xb2; d[i++] = 0x02; d[i++] = 0x01;
}
@@ -3311,32 +3158,33 @@ static int _hid_get_report_descriptor(struct hid_device_priv *dev, void *data, s
return LIBUSB_COMPLETED;
}
-static int _hid_get_descriptor(struct hid_device_priv *dev, HANDLE hid_handle, int recipient,
+static int _hid_get_descriptor(struct libusb_device *dev, HANDLE hid_handle, int recipient,
int type, int _index, void *data, size_t *size)
{
+ struct winusb_device_priv *priv = _device_priv(dev);
UNUSED(recipient);
switch (type) {
case LIBUSB_DT_DEVICE:
usbi_dbg("LIBUSB_DT_DEVICE");
- return _hid_get_device_descriptor(dev, data, size);
+ return _hid_get_device_descriptor(priv->hid, data, size);
case LIBUSB_DT_CONFIG:
usbi_dbg("LIBUSB_DT_CONFIG");
if (!_index)
- return _hid_get_config_descriptor(dev, data, size);
+ return _hid_get_config_descriptor(priv->hid, data, size);
return LIBUSB_ERROR_INVALID_PARAM;
case LIBUSB_DT_STRING:
usbi_dbg("LIBUSB_DT_STRING");
- return _hid_get_string_descriptor(dev, _index, data, size, hid_handle);
+ return _hid_get_string_descriptor(priv->hid, _index, data, size, hid_handle);
case LIBUSB_DT_HID:
usbi_dbg("LIBUSB_DT_HID");
if (!_index)
- return _hid_get_hid_descriptor(dev, data, size);
+ return _hid_get_hid_descriptor(priv->hid, data, size);
return LIBUSB_ERROR_INVALID_PARAM;
case LIBUSB_DT_REPORT:
usbi_dbg("LIBUSB_DT_REPORT");
if (!_index)
- return _hid_get_report_descriptor(dev, data, size);
+ return _hid_get_report_descriptor(priv->hid, data, size);
return LIBUSB_ERROR_INVALID_PARAM;
case LIBUSB_DT_PHYSICAL:
usbi_dbg("LIBUSB_DT_PHYSICAL");
@@ -3345,24 +3193,21 @@ static int _hid_get_descriptor(struct hid_device_priv *dev, HANDLE hid_handle, i
return LIBUSB_ERROR_OTHER;
}
- usbi_dbg("unsupported");
+ usbi_warn(DEVICE_CTX(dev), "unsupported");
return LIBUSB_ERROR_NOT_SUPPORTED;
}
-static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
- struct winusb_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
+static int _hid_get_report(struct libusb_device *dev, HANDLE hid_handle, int id, void *data,
+ struct winusb_transfer_priv *tp, size_t size, OVERLAPPED *overlapped, int report_type)
{
+ DWORD ioctl_code, expected_size = (DWORD)size;
uint8_t *buf;
- DWORD ioctl_code, read_size, expected_size = (DWORD)*size;
- int r = LIBUSB_SUCCESS;
-
- UNUSED(dev);
if (tp->hid_buffer != NULL)
- usbi_dbg("program assertion failed: hid_buffer is not NULL");
+ usbi_err(DEVICE_CTX(dev), "program assertion failed - hid_buffer is not NULL");
- if ((*size == 0) || (*size > MAX_HID_REPORT_SIZE)) {
- usbi_dbg("invalid size (%"PRIuPTR")", (uintptr_t)*size);
+ if ((size == 0) || (size > MAX_HID_REPORT_SIZE)) {
+ usbi_warn(DEVICE_CTX(dev), "invalid size (%"PRIuPTR")", (uintptr_t)size);
return LIBUSB_ERROR_INVALID_PARAM;
}
@@ -3374,7 +3219,7 @@ static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int i
ioctl_code = IOCTL_HID_GET_FEATURE;
break;
default:
- usbi_dbg("unknown HID report type %d", report_type);
+ usbi_warn(DEVICE_CTX(dev), "unknown HID report type %d", report_type);
return LIBUSB_ERROR_INVALID_PARAM;
}
@@ -3386,64 +3231,37 @@ static int _hid_get_report(struct hid_device_priv *dev, HANDLE hid_handle, int i
buf[0] = (uint8_t)id; // Must be set always
usbi_dbg("report ID: 0x%02X", buf[0]);
- tp->hid_expected_size = expected_size;
- read_size = expected_size;
-
// NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
if (!DeviceIoControl(hid_handle, ioctl_code, buf, expected_size + 1,
- buf, expected_size + 1, &read_size, overlapped)) {
+ buf, expected_size + 1, NULL, overlapped)) {
if (GetLastError() != ERROR_IO_PENDING) {
- usbi_dbg("Failed to Read HID Report: %s", windows_error_str(0));
+ usbi_err(DEVICE_CTX(dev), "failed to read HID Report: %s", windows_error_str(0));
free(buf);
return LIBUSB_ERROR_IO;
}
- // Asynchronous wait
- tp->hid_buffer = buf;
- tp->hid_dest = data; // copy dest, as not necessarily the start of the transfer buffer
- return LIBUSB_SUCCESS;
}
- // Transfer completed synchronously => copy and discard extra buffer
- if (read_size == 0) {
- usbi_warn(NULL, "program assertion failed - read completed synchronously, but no data was read");
- *size = 0;
- } else {
- if (buf[0] != id)
- usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
-
- if ((size_t)read_size > expected_size) {
- r = LIBUSB_ERROR_OVERFLOW;
- usbi_dbg("OVERFLOW!");
- } else {
- r = LIBUSB_COMPLETED;
- }
-
- *size = MIN((size_t)read_size, *size);
- if (id == 0)
- memcpy(data, buf + 1, *size); // Discard report ID
- else
- memcpy(data, buf, *size);
- }
+ // Asynchronous wait
+ tp->hid_buffer = buf;
+ tp->hid_dest = data; // copy dest, as not necessarily the start of the transfer buffer
+ tp->hid_expected_size = expected_size;
- free(buf);
- return r;
+ return LIBUSB_SUCCESS;
}
-static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int id, void *data,
- struct winusb_transfer_priv *tp, size_t *size, OVERLAPPED *overlapped, int report_type)
+static int _hid_set_report(struct libusb_device *dev, HANDLE hid_handle, int id, void *data,
+ struct winusb_transfer_priv *tp, size_t size, OVERLAPPED *overlapped, int report_type)
{
- uint8_t *buf = NULL;
- DWORD ioctl_code, write_size = (DWORD)*size;
+ DWORD ioctl_code, write_size = (DWORD)size;
// If an id is reported, we must allow MAX_HID_REPORT_SIZE + 1
size_t max_report_size = MAX_HID_REPORT_SIZE + (id ? 1 : 0);
-
- UNUSED(dev);
+ uint8_t *buf;
if (tp->hid_buffer != NULL)
- usbi_dbg("program assertion failed: hid_buffer is not NULL");
+ usbi_err(DEVICE_CTX(dev), "program assertion failed - hid_buffer is not NULL");
- if ((*size == 0) || (*size > max_report_size)) {
- usbi_dbg("invalid size (%"PRIuPTR")", (uintptr_t)*size);
+ if ((size == 0) || (size > max_report_size)) {
+ usbi_warn(DEVICE_CTX(dev), "invalid size (%"PRIuPTR")", (uintptr_t)size);
return LIBUSB_ERROR_INVALID_PARAM;
}
@@ -3455,7 +3273,7 @@ static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int i
ioctl_code = IOCTL_HID_SET_FEATURE;
break;
default:
- usbi_dbg("unknown HID report type %d", report_type);
+ usbi_warn(DEVICE_CTX(dev), "unknown HID report type %d", report_type);
return LIBUSB_ERROR_INVALID_PARAM;
}
@@ -3471,40 +3289,33 @@ static int _hid_set_report(struct hid_device_priv *dev, HANDLE hid_handle, int i
if (id == 0) {
buf[0] = 0;
- memcpy(buf + 1, data, *size);
+ memcpy(buf + 1, data, size);
} else {
// This seems like a waste, but if we don't duplicate the
// data, we'll get issues when freeing hid_buffer
- memcpy(buf, data, *size);
+ memcpy(buf, data, size);
if (buf[0] != id)
- usbi_warn(NULL, "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
+ usbi_warn(DEVICE_CTX(dev), "mismatched report ID (data is %02X, parameter is %02X)", buf[0], id);
}
// NB: The size returned by DeviceIoControl doesn't include report IDs when not in use (0)
if (!DeviceIoControl(hid_handle, ioctl_code, buf, write_size,
- buf, write_size, &write_size, overlapped)) {
+ buf, write_size, NULL, overlapped)) {
if (GetLastError() != ERROR_IO_PENDING) {
- usbi_dbg("Failed to Write HID Output Report: %s", windows_error_str(0));
+ usbi_err(DEVICE_CTX(dev), "failed to write HID Output Report: %s", windows_error_str(0));
free(buf);
return LIBUSB_ERROR_IO;
}
- tp->hid_buffer = buf;
- tp->hid_dest = NULL;
- return LIBUSB_SUCCESS;
}
- // Transfer completed synchronously
- *size = write_size;
- if (write_size == 0)
- usbi_dbg("program assertion failed - write completed synchronously, but no data was written");
-
- free(buf);
- return LIBUSB_COMPLETED;
+ tp->hid_buffer = buf;
+ tp->hid_dest = NULL;
+ return LIBUSB_SUCCESS;
}
-static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, int request_type,
+static int _hid_class_request(struct libusb_device *dev, HANDLE hid_handle, int request_type,
int request, int value, int _index, void *data, struct winusb_transfer_priv *tp,
- size_t *size, OVERLAPPED *overlapped)
+ size_t size, OVERLAPPED *overlapped)
{
int report_type = (value >> 8) & 0xFF;
int report_id = value & 0xFF;
@@ -3524,32 +3335,30 @@ static int _hid_class_request(struct hid_device_priv *dev, HANDLE hid_handle, in
return LIBUSB_ERROR_INVALID_PARAM;
}
-
/*
* HID API functions
*/
-static int hid_init(struct libusb_context *ctx)
+static bool hid_init(struct libusb_context *ctx)
{
UNUSED(ctx);
DLL_GET_HANDLE(hid);
- DLL_LOAD_FUNC(hid, HidD_GetAttributes, TRUE);
- DLL_LOAD_FUNC(hid, HidD_GetHidGuid, TRUE);
- DLL_LOAD_FUNC(hid, HidD_GetPreparsedData, TRUE);
- DLL_LOAD_FUNC(hid, HidD_FreePreparsedData, TRUE);
- DLL_LOAD_FUNC(hid, HidD_GetManufacturerString, TRUE);
- DLL_LOAD_FUNC(hid, HidD_GetProductString, TRUE);
- DLL_LOAD_FUNC(hid, HidD_GetSerialNumberString, TRUE);
- DLL_LOAD_FUNC(hid, HidD_GetIndexedString, TRUE);
- DLL_LOAD_FUNC(hid, HidP_GetCaps, TRUE);
- DLL_LOAD_FUNC(hid, HidD_SetNumInputBuffers, TRUE);
- DLL_LOAD_FUNC(hid, HidD_GetPhysicalDescriptor, TRUE);
- DLL_LOAD_FUNC(hid, HidD_FlushQueue, TRUE);
- DLL_LOAD_FUNC(hid, HidP_GetValueCaps, TRUE);
-
- api_hid_available = true;
- return LIBUSB_SUCCESS;
+ DLL_LOAD_FUNC(hid, HidD_GetAttributes, true);
+ DLL_LOAD_FUNC(hid, HidD_GetHidGuid, true);
+ DLL_LOAD_FUNC(hid, HidD_GetPreparsedData, true);
+ DLL_LOAD_FUNC(hid, HidD_FreePreparsedData, true);
+ DLL_LOAD_FUNC(hid, HidD_GetManufacturerString, true);
+ DLL_LOAD_FUNC(hid, HidD_GetProductString, true);
+ DLL_LOAD_FUNC(hid, HidD_GetSerialNumberString, true);
+ DLL_LOAD_FUNC(hid, HidD_GetIndexedString, true);
+ DLL_LOAD_FUNC(hid, HidP_GetCaps, true);
+ DLL_LOAD_FUNC(hid, HidD_SetNumInputBuffers, true);
+ DLL_LOAD_FUNC(hid, HidD_GetPhysicalDescriptor, true);
+ DLL_LOAD_FUNC(hid, HidD_FlushQueue, true);
+ DLL_LOAD_FUNC(hid, HidP_GetValueCaps, true);
+
+ return true;
}
static void hid_exit(void)
@@ -3562,7 +3371,6 @@ static void hid_exit(void)
// composite_open(), with interfaces belonging to different APIs
static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
{
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
HIDD_ATTRIBUTES hid_attributes;
@@ -3582,7 +3390,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
CHECK_HID_AVAILABLE;
if (priv->hid == NULL) {
- usbi_err(ctx, "program assertion failed - private HID structure is unitialized");
+ usbi_err(HANDLE_CTX(dev_handle), "program assertion failed - private HID structure is unitialized");
return LIBUSB_ERROR_NOT_FOUND;
}
@@ -3590,7 +3398,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
if ((priv->usb_interface[i].path != NULL)
&& (priv->usb_interface[i].apib->id == USB_API_HID)) {
hid_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
+ NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
/*
* http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID?
* "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system
@@ -3599,11 +3407,11 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
* HidD_GetFeature (if the device supports Feature reports)."
*/
if (hid_handle == INVALID_HANDLE_VALUE) {
- usbi_warn(ctx, "could not open HID device in R/W mode (keyboard or mouse?) - trying without");
+ usbi_warn(HANDLE_CTX(dev_handle), "could not open HID device in R/W mode (keyboard or mouse?) - trying without");
hid_handle = CreateFileA(priv->usb_interface[i].path, 0, FILE_SHARE_WRITE | FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
+ NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (hid_handle == INVALID_HANDLE_VALUE) {
- usbi_err(ctx, "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0));
+ usbi_err(HANDLE_CTX(dev_handle), "could not open device %s (interface %d): %s", priv->path, i, windows_error_str(0));
switch (GetLastError()) {
case ERROR_FILE_NOT_FOUND: // The device was disconnected
return LIBUSB_ERROR_NO_DEVICE;
@@ -3622,7 +3430,7 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
hid_attributes.Size = sizeof(hid_attributes);
do {
if (!HidD_GetAttributes(hid_handle, &hid_attributes)) {
- usbi_err(ctx, "could not gain access to HID top collection (HidD_GetAttributes)");
+ usbi_err(HANDLE_CTX(dev_handle), "could not gain access to HID top collection (HidD_GetAttributes)");
break;
}
@@ -3635,11 +3443,11 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
// Get the maximum input and output report size
if (!HidD_GetPreparsedData(hid_handle, &preparsed_data) || !preparsed_data) {
- usbi_err(ctx, "could not read HID preparsed data (HidD_GetPreparsedData)");
+ usbi_err(HANDLE_CTX(dev_handle), "could not read HID preparsed data (HidD_GetPreparsedData)");
break;
}
if (HidP_GetCaps(preparsed_data, &capabilities) != HIDP_STATUS_SUCCESS) {
- usbi_err(ctx, "could not parse HID capabilities (HidP_GetCaps)");
+ usbi_err(HANDLE_CTX(dev_handle), "could not parse HID capabilities (HidP_GetCaps)");
break;
}
@@ -3666,12 +3474,12 @@ static int hid_open(int sub_api, struct libusb_device_handle *dev_handle)
}
if (nb_ids[1] != 0) {
if (nb_ids[0] != 0)
- usbi_warn(ctx, "program assertion failed: zero and nonzero report IDs used for %s",
+ usbi_warn(HANDLE_CTX(dev_handle), "program assertion failed - zero and nonzero report IDs used for %s",
type[j]);
priv->hid->uses_report_ids[j] = true;
}
} else {
- usbi_warn(ctx, " could not process %s report IDs", type[j]);
+ usbi_warn(HANDLE_CTX(dev_handle), " could not process %s report IDs", type[j]);
}
free(value_caps);
}
@@ -3720,7 +3528,8 @@ static void hid_close(int sub_api, struct libusb_device_handle *dev_handle)
int i;
UNUSED(sub_api);
- if (!api_hid_available)
+
+ if (DLL_HANDLE_NAME(hid) == NULL)
return;
for (i = 0; i < USB_MAXINTERFACES; i++) {
@@ -3777,8 +3586,6 @@ static int hid_release_interface(int sub_api, struct libusb_device_handle *dev_h
static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle *dev_handle, int iface, int altsetting)
{
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
-
UNUSED(sub_api);
UNUSED(iface);
@@ -3788,7 +3595,7 @@ static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle
return LIBUSB_ERROR_INVALID_PARAM;
if (altsetting != 0) {
- usbi_err(ctx, "set interface altsetting not supported for altsetting >0");
+ usbi_err(HANDLE_CTX(dev_handle), "set interface altsetting not supported for altsetting >0");
return LIBUSB_ERROR_NOT_SUPPORTED;
}
@@ -3798,10 +3605,10 @@ static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle
static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
+ struct libusb_device_handle *dev_handle = transfer->dev_handle;
+ struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
HANDLE hid_handle;
OVERLAPPED *overlapped;
@@ -3819,7 +3626,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
if (size > MAX_CTRL_BUFFER_LENGTH)
return LIBUSB_ERROR_INVALID_PARAM;
- current_interface = get_valid_interface(transfer->dev_handle, USB_API_HID);
+ current_interface = get_valid_interface(dev_handle, USB_API_HID);
if (current_interface < 0) {
if (auto_claim(transfer, &current_interface, USB_API_HID) != LIBUSB_SUCCESS)
return LIBUSB_ERROR_NOT_FOUND;
@@ -3828,17 +3635,18 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
usbi_dbg("will use interface %d", current_interface);
hid_handle = handle_priv->interface_handle[current_interface].api_handle;
- overlapped = transfer_priv->pollable_fd.overlapped;
+ set_transfer_priv_handle(itransfer, hid_handle);
+ overlapped = get_transfer_priv_overlapped(itransfer);
switch (LIBUSB_REQ_TYPE(setup->RequestType)) {
case LIBUSB_REQUEST_TYPE_STANDARD:
switch (setup->Request) {
case LIBUSB_REQUEST_GET_DESCRIPTOR:
- r = _hid_get_descriptor(priv->hid, hid_handle, LIBUSB_REQ_RECIPIENT(setup->RequestType),
+ r = _hid_get_descriptor(dev_handle->dev, hid_handle, LIBUSB_REQ_RECIPIENT(setup->RequestType),
(setup->Value >> 8) & 0xFF, setup->Value & 0xFF, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, &size);
break;
case LIBUSB_REQUEST_GET_CONFIGURATION:
- r = winusb_get_configuration(transfer->dev_handle, &config);
+ r = winusb_get_configuration(dev_handle, &config);
if (r == LIBUSB_SUCCESS) {
size = 1;
((uint8_t *)transfer->buffer)[LIBUSB_CONTROL_SETUP_SIZE] = (uint8_t)config;
@@ -3849,7 +3657,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
if (setup->Value == priv->active_config) {
r = LIBUSB_COMPLETED;
} else {
- usbi_warn(ctx, "cannot set configuration other than the default one");
+ usbi_warn(TRANSFER_CTX(transfer), "cannot set configuration other than the default one");
r = LIBUSB_ERROR_NOT_SUPPORTED;
}
break;
@@ -3859,22 +3667,22 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
r = LIBUSB_COMPLETED;
break;
case LIBUSB_REQUEST_SET_INTERFACE:
- r = hid_set_interface_altsetting(0, transfer->dev_handle, setup->Index, setup->Value);
+ r = hid_set_interface_altsetting(0, dev_handle, setup->Index, setup->Value);
if (r == LIBUSB_SUCCESS)
r = LIBUSB_COMPLETED;
break;
default:
- usbi_warn(ctx, "unsupported HID control request");
+ usbi_warn(TRANSFER_CTX(transfer), "unsupported HID control request");
return LIBUSB_ERROR_NOT_SUPPORTED;
}
break;
case LIBUSB_REQUEST_TYPE_CLASS:
- r = _hid_class_request(priv->hid, hid_handle, setup->RequestType, setup->Request, setup->Value,
+ r = _hid_class_request(dev_handle->dev, hid_handle, setup->RequestType, setup->Request, setup->Value,
setup->Index, transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE, transfer_priv,
- &size, overlapped);
+ size, overlapped);
break;
default:
- usbi_warn(ctx, "unsupported HID control request");
+ usbi_warn(TRANSFER_CTX(transfer), "unsupported HID control request");
return LIBUSB_ERROR_NOT_SUPPORTED;
}
@@ -3895,16 +3703,14 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
HANDLE hid_handle;
OVERLAPPED *overlapped;
- bool direction_in, ret;
+ bool direction_in;
+ BOOL ret;
int current_interface, length;
- DWORD size;
- int r = LIBUSB_SUCCESS;
UNUSED(sub_api);
CHECK_HID_AVAILABLE;
@@ -3914,14 +3720,15 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
if (current_interface < 0) {
- usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
+ usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
return LIBUSB_ERROR_NOT_FOUND;
}
usbi_dbg("matched endpoint %02X with interface %d", transfer->endpoint, current_interface);
- transfer_priv->handle = hid_handle = handle_priv->interface_handle[current_interface].api_handle;
- overlapped = transfer_priv->pollable_fd.overlapped;
+ hid_handle = handle_priv->interface_handle[current_interface].api_handle;
+ set_transfer_priv_handle(itransfer, hid_handle);
+ overlapped = get_transfer_priv_overlapped(itransfer);
direction_in = IS_XFERIN(transfer);
// If report IDs are not in use, an extra prefix byte must be added
@@ -3941,7 +3748,7 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
if (direction_in) {
transfer_priv->hid_dest = transfer->buffer;
usbi_dbg("reading %d bytes (report ID: 0x00)", length);
- ret = ReadFile(hid_handle, transfer_priv->hid_buffer, length + 1, &size, overlapped);
+ ret = ReadFile(hid_handle, transfer_priv->hid_buffer, length + 1, NULL, overlapped);
} else {
if (!priv->hid->uses_report_ids[1])
memcpy(transfer_priv->hid_buffer + 1, transfer->buffer, transfer->length);
@@ -3950,64 +3757,18 @@ static int hid_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer
memcpy(transfer_priv->hid_buffer, transfer->buffer, transfer->length);
usbi_dbg("writing %d bytes (report ID: 0x%02X)", length, transfer_priv->hid_buffer[0]);
- ret = WriteFile(hid_handle, transfer_priv->hid_buffer, length, &size, overlapped);
+ ret = WriteFile(hid_handle, transfer_priv->hid_buffer, length, NULL, overlapped);
}
- if (!ret) {
- if (GetLastError() != ERROR_IO_PENDING) {
- usbi_err(ctx, "HID transfer failed: %s", windows_error_str(0));
- safe_free(transfer_priv->hid_buffer);
- return LIBUSB_ERROR_IO;
- }
- } else {
- // Only write operations that completed synchronously need to free up
- // hid_buffer. For reads, copy_transfer_data() handles that process.
- if (!direction_in)
- safe_free(transfer_priv->hid_buffer);
-
- if (size == 0) {
- usbi_err(ctx, "program assertion failed - no data was transferred");
- size = 1;
- }
- if (size > (size_t)length) {
- usbi_err(ctx, "OVERFLOW!");
- r = LIBUSB_ERROR_OVERFLOW;
- }
- windows_force_sync_completion(overlapped, (ULONG)size);
+ if (!ret && GetLastError() != ERROR_IO_PENDING) {
+ usbi_err(TRANSFER_CTX(transfer), "HID transfer failed: %s", windows_error_str(0));
+ safe_free(transfer_priv->hid_buffer);
+ return LIBUSB_ERROR_IO;
}
transfer_priv->interface_number = (uint8_t)current_interface;
- return r;
-}
-
-static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
-{
- struct libusb_context *ctx = ITRANSFER_CTX(itransfer);
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
- struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
- HANDLE hid_handle;
- int current_interface;
-
- UNUSED(sub_api);
- CHECK_HID_AVAILABLE;
-
- current_interface = transfer_priv->interface_number;
- if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
- usbi_err(ctx, "program assertion failed: invalid interface_number");
- return LIBUSB_ERROR_NOT_FOUND;
- }
- usbi_dbg("will use interface %d", current_interface);
-
- hid_handle = handle_priv->interface_handle[current_interface].api_handle;
-
- // Use CancelIoEx to cancel just a single transfer
- if (CancelIoEx(hid_handle, transfer_priv->pollable_fd.overlapped))
- return LIBUSB_SUCCESS;
-
- usbi_warn(ctx, "CancelIoEx failed: %s", windows_error_str(0));
- return LIBUSB_ERROR_NOT_FOUND;
+ return LIBUSB_SUCCESS;
}
static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
@@ -4031,7 +3792,6 @@ static int hid_reset_device(int sub_api, struct libusb_device_handle *dev_handle
static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
{
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
HANDLE hid_handle;
@@ -4042,7 +3802,7 @@ static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle,
current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
if (current_interface < 0) {
- usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
+ usbi_err(HANDLE_CTX(dev_handle), "unable to match endpoint to an open interface - cannot clear");
return LIBUSB_ERROR_NOT_FOUND;
}
@@ -4052,7 +3812,7 @@ static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle,
// No endpoint selection with Microsoft's implementation, so we try to flush the
// whole interface. Should be OK for most case scenarios
if (!HidD_FlushQueue(hid_handle)) {
- usbi_err(ctx, "Flushing of HID queue failed: %s", windows_error_str(0));
+ usbi_err(HANDLE_CTX(dev_handle), "Flushing of HID queue failed: %s", windows_error_str(0));
// Device was probably disconnected
return LIBUSB_ERROR_NO_DEVICE;
}
@@ -4061,33 +3821,31 @@ static int hid_clear_halt(int sub_api, struct libusb_device_handle *dev_handle,
}
// This extra function is only needed for HID
-static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
+static enum libusb_transfer_status hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
- int r = LIBUSB_TRANSFER_COMPLETED;
- uint32_t corrected_size = io_size;
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
+ enum libusb_transfer_status r = LIBUSB_TRANSFER_COMPLETED;
UNUSED(sub_api);
if (transfer_priv->hid_buffer != NULL) {
// If we have a valid hid_buffer, it means the transfer was async
if (transfer_priv->hid_dest != NULL) { // Data readout
- if (corrected_size > 0) {
+ if (length > 0) {
// First, check for overflow
- if (corrected_size > transfer_priv->hid_expected_size) {
- usbi_err(ctx, "OVERFLOW!");
- corrected_size = (uint32_t)transfer_priv->hid_expected_size;
+ if ((size_t)length > transfer_priv->hid_expected_size) {
+ usbi_err(TRANSFER_CTX(transfer), "OVERFLOW!");
+ length = (DWORD)transfer_priv->hid_expected_size;
r = LIBUSB_TRANSFER_OVERFLOW;
}
if (transfer_priv->hid_buffer[0] == 0) {
// Discard the 1 byte report ID prefix
- corrected_size--;
- memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, corrected_size);
+ length--;
+ memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer + 1, length);
} else {
- memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, corrected_size);
+ memcpy(transfer_priv->hid_dest, transfer_priv->hid_buffer, length);
}
}
transfer_priv->hid_dest = NULL;
@@ -4096,7 +3854,7 @@ static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer,
safe_free(transfer_priv->hid_buffer);
}
- itransfer->transferred += corrected_size;
+ itransfer->transferred += (int)length;
return r;
}
@@ -4107,13 +3865,15 @@ static int hid_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer,
static int composite_open(int sub_api, struct libusb_device_handle *dev_handle)
{
struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
- int r = LIBUSB_ERROR_NOT_FOUND;
- uint8_t i;
+ int i, r = LIBUSB_ERROR_NOT_FOUND;
// SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID
- bool available[SUB_API_MAX + 1] = { 0 };
+ bool available[SUB_API_MAX + 1];
UNUSED(sub_api);
+ for (i = 0; i < SUB_API_MAX + 1; i++)
+ available[i] = false;
+
for (i = 0; i < USB_MAXINTERFACES; i++) {
switch (priv->usb_interface[i].apib->id) {
case USB_API_WINUSBX:
@@ -4154,12 +3914,15 @@ static int composite_open(int sub_api, struct libusb_device_handle *dev_handle)
static void composite_close(int sub_api, struct libusb_device_handle *dev_handle)
{
struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
- uint8_t i;
+ int i;
// SUB_API_MAX + 1 as the SUB_API_MAX pos is used to indicate availability of HID
- bool available[SUB_API_MAX + 1] = { 0 };
+ bool available[SUB_API_MAX + 1];
UNUSED(sub_api);
+ for (i = 0; i < SUB_API_MAX + 1; i++)
+ available[i] = false;
+
for (i = 0; i < USB_MAXINTERFACES; i++) {
switch (priv->usb_interface[i].apib->id) {
case USB_API_WINUSBX:
@@ -4219,7 +3982,6 @@ static int composite_release_interface(int sub_api, struct libusb_device_handle
static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
struct libusb_config_descriptor *conf_desc;
WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *)transfer->buffer;
@@ -4278,13 +4040,13 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *
}
}
- usbi_err(ctx, "no libusb supported interfaces to complete request");
+ usbi_err(TRANSFER_CTX(transfer), "no libusb supported interfaces to complete request");
return LIBUSB_ERROR_NOT_FOUND;
}
-static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer) {
+static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itransfer)
+{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
int current_interface;
@@ -4293,7 +4055,7 @@ static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itr
current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
if (current_interface < 0) {
- usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
+ usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
return LIBUSB_ERROR_NOT_FOUND;
}
@@ -4303,9 +4065,9 @@ static int composite_submit_bulk_transfer(int sub_api, struct usbi_transfer *itr
submit_bulk_transfer(priv->usb_interface[current_interface].sub_api, itransfer);
}
-static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer) {
+static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itransfer)
+{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(transfer->dev_handle);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
int current_interface;
@@ -4314,7 +4076,7 @@ static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itra
current_interface = interface_by_endpoint(priv, handle_priv, transfer->endpoint);
if (current_interface < 0) {
- usbi_err(ctx, "unable to match endpoint to an open interface - cancelling transfer");
+ usbi_err(TRANSFER_CTX(transfer), "unable to match endpoint to an open interface - cancelling transfer");
return LIBUSB_ERROR_NOT_FOUND;
}
@@ -4326,7 +4088,6 @@ static int composite_submit_iso_transfer(int sub_api, struct usbi_transfer *itra
static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_handle, unsigned char endpoint)
{
- struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
struct winusb_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
int current_interface;
@@ -4335,7 +4096,7 @@ static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_ha
current_interface = interface_by_endpoint(priv, handle_priv, endpoint);
if (current_interface < 0) {
- usbi_err(ctx, "unable to match endpoint to an open interface - cannot clear");
+ usbi_err(HANDLE_CTX(dev_handle), "unable to match endpoint to an open interface - cannot clear");
return LIBUSB_ERROR_NOT_FOUND;
}
@@ -4345,51 +4106,30 @@ static int composite_clear_halt(int sub_api, struct libusb_device_handle *dev_ha
clear_halt(priv->usb_interface[current_interface].sub_api, dev_handle, endpoint);
}
-static int composite_abort_control(int sub_api, struct usbi_transfer *itransfer)
+static int composite_cancel_transfer(int sub_api, struct usbi_transfer *itransfer)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
int current_interface = transfer_priv->interface_number;
UNUSED(sub_api);
if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
- usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number");
+ usbi_err(TRANSFER_CTX(transfer), "program assertion failed - invalid interface_number");
return LIBUSB_ERROR_NOT_FOUND;
}
- CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_control);
+ CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, cancel_transfer);
return priv->usb_interface[current_interface].apib->
- abort_control(priv->usb_interface[current_interface].sub_api, itransfer);
-}
-
-static int composite_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
-{
- struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
- struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
- int current_interface = transfer_priv->interface_number;
-
- UNUSED(sub_api);
-
- if ((current_interface < 0) || (current_interface >= USB_MAXINTERFACES)) {
- usbi_err(TRANSFER_CTX(transfer), "program assertion failed: invalid interface_number");
- return LIBUSB_ERROR_NOT_FOUND;
- }
-
- CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, abort_transfers);
-
- return priv->usb_interface[current_interface].apib->
- abort_transfers(priv->usb_interface[current_interface].sub_api, itransfer);
+ cancel_transfer(priv->usb_interface[current_interface].sub_api, itransfer);
}
static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_handle)
{
struct winusb_device_priv *priv = _device_priv(dev_handle->dev);
- int r;
- uint8_t i;
+ int i, r;
bool available[SUB_API_MAX];
UNUSED(sub_api);
@@ -4414,16 +4154,19 @@ static int composite_reset_device(int sub_api, struct libusb_device_handle *dev_
return LIBUSB_SUCCESS;
}
-static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size)
+static enum libusb_transfer_status composite_copy_transfer_data(int sub_api, struct usbi_transfer *itransfer, DWORD length)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
- struct winusb_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
+ struct winusb_transfer_priv *transfer_priv = get_winusb_transfer_priv(itransfer);
struct winusb_device_priv *priv = _device_priv(transfer->dev_handle->dev);
int current_interface = transfer_priv->interface_number;
UNUSED(sub_api);
- CHECK_SUPPORTED_API(priv->usb_interface[current_interface].apib, copy_transfer_data);
+ if (priv->usb_interface[current_interface].apib->copy_transfer_data == NULL) {
+ usbi_err(TRANSFER_CTX(transfer), "program assertion failed - no function to copy transfer data");
+ return LIBUSB_TRANSFER_ERROR;
+ }
return priv->usb_interface[current_interface].apib->
- copy_transfer_data(priv->usb_interface[current_interface].sub_api, itransfer, io_size);
+ copy_transfer_data(priv->usb_interface[current_interface].sub_api, itransfer, length);
}
diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h
index 6ac39c3..57d4b7f 100644
--- a/libusb/os/windows_winusb.h
+++ b/libusb/os/windows_winusb.h
@@ -69,6 +69,8 @@ const GUID GUID_DEVINTERFACE_USB_HUB = {0xF18A0E88, 0xC30C, 0x11D0, {0x88, 0x15,
const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = {0xF9F3FF14, 0xAE21, 0x48A0, {0x8A, 0x25, 0x80, 0x11, 0xA7, 0xA9, 0x31, 0xD9}};
#endif
+// The following define MUST be == sizeof(USB_DESCRIPTOR_REQUEST)
+#define USB_DESCRIPTOR_REQUEST_SIZE 12U
/*
* Multiple USB API backend support
@@ -93,7 +95,7 @@ struct windows_usb_api_backend {
const char * const designation;
const char * const * const driver_name_list; // Driver name, without .sys, e.g. "usbccgp"
const uint8_t nb_driver_names;
- int (*init)(struct libusb_context *ctx);
+ bool (*init)(struct libusb_context *ctx);
void (*exit)(void);
int (*open)(int sub_api, struct libusb_device_handle *dev_handle);
void (*close)(int sub_api, struct libusb_device_handle *dev_handle);
@@ -106,9 +108,8 @@ struct windows_usb_api_backend {
int (*submit_bulk_transfer)(int sub_api, struct usbi_transfer *itransfer);
int (*submit_iso_transfer)(int sub_api, struct usbi_transfer *itransfer);
int (*submit_control_transfer)(int sub_api, struct usbi_transfer *itransfer);
- int (*abort_control)(int sub_api, struct usbi_transfer *itransfer);
- int (*abort_transfers)(int sub_api, struct usbi_transfer *itransfer);
- int (*copy_transfer_data)(int sub_api, struct usbi_transfer *itransfer, uint32_t io_size);
+ int (*cancel_transfer)(int sub_api, struct usbi_transfer *itransfer);
+ enum libusb_transfer_status (*copy_transfer_data)(int sub_api, struct usbi_transfer *itransfer, DWORD length);
};
extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX];
@@ -226,8 +227,11 @@ static inline void winusb_device_priv_release(struct libusb_device *dev)
free(p->dev_id);
free(p->path);
if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) {
- for (i = 0; i < dev->num_configurations; i++)
- free(p->config_descriptor[i]);
+ for (i = 0; i < dev->num_configurations; i++) {
+ if (p->config_descriptor[i] == NULL)
+ continue;
+ free((UCHAR *)p->config_descriptor[i] - USB_DESCRIPTOR_REQUEST_SIZE);
+ }
}
free(p->config_descriptor);
free(p->hid);
@@ -422,6 +426,12 @@ typedef struct _USB_NODE_CONNECTION_INFORMATION_EX_V2 {
/* libusbK */
#define ISO_ALWAYS_START_ASAP 0x21
+typedef struct _USBD_ISO_PACKET_DESCRIPTOR {
+ ULONG Offset;
+ ULONG Length;
+ USBD_STATUS Status;
+} USBD_ISO_PACKET_DESCRIPTOR, *PUSBD_ISO_PACKET_DESCRIPTOR;
+
typedef enum _USBD_PIPE_TYPE {
UsbdPipeTypeControl,
UsbdPipeTypeIsochronous,
@@ -429,6 +439,14 @@ typedef enum _USBD_PIPE_TYPE {
UsbdPipeTypeInterrupt
} USBD_PIPE_TYPE;
+typedef struct {
+ USBD_PIPE_TYPE PipeType;
+ UCHAR PipeId;
+ USHORT MaximumPacketSize;
+ UCHAR Interval;
+ ULONG MaximumBytesPerInterval;
+} WINUSB_PIPE_INFORMATION_EX, *PWINUSB_PIPE_INFORMATION_EX;
+
#include <pshpack1.h>
typedef struct _WINUSB_SETUP_PACKET {
@@ -441,7 +459,8 @@ typedef struct _WINUSB_SETUP_PACKET {
#include <poppack.h>
-typedef void *WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE;
+typedef PVOID WINUSB_INTERFACE_HANDLE, *PWINUSB_INTERFACE_HANDLE;
+typedef PVOID WINUSB_ISOCH_BUFFER_HANDLE, *PWINUSB_ISOCH_BUFFER_HANDLE;
typedef BOOL (WINAPI *WinUsb_AbortPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
@@ -471,6 +490,21 @@ typedef BOOL (WINAPI *WinUsb_Initialize_t)(
HANDLE DeviceHandle,
PWINUSB_INTERFACE_HANDLE InterfaceHandle
);
+typedef BOOL (WINAPI *WinUsb_QueryPipeEx_t)(
+ WINUSB_INTERFACE_HANDLE InterfaceHandle,
+ UCHAR AlternateInterfaceHandle,
+ UCHAR PipeIndex,
+ PWINUSB_PIPE_INFORMATION_EX PipeInformationEx
+);
+typedef BOOL (WINAPI *WinUsb_ReadIsochPipeAsap_t)(
+ PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle,
+ ULONG Offset,
+ ULONG Length,
+ BOOL ContinueStream,
+ ULONG NumberOfPackets,
+ PUSBD_ISO_PACKET_DESCRIPTOR IsoPacketDescriptors,
+ LPOVERLAPPED Overlapped
+);
typedef BOOL (WINAPI *WinUsb_ReadPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID,
@@ -479,8 +513,12 @@ typedef BOOL (WINAPI *WinUsb_ReadPipe_t)(
PULONG LengthTransferred,
LPOVERLAPPED Overlapped
);
-typedef BOOL (WINAPI *WinUsb_ResetDevice_t)(
- WINUSB_INTERFACE_HANDLE InterfaceHandle
+typedef BOOL (WINAPI *WinUsb_RegisterIsochBuffer_t)(
+ WINUSB_INTERFACE_HANDLE InterfaceHandle,
+ UCHAR PipeID,
+ PVOID Buffer,
+ ULONG BufferLength,
+ PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle
);
typedef BOOL (WINAPI *WinUsb_ResetPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
@@ -497,29 +535,9 @@ typedef BOOL (WINAPI *WinUsb_SetPipePolicy_t)(
ULONG ValueLength,
PVOID Value
);
-typedef BOOL (WINAPI *WinUsb_WritePipe_t)(
- WINUSB_INTERFACE_HANDLE InterfaceHandle,
- UCHAR PipeID,
- PUCHAR Buffer,
- ULONG BufferLength,
- PULONG LengthTransferred,
- LPOVERLAPPED Overlapped
-);
-
-typedef PVOID WINUSB_ISOCH_BUFFER_HANDLE, *PWINUSB_ISOCH_BUFFER_HANDLE;
-
-typedef BOOL (WINAPI *WinUsb_RegisterIsochBuffer_t)(
- WINUSB_INTERFACE_HANDLE InterfaceHandle,
- UCHAR PipeID,
- PVOID Buffer,
- ULONG BufferLength,
- PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle
-);
-
typedef BOOL (WINAPI *WinUsb_UnregisterIsochBuffer_t)(
WINUSB_ISOCH_BUFFER_HANDLE BufferHandle
);
-
typedef BOOL (WINAPI *WinUsb_WriteIsochPipeAsap_t)(
WINUSB_ISOCH_BUFFER_HANDLE BufferHandle,
ULONG Offset,
@@ -527,37 +545,13 @@ typedef BOOL (WINAPI *WinUsb_WriteIsochPipeAsap_t)(
BOOL ContinueStream,
LPOVERLAPPED Overlapped
);
-
-typedef LONG USBD_STATUS;
-typedef struct {
- ULONG Offset;
- ULONG Length;
- USBD_STATUS Status;
-} USBD_ISO_PACKET_DESCRIPTOR, *PUSBD_ISO_PACKET_DESCRIPTOR;
-
-typedef BOOL (WINAPI *WinUsb_ReadIsochPipeAsap_t)(
- PWINUSB_ISOCH_BUFFER_HANDLE BufferHandle,
- ULONG Offset,
- ULONG Length,
- BOOL ContinueStream,
- ULONG NumberOfPackets,
- PUSBD_ISO_PACKET_DESCRIPTOR IsoPacketDescriptors,
- LPOVERLAPPED Overlapped
-);
-
-typedef struct {
- USBD_PIPE_TYPE PipeType;
- UCHAR PipeId;
- USHORT MaximumPacketSize;
- UCHAR Interval;
- ULONG MaximumBytesPerInterval;
-} WINUSB_PIPE_INFORMATION_EX, *PWINUSB_PIPE_INFORMATION_EX;
-
-typedef BOOL (WINAPI *WinUsb_QueryPipeEx_t)(
+typedef BOOL (WINAPI *WinUsb_WritePipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
- UCHAR AlternateInterfaceHandle,
- UCHAR PipeIndex,
- PWINUSB_PIPE_INFORMATION_EX PipeInformationEx
+ UCHAR PipeID,
+ PUCHAR Buffer,
+ ULONG BufferLength,
+ PULONG LengthTransferred,
+ LPOVERLAPPED Overlapped
);
/* /!\ These must match the ones from the official libusbk.h */
@@ -607,15 +601,19 @@ typedef struct _KLIB_VERSION {
} KLIB_VERSION, *PKLIB_VERSION;
typedef BOOL (WINAPI *LibK_GetProcAddress_t)(
- PVOID *ProcAddress,
- ULONG DriverID,
- ULONG FunctionID
+ PVOID ProcAddress,
+ INT DriverID,
+ INT FunctionID
);
typedef VOID (WINAPI *LibK_GetVersion_t)(
PKLIB_VERSION Version
);
+typedef BOOL (WINAPI *LibK_ResetDevice_t)(
+ WINUSB_INTERFACE_HANDLE InterfaceHandle
+);
+
//KISO_PACKET is equivalent of libusb_iso_packet_descriptor except uses absolute "offset" field instead of sequential Lengths
typedef struct _KISO_PACKET {
UINT offset;
@@ -638,7 +636,7 @@ typedef struct _KISO_CONTEXT {
KISO_PACKET IsoPackets[0];
} KISO_CONTEXT, *PKISO_CONTEXT;
-typedef BOOL(WINAPI *WinUsb_IsoReadPipe_t)(
+typedef BOOL(WINAPI *LibK_IsoReadPipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID,
PUCHAR Buffer,
@@ -647,7 +645,7 @@ typedef BOOL(WINAPI *WinUsb_IsoReadPipe_t)(
PKISO_CONTEXT IsoContext
);
-typedef BOOL(WINAPI *WinUsb_IsoWritePipe_t)(
+typedef BOOL(WINAPI *LibK_IsoWritePipe_t)(
WINUSB_INTERFACE_HANDLE InterfaceHandle,
UCHAR PipeID,
PUCHAR Buffer,
@@ -657,8 +655,7 @@ typedef BOOL(WINAPI *WinUsb_IsoWritePipe_t)(
);
struct winusb_interface {
- bool initialized;
- bool CancelIoEx_supported;
+ HMODULE hDll;
WinUsb_AbortPipe_t AbortPipe;
WinUsb_ControlTransfer_t ControlTransfer;
WinUsb_FlushPipe_t FlushPipe;
@@ -666,22 +663,27 @@ struct winusb_interface {
WinUsb_GetAssociatedInterface_t GetAssociatedInterface;
WinUsb_Initialize_t Initialize;
WinUsb_ReadPipe_t ReadPipe;
- WinUsb_ResetDevice_t ResetDevice;
WinUsb_ResetPipe_t ResetPipe;
WinUsb_SetCurrentAlternateSetting_t SetCurrentAlternateSetting;
WinUsb_SetPipePolicy_t SetPipePolicy;
WinUsb_WritePipe_t WritePipe;
-
- // Isochoronous functions for LibUSBk sub api:
- WinUsb_IsoReadPipe_t IsoReadPipe;
- WinUsb_IsoWritePipe_t IsoWritePipe;
-
- // Isochronous functions for Microsoft WinUSB sub api (native WinUSB):
- WinUsb_RegisterIsochBuffer_t RegisterIsochBuffer;
- WinUsb_UnregisterIsochBuffer_t UnregisterIsochBuffer;
- WinUsb_WriteIsochPipeAsap_t WriteIsochPipeAsap;
- WinUsb_ReadIsochPipeAsap_t ReadIsochPipeAsap;
- WinUsb_QueryPipeEx_t QueryPipeEx;
+ union {
+ struct {
+ // Isochoronous functions for libusbK sub api:
+ LibK_IsoReadPipe_t IsoReadPipe;
+ LibK_IsoWritePipe_t IsoWritePipe;
+ // Reset device function for libusbK sub api:
+ LibK_ResetDevice_t ResetDevice;
+ };
+ struct {
+ // Isochronous functions for WinUSB sub api:
+ WinUsb_QueryPipeEx_t QueryPipeEx;
+ WinUsb_ReadIsochPipeAsap_t ReadIsochPipeAsap;
+ WinUsb_RegisterIsochBuffer_t RegisterIsochBuffer;
+ WinUsb_UnregisterIsochBuffer_t UnregisterIsochBuffer;
+ WinUsb_WriteIsochPipeAsap_t WriteIsochPipeAsap;
+ };
+ };
};
/* hid.dll interface */
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 7e27bf5..8c3a7c4 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11453
+#define LIBUSB_NANO 11454