Large diffs are not rendered by default.

@@ -65,6 +65,12 @@ struct devlink_cbarg {
di_minor_t minor;
};

typedef struct walk_link {
char *path;
int len;
char **linkpp;
} walk_link_t;

/* AIO callback args */
struct aio_callback_args{
struct libusb_transfer *transfer;
@@ -29,7 +29,7 @@
# include <unistd.h>
# include <sys/syscall.h>
#elif defined(__APPLE__)
# include <mach/mach.h>
# include <pthread.h>
#elif defined(__CYGWIN__)
# include <windows.h>
#endif
@@ -43,7 +43,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond,
struct timespec timeout;
int r;

r = usbi_backend->clock_gettime(USBI_CLOCK_REALTIME, &timeout);
r = usbi_backend.clock_gettime(USBI_CLOCK_REALTIME, &timeout);
if (r < 0)
return r;

@@ -59,7 +59,7 @@ int usbi_cond_timedwait(pthread_cond_t *cond,

int usbi_get_tid(void)
{
int ret = -1;
int ret;
#if defined(__ANDROID__)
ret = gettid();
#elif defined(__linux__)
@@ -69,10 +69,11 @@ int usbi_get_tid(void)
real thread support. For 5.1 and earlier, -1 is returned. */
ret = syscall(SYS_getthrid);
#elif defined(__APPLE__)
ret = mach_thread_self();
mach_port_deallocate(mach_task_self(), ret);
ret = (int)pthread_mach_thread_np(pthread_self());
#elif defined(__CYGWIN__)
ret = GetCurrentThreadId();
#else
ret = -1;
#endif
/* TODO: NetBSD thread ID support */
return ret;
@@ -26,32 +26,76 @@
#include <sys/time.h>
#endif

#define usbi_mutex_static_t pthread_mutex_t
#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#define usbi_mutex_static_lock pthread_mutex_lock
#define usbi_mutex_static_unlock pthread_mutex_unlock

#define usbi_mutex_t pthread_mutex_t
#define usbi_mutex_init(mutex) pthread_mutex_init((mutex), NULL)
#define usbi_mutex_lock pthread_mutex_lock
#define usbi_mutex_unlock pthread_mutex_unlock
#define usbi_mutex_trylock pthread_mutex_trylock
#define usbi_mutex_destroy pthread_mutex_destroy

#define usbi_cond_t pthread_cond_t
#define usbi_cond_init(cond) pthread_cond_init((cond), NULL)
#define usbi_cond_wait pthread_cond_wait
#define usbi_cond_broadcast pthread_cond_broadcast
#define usbi_cond_destroy pthread_cond_destroy

#define usbi_tls_key_t pthread_key_t
#define usbi_tls_key_create(key) pthread_key_create((key), NULL)
#define usbi_tls_key_get pthread_getspecific
#define usbi_tls_key_set pthread_setspecific
#define usbi_tls_key_delete pthread_key_delete

int usbi_cond_timedwait(pthread_cond_t *cond,
pthread_mutex_t *mutex, const struct timeval *tv);
#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
typedef pthread_mutex_t usbi_mutex_static_t;
static inline void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
{
(void)pthread_mutex_lock(mutex);
}
static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
{
(void)pthread_mutex_unlock(mutex);
}

typedef pthread_mutex_t usbi_mutex_t;
static inline int usbi_mutex_init(usbi_mutex_t *mutex)
{
return pthread_mutex_init(mutex, NULL);
}
static inline void usbi_mutex_lock(usbi_mutex_t *mutex)
{
(void)pthread_mutex_lock(mutex);
}
static inline void usbi_mutex_unlock(usbi_mutex_t *mutex)
{
(void)pthread_mutex_unlock(mutex);
}
static inline int usbi_mutex_trylock(usbi_mutex_t *mutex)
{
return pthread_mutex_trylock(mutex);
}
static inline void usbi_mutex_destroy(usbi_mutex_t *mutex)
{
(void)pthread_mutex_destroy(mutex);
}

typedef pthread_cond_t usbi_cond_t;
static inline void usbi_cond_init(pthread_cond_t *cond)
{
(void)pthread_cond_init(cond, NULL);
}
static inline int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
{
return pthread_cond_wait(cond, mutex);
}
int usbi_cond_timedwait(usbi_cond_t *cond,
usbi_mutex_t *mutex, const struct timeval *tv);
static inline void usbi_cond_broadcast(usbi_cond_t *cond)
{
(void)pthread_cond_broadcast(cond);
}
static inline void usbi_cond_destroy(usbi_cond_t *cond)
{
(void)pthread_cond_destroy(cond);
}

typedef pthread_key_t usbi_tls_key_t;
static inline void usbi_tls_key_create(usbi_tls_key_t *key)
{
(void)pthread_key_create(key, NULL);
}
static inline void *usbi_tls_key_get(usbi_tls_key_t key)
{
return pthread_getspecific(key);
}
static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr)
{
(void)pthread_setspecific(key, ptr);
}
static inline void usbi_tls_key_delete(usbi_tls_key_t key)
{
(void)pthread_key_delete(key);
}

int usbi_get_tid(void);

@@ -20,189 +20,67 @@

#include <config.h>

#include <objbase.h>
#include <errno.h>

#include "libusbi.h"

struct usbi_cond_perthread {
struct list_head list;
DWORD tid;
HANDLE event;
};

int usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
void usbi_mutex_static_lock(usbi_mutex_static_t *mutex)
{
if (!mutex)
return EINVAL;
while (InterlockedExchange(mutex, 1) == 1)
while (InterlockedExchange(mutex, 1L) == 1L)
SleepEx(0, TRUE);
return 0;
}

int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
{
if (!mutex)
return EINVAL;
InterlockedExchange(mutex, 0);
return 0;
}

int usbi_mutex_init(usbi_mutex_t *mutex)
{
if (!mutex)
return EINVAL;
*mutex = CreateMutex(NULL, FALSE, NULL);
if (!*mutex)
return ENOMEM;
return 0;
}

int usbi_mutex_lock(usbi_mutex_t *mutex)
{
DWORD result;

if (!mutex)
return EINVAL;
result = WaitForSingleObject(*mutex, INFINITE);
if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
return 0; // acquired (ToDo: check that abandoned is ok)
else
return EINVAL; // don't know how this would happen
// so don't know proper errno
}

int usbi_mutex_unlock(usbi_mutex_t *mutex)
{
if (!mutex)
return EINVAL;
if (ReleaseMutex(*mutex))
return 0;
else
return EPERM;
}

int usbi_mutex_trylock(usbi_mutex_t *mutex)
{
DWORD result;

if (!mutex)
return EINVAL;
result = WaitForSingleObject(*mutex, 0);
if (result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
return 0; // acquired (ToDo: check that abandoned is ok)
else if (result == WAIT_TIMEOUT)
return EBUSY;
else
return EINVAL; // don't know how this would happen
// so don't know proper error
}

int usbi_mutex_destroy(usbi_mutex_t *mutex)
void usbi_cond_init(usbi_cond_t *cond)
{
// It is not clear if CloseHandle failure is due to failure to unlock.
// If so, this should be errno=EBUSY.
if (!mutex || !CloseHandle(*mutex))
return EINVAL;
*mutex = NULL;
return 0;
}

int usbi_cond_init(usbi_cond_t *cond)
{
if (!cond)
return EINVAL;
list_init(&cond->waiters);
list_init(&cond->not_waiting);
return 0;
}

int usbi_cond_destroy(usbi_cond_t *cond)
{
// This assumes no one is using this anymore. The check MAY NOT BE safe.
struct usbi_cond_perthread *pos, *next_pos;

if(!cond)
return EINVAL;
if (!list_empty(&cond->waiters))
return EBUSY; // (!see above!)
list_for_each_entry_safe(pos, next_pos, &cond->not_waiting, list, struct usbi_cond_perthread) {
CloseHandle(pos->event);
list_del(&pos->list);
free(pos);
}
return 0;
}

int usbi_cond_broadcast(usbi_cond_t *cond)
{
// Assumes mutex is locked; this is not in keeping with POSIX spec, but
// libusb does this anyway, so we simplify by not adding more sync
// primitives to the CV definition!
int fail = 0;
struct usbi_cond_perthread *pos;

if (!cond)
return EINVAL;
list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) {
if (!SetEvent(pos->event))
fail = 1;
}
// The wait function will remove its respective item from the list.
return fail ? EINVAL : 0;
}

__inline static int usbi_cond_intwait(usbi_cond_t *cond,
static int usbi_cond_intwait(usbi_cond_t *cond,
usbi_mutex_t *mutex, DWORD timeout_ms)
{
struct usbi_cond_perthread *pos;
int r, found = 0;
DWORD r2, tid = GetCurrentThreadId();

if (!cond || !mutex)
return EINVAL;
list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) {
if(tid == pos->tid) {
found = 1;
break;
}
}
DWORD r;

if (!found) {
pos = calloc(1, sizeof(struct usbi_cond_perthread));
if (!pos)
// Same assumption as usbi_cond_broadcast() holds
if (list_empty(&cond->not_waiting)) {
pos = malloc(sizeof(*pos));
if (pos == NULL)
return ENOMEM; // This errno is not POSIX-allowed.
pos->tid = tid;
pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset.
if (!pos->event) {
if (pos->event == NULL) {
free(pos);
return ENOMEM;
}
list_add(&pos->list, &cond->not_waiting);
} else {
pos = list_first_entry(&cond->not_waiting, struct usbi_cond_perthread, list);
list_del(&pos->list); // remove from not_waiting list.
// Ensure the event is clear before waiting
WaitForSingleObject(pos->event, 0);
}

list_del(&pos->list); // remove from not_waiting list.
list_add(&pos->list, &cond->waiters);

r = usbi_mutex_unlock(mutex);
if (r)
return r;

r2 = WaitForSingleObject(pos->event, timeout_ms);
r = usbi_mutex_lock(mutex);
if (r)
return r;
LeaveCriticalSection(mutex);
r = WaitForSingleObject(pos->event, timeout_ms);
EnterCriticalSection(mutex);

list_del(&pos->list);
list_add(&pos->list, &cond->not_waiting);

if (r2 == WAIT_OBJECT_0)
if (r == WAIT_OBJECT_0)
return 0;
else if (r2 == WAIT_TIMEOUT)
else if (r == WAIT_TIMEOUT)
return ETIMEDOUT;
else
return EINVAL;
}

// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot!
int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
{
@@ -221,39 +99,28 @@ int usbi_cond_timedwait(usbi_cond_t *cond,
return usbi_cond_intwait(cond, mutex, millis);
}

int usbi_tls_key_create(usbi_tls_key_t *key)
{
if (!key)
return EINVAL;
*key = TlsAlloc();
if (*key == TLS_OUT_OF_INDEXES)
return ENOMEM;
else
return 0;
}

void *usbi_tls_key_get(usbi_tls_key_t key)
void usbi_cond_broadcast(usbi_cond_t *cond)
{
return TlsGetValue(key);
}
// Assumes mutex is locked; this is not in keeping with POSIX spec, but
// libusb does this anyway, so we simplify by not adding more sync
// primitives to the CV definition!
struct usbi_cond_perthread *pos;

int usbi_tls_key_set(usbi_tls_key_t key, void *value)
{
if (TlsSetValue(key, value))
return 0;
else
return EINVAL;
list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread)
SetEvent(pos->event);
// The wait function will remove its respective item from the list.
}

int usbi_tls_key_delete(usbi_tls_key_t key)
void usbi_cond_destroy(usbi_cond_t *cond)
{
if (TlsFree(key))
return 0;
else
return EINVAL;
}
// This assumes no one is using this anymore. The check MAY NOT BE safe.
struct usbi_cond_perthread *pos, *next;

int usbi_get_tid(void)
{
return (int)GetCurrentThreadId();
if (!list_empty(&cond->waiters))
return; // (!see above!)
list_for_each_entry_safe(pos, next, &cond->not_waiting, list, struct usbi_cond_perthread) {
CloseHandle(pos->event);
list_del(&pos->list);
free(pos);
}
}
@@ -21,17 +21,40 @@
#ifndef LIBUSB_THREADS_WINDOWS_H
#define LIBUSB_THREADS_WINDOWS_H

#define usbi_mutex_static_t volatile LONG
#define USBI_MUTEX_INITIALIZER 0

#define usbi_mutex_t HANDLE
#define USBI_MUTEX_INITIALIZER 0L
#ifdef _WIN32_WCE
typedef LONG usbi_mutex_static_t;
#else
typedef volatile LONG usbi_mutex_static_t;
#endif
void usbi_mutex_static_lock(usbi_mutex_static_t *mutex);
static inline void usbi_mutex_static_unlock(usbi_mutex_static_t *mutex)
{
InterlockedExchange(mutex, 0L);
}

typedef struct usbi_cond {
// Every time a thread touches the CV, it winds up in one of these lists.
// It stays there until the CV is destroyed, even if the thread terminates.
struct list_head waiters;
struct list_head not_waiting;
} usbi_cond_t;
typedef CRITICAL_SECTION usbi_mutex_t;
static inline int usbi_mutex_init(usbi_mutex_t *mutex)
{
InitializeCriticalSection(mutex);
return 0;
}
static inline void usbi_mutex_lock(usbi_mutex_t *mutex)
{
EnterCriticalSection(mutex);
}
static inline void usbi_mutex_unlock(usbi_mutex_t *mutex)
{
LeaveCriticalSection(mutex);
}
static inline int usbi_mutex_trylock(usbi_mutex_t *mutex)
{
return !TryEnterCriticalSection(mutex);
}
static inline void usbi_mutex_destroy(usbi_mutex_t *mutex)
{
DeleteCriticalSection(mutex);
}

// We *were* getting timespec from pthread.h:
#if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED))
@@ -45,32 +68,44 @@ struct timespec {

// We *were* getting ETIMEDOUT from pthread.h:
#ifndef ETIMEDOUT
# define ETIMEDOUT 10060 /* This is the value in winsock.h. */
#define ETIMEDOUT 10060 /* This is the value in winsock.h. */
#endif

#define usbi_tls_key_t DWORD

int usbi_mutex_static_lock(usbi_mutex_static_t *mutex);
int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex);

int usbi_mutex_init(usbi_mutex_t *mutex);
int usbi_mutex_lock(usbi_mutex_t *mutex);
int usbi_mutex_unlock(usbi_mutex_t *mutex);
int usbi_mutex_trylock(usbi_mutex_t *mutex);
int usbi_mutex_destroy(usbi_mutex_t *mutex);
typedef struct usbi_cond {
// Every time a thread touches the CV, it winds up in one of these lists.
// It stays there until the CV is destroyed, even if the thread terminates.
struct list_head waiters;
struct list_head not_waiting;
} usbi_cond_t;

int usbi_cond_init(usbi_cond_t *cond);
void usbi_cond_init(usbi_cond_t *cond);
int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex);
int usbi_cond_timedwait(usbi_cond_t *cond,
usbi_mutex_t *mutex, const struct timeval *tv);
int usbi_cond_broadcast(usbi_cond_t *cond);
int usbi_cond_destroy(usbi_cond_t *cond);
void usbi_cond_broadcast(usbi_cond_t *cond);
void usbi_cond_destroy(usbi_cond_t *cond);

int usbi_tls_key_create(usbi_tls_key_t *key);
void *usbi_tls_key_get(usbi_tls_key_t key);
int usbi_tls_key_set(usbi_tls_key_t key, void *value);
int usbi_tls_key_delete(usbi_tls_key_t key);
typedef DWORD usbi_tls_key_t;
static inline void usbi_tls_key_create(usbi_tls_key_t *key)
{
*key = TlsAlloc();
}
static inline void *usbi_tls_key_get(usbi_tls_key_t key)
{
return TlsGetValue(key);
}
static inline void usbi_tls_key_set(usbi_tls_key_t key, void *ptr)
{
(void)TlsSetValue(key, ptr);
}
static inline void usbi_tls_key_delete(usbi_tls_key_t key)
{
(void)TlsFree(key);
}

int usbi_get_tid(void);
static inline int usbi_get_tid(void)
{
return (int)GetCurrentThreadId();
}

#endif /* LIBUSB_THREADS_WINDOWS_H */
@@ -31,8 +31,7 @@
#include "wince_usb.h"

// Global variables
const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
int windows_version = WINDOWS_CE;
int errno = 0;
static uint64_t hires_frequency, hires_ticks_to_ps;
static HANDLE driver_handle = INVALID_HANDLE_VALUE;
static int concurrent_usage = -1;
@@ -42,38 +41,39 @@ static int concurrent_usage = -1;
* uses retval as errorcode, or, if 0, use GetLastError()
*/
#if defined(ENABLE_LOGGING)
static const char *windows_error_str(DWORD retval)
static const char *windows_error_str(DWORD error_code)
{
static TCHAR wErr_string[ERR_BUFFER_SIZE];
static char err_string[ERR_BUFFER_SIZE];

DWORD error_code, format_error;
DWORD size;
size_t i;
int len;

error_code = retval ? retval : GetLastError();
if (error_code == 0)
error_code = GetLastError();

safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("[%u] "), (unsigned int)error_code);
len = sprintf(err_string, "[%u] ", (unsigned int)error_code);

size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &wErr_string[safe_tcslen(wErr_string)],
ERR_BUFFER_SIZE - (DWORD)safe_tcslen(wErr_string), NULL);
size = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
wErr_string, ERR_BUFFER_SIZE, NULL);
if (size == 0) {
format_error = GetLastError();
DWORD format_error = GetLastError();
if (format_error)
safe_stprintf(wErr_string, ERR_BUFFER_SIZE,
_T("Windows error code %u (FormatMessage error code %u)"),
snprintf(err_string, ERR_BUFFER_SIZE,
"Windows error code %u (FormatMessage error code %u)",
(unsigned int)error_code, (unsigned int)format_error);
else
safe_stprintf(wErr_string, ERR_BUFFER_SIZE, _T("Unknown error code %u"), (unsigned int)error_code);
snprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", (unsigned int)error_code);
} else {
// Remove CR/LF terminators
for (i = safe_tcslen(wErr_string) - 1; ((wErr_string[i] == 0x0A) || (wErr_string[i] == 0x0D)); i--)
wErr_string[i] = 0;
}
// Remove CR/LF terminators, if present
size_t pos = size - 2;
if (wErr_string[pos] == 0x0D)
wErr_string[pos] = 0;

if (WideCharToMultiByte(CP_ACP, 0, wErr_string, -1, err_string, ERR_BUFFER_SIZE, NULL, NULL) < 0)
strcpy(err_string, "Unable to convert error string");
if (!WideCharToMultiByte(CP_ACP, 0, wErr_string, -1, &err_string[len], ERR_BUFFER_SIZE - len, NULL, NULL))
strcpy(err_string, "Unable to convert error string");
}

return err_string;
}
@@ -109,7 +109,7 @@ static int translate_driver_error(DWORD error)
}
}

static int init_dllimports(void)
static BOOL init_dllimports(void)
{
DLL_GET_HANDLE(ceusbkwrapper);
DLL_LOAD_FUNC(ceusbkwrapper, UkwOpenDriver, TRUE);
@@ -135,7 +135,7 @@ static int init_dllimports(void)
DLL_LOAD_FUNC(ceusbkwrapper, UkwIssueBulkTransfer, TRUE);
DLL_LOAD_FUNC(ceusbkwrapper, UkwIsPipeHalted, TRUE);

return LIBUSB_SUCCESS;
return TRUE;
}

static void exit_dllimports(void)
@@ -186,11 +186,8 @@ static int wince_init(struct libusb_context *ctx)
// NB: concurrent usage supposes that init calls are equally balanced with
// exit calls. If init is called more than exit, we will not exit properly
if ( ++concurrent_usage == 0 ) { // First init?
// Initialize pollable file descriptors
init_polling();

// Load DLL imports
if (init_dllimports() != LIBUSB_SUCCESS) {
if (!init_dllimports()) {
usbi_err(ctx, "could not resolve DLL functions");
r = LIBUSB_ERROR_NOT_SUPPORTED;
goto init_exit;
@@ -223,7 +220,6 @@ static int wince_init(struct libusb_context *ctx)
init_exit: // Holds semaphore here.
if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
exit_dllimports();
exit_polling();

if (driver_handle != INVALID_HANDLE_VALUE) {
UkwCloseDriver(driver_handle);
@@ -239,10 +235,11 @@ static int wince_init(struct libusb_context *ctx)
return r;
}

static void wince_exit(void)
static void wince_exit(struct libusb_context *ctx)
{
HANDLE semaphore;
TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0'
UNUSED(ctx);

_stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF));
semaphore = CreateSemaphore(NULL, 1, 1, sem_name);
@@ -259,7 +256,6 @@ static void wince_exit(void)
// Only works if exits and inits are balanced exactly
if (--concurrent_usage < 0) { // Last exit
exit_dllimports();
exit_polling();

if (driver_handle != INVALID_HANDLE_VALUE) {
UkwCloseDriver(driver_handle);
@@ -328,19 +324,19 @@ static int wince_get_device_list(
}

new_devices = discovered_devs_append(new_devices, dev);
if (!discdevs) {
if (!new_devices) {
r = LIBUSB_ERROR_NO_MEM;
goto err_out;
}

safe_unref_device(dev);
libusb_unref_device(dev);
}

*discdevs = new_devices;
return r;
err_out:
*discdevs = new_devices;
safe_unref_device(dev);
libusb_unref_device(dev);
// Release the remainder of the unprocessed device list.
// The devices added to new_devices already will still be passed up to libusb,
// which can dispose of them at its leisure.
@@ -541,12 +537,9 @@ static void wince_destroy_device(struct libusb_device *dev)
static void wince_clear_transfer_priv(struct usbi_transfer *itransfer)
{
struct wince_transfer_priv *transfer_priv = usbi_transfer_get_os_priv(itransfer);
struct winfd wfd = fd_to_winfd(transfer_priv->pollable_fd.fd);

// No need to cancel transfer as it is either complete or abandoned
wfd.itransfer = NULL;
CloseHandle(wfd.handle);
usbi_free_fd(&transfer_priv->pollable_fd);
usbi_close(transfer_priv->pollable_fd.fd);
transfer_priv->pollable_fd = INVALID_WINFD;
}

static int wince_cancel_transfer(struct usbi_transfer *itransfer)
@@ -570,11 +563,10 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer
BOOL direction_in, ret;
struct winfd wfd;
DWORD flags;
HANDLE eventHandle;
PUKW_CONTROL_HEADER setup = NULL;
const BOOL control_transfer = transfer->type == LIBUSB_TRANSFER_TYPE_CONTROL;
int r;

transfer_priv->pollable_fd = INVALID_WINFD;
if (control_transfer) {
setup = (PUKW_CONTROL_HEADER) transfer->buffer;
direction_in = setup->bmRequestType & LIBUSB_ENDPOINT_IN;
@@ -584,19 +576,18 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer
flags = direction_in ? UKW_TF_IN_TRANSFER : UKW_TF_OUT_TRANSFER;
flags |= UKW_TF_SHORT_TRANSFER_OK;

eventHandle = CreateEvent(NULL, FALSE, FALSE, NULL);
if (eventHandle == NULL) {
usbi_err(ctx, "Failed to create event for async transfer");
wfd = usbi_create_fd();
if (wfd.fd < 0)
return LIBUSB_ERROR_NO_MEM;
}

wfd = usbi_create_fd(eventHandle, direction_in ? RW_READ : RW_WRITE, itransfer, &wince_cancel_transfer);
if (wfd.fd < 0) {
CloseHandle(eventHandle);
return LIBUSB_ERROR_NO_MEM;
r = usbi_add_pollfd(ctx, wfd.fd, direction_in ? POLLIN : POLLOUT);
if (r) {
usbi_close(wfd.fd);
return r;
}

transfer_priv->pollable_fd = wfd;

if (control_transfer) {
// Split out control setup header and data buffer
DWORD bufLen = transfer->length - sizeof(UKW_CONTROL_HEADER);
@@ -612,17 +603,14 @@ static int wince_submit_control_or_bulk_transfer(struct usbi_transfer *itransfer
int libusbErr = translate_driver_error(GetLastError());
usbi_err(ctx, "UkwIssue%sTransfer failed: error %u",
control_transfer ? "Control" : "Bulk", (unsigned int)GetLastError());
wince_clear_transfer_priv(itransfer);
usbi_remove_pollfd(ctx, wfd.fd);
usbi_close(wfd.fd);
transfer_priv->pollable_fd = INVALID_WINFD;
return libusbErr;
}
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, direction_in ? POLLIN : POLLOUT);

return LIBUSB_SUCCESS;
}

static int wince_submit_iso_transfer(struct usbi_transfer *itransfer)
{
return LIBUSB_ERROR_NOT_SUPPORTED;
return LIBUSB_SUCCESS;
}

static int wince_submit_transfer(struct usbi_transfer *itransfer)
@@ -635,7 +623,6 @@ static int wince_submit_transfer(struct usbi_transfer *itransfer)
case LIBUSB_TRANSFER_TYPE_INTERRUPT:
return wince_submit_control_or_bulk_transfer(itransfer);
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
return wince_submit_iso_transfer(itransfer);
case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
return LIBUSB_ERROR_NOT_SUPPORTED;
default:
@@ -763,7 +750,7 @@ static int wince_handle_events(
struct wince_transfer_priv* transfer_priv = NULL;
POLL_NFDS_TYPE i = 0;
BOOL found = FALSE;
struct usbi_transfer *transfer;
struct usbi_transfer *itransfer;
DWORD io_size, io_result;
int r = LIBUSB_SUCCESS;

@@ -780,8 +767,8 @@ static int wince_handle_events(
// Because a Windows OVERLAPPED is used for poll emulation,
// a pollable fd is created and stored with each transfer
usbi_mutex_lock(&ctx->flying_transfers_lock);
list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
transfer_priv = usbi_transfer_get_os_priv(transfer);
list_for_each_entry(itransfer, &ctx->flying_transfers, list, struct usbi_transfer) {
transfer_priv = usbi_transfer_get_os_priv(itransfer);
if (transfer_priv->pollable_fd.fd == fds[i].fd) {
found = TRUE;
break;
@@ -796,7 +783,7 @@ static int wince_handle_events(
// 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.
wince_handle_callback(transfer, io_result, io_size);
wince_handle_callback(itransfer, io_result, io_size);
} else if (found) {
usbi_err(ctx, "matching transfer for fd %d has not completed", fds[i]);
r = LIBUSB_ERROR_OTHER;
@@ -832,14 +819,14 @@ static int wince_clock_gettime(int clk_id, struct timespec *tp)
// Fall through and return real-time if monotonic read failed or was not detected @ init
case USBI_CLOCK_REALTIME:
// We follow http://msdn.microsoft.com/en-us/library/ms724928%28VS.85%29.aspx
// with a predef epoch_time to have an epoch that starts at 1970.01.01 00:00
// with a predef epoch time to have an epoch that starts at 1970.01.01 00:00
// Note however that our resolution is bounded by the Windows system time
// functions and is at best of the order of 1 ms (or, usually, worse)
GetSystemTime(&st);
SystemTimeToFileTime(&st, &filetime);
rtime.LowPart = filetime.dwLowDateTime;
rtime.HighPart = filetime.dwHighDateTime;
rtime.QuadPart -= epoch_time;
rtime.QuadPart -= EPOCH_TIME;
tp->tv_sec = (long)(rtime.QuadPart / 10000000);
tp->tv_nsec = (long)((rtime.QuadPart % 10000000)*100);
return LIBUSB_SUCCESS;
@@ -848,11 +835,12 @@ static int wince_clock_gettime(int clk_id, struct timespec *tp)
}
}

const struct usbi_os_backend wince_backend = {
const struct usbi_os_backend usbi_backend = {
"Windows CE",
0,
wince_init,
wince_exit,
NULL, /* set_option() */

wince_get_device_list,
NULL, /* hotplug_poll */
@@ -893,6 +881,7 @@ const struct usbi_os_backend wince_backend = {
NULL, /* handle_transfer_completion() */

wince_clock_gettime,
0,
sizeof(struct wince_device_priv),
0,
sizeof(struct wince_transfer_priv),
@@ -37,38 +37,23 @@
#define false FALSE
#endif

#define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime

#if defined(__CYGWIN__ )
#define _stricmp strcasecmp
#define _snprintf snprintf
#define _strdup strdup
// _beginthreadex is MSVCRT => unavailable for cygwin. Fallback to using CreateThread
#define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, (LPDWORD)f)
#endif

#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0)
#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
#define safe_min(a, b) MIN((size_t)(a), (size_t)(b))
#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1)
#define safe_strncat(dst, dst_max, src, count) strncat(dst, src, safe_min(count, dst_max - safe_strlen(dst) - 1))
#define safe_strcat(dst, dst_max, src) safe_strncat(dst, dst_max, src, safe_strlen(src)+1)
#define safe_strcmp(str1, str2) strcmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
#define safe_strlen(str) ((str==NULL)?0:strlen(str))
#define safe_sprintf(dst, count, ...) do {_snprintf(dst, count, __VA_ARGS__); (dst)[(count)-1] = 0; } while(0)
#define safe_stprintf _sntprintf
#define safe_tcslen(str) ((str==NULL)?0:_tcslen(str))
#define safe_unref_device(dev) do {if (dev != NULL) {libusb_unref_device(dev); dev = NULL;}} while(0)
#define wchar_to_utf8_ms(wstr, str, strlen) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, strlen, NULL, NULL)
#define safe_free(p) do {if (p != NULL) {free((void *)p); p = NULL;}} while (0)

#ifndef ARRAYSIZE
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif

#define ERR_BUFFER_SIZE 256


/*
* API macros - leveraged from libusb-win32 1.x
*/
@@ -83,31 +68,35 @@
/*
* Macros for handling DLL themselves
*/
#define DLL_HANDLE_NAME(name) __dll_##name##_handle

#define DLL_DECLARE_HANDLE(name) \
static HMODULE __dll_##name##_handle = NULL
static HMODULE DLL_HANDLE_NAME(name) = NULL

#define DLL_GET_HANDLE(name) \
do { \
__dll_##name##_handle = DLL_LOAD_LIBRARY(name); \
if (!__dll_##name##_handle) \
return LIBUSB_ERROR_OTHER; \
DLL_HANDLE_NAME(name) = DLL_LOAD_LIBRARY(name); \
if (!DLL_HANDLE_NAME(name)) \
return FALSE; \
} while (0)

#define DLL_FREE_HANDLE(name) \
do { \
if (__dll_##name##_handle) { \
FreeLibrary(__dll_##name##_handle); \
__dll_##name##_handle = NULL; \
if (DLL_HANDLE_NAME(name)) { \
FreeLibrary(DLL_HANDLE_NAME(name)); \
DLL_HANDLE_NAME(name) = NULL; \
} \
} while(0)
} while (0)


/*
* Macros for handling functions within a DLL
*/
#define DLL_FUNC_NAME(name) __dll_##name##_func_t

#define DLL_DECLARE_FUNC_PREFIXNAME(api, ret, prefixname, name, args) \
typedef ret (api * __dll_##name##_func_t)args; \
static __dll_##name##_func_t prefixname = NULL
typedef ret (api * DLL_FUNC_NAME(name))args; \
static DLL_FUNC_NAME(name) prefixname = NULL

#define DLL_DECLARE_FUNC(api, ret, name, args) \
DLL_DECLARE_FUNC_PREFIXNAME(api, ret, name, name, args)
@@ -116,22 +105,22 @@

#define DLL_LOAD_FUNC_PREFIXNAME(dll, prefixname, name, ret_on_failure) \
do { \
HMODULE h = __dll_##dll##_handle; \
prefixname = (__dll_##name##_func_t)GetProcAddress(h, \
HMODULE h = DLL_HANDLE_NAME(dll); \
prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \
DLL_STRINGIFY(name)); \
if (prefixname) \
break; \
prefixname = (__dll_##name##_func_t)GetProcAddress(h, \
prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \
DLL_STRINGIFY(name) DLL_STRINGIFY(A)); \
if (prefixname) \
break; \
prefixname = (__dll_##name##_func_t)GetProcAddress(h, \
prefixname = (DLL_FUNC_NAME(name))GetProcAddress(h, \
DLL_STRINGIFY(name) DLL_STRINGIFY(W)); \
if (prefixname) \
break; \
if (ret_on_failure) \
return LIBUSB_ERROR_NOT_FOUND; \
} while(0)
return FALSE; \
} while (0)

#define DLL_LOAD_FUNC(dll, name, ret_on_failure) \
DLL_LOAD_FUNC_PREFIXNAME(dll, name, name, ret_on_failure)

Large diffs are not rendered by default.

@@ -26,48 +26,85 @@

#pragma once

// Missing from MinGW
#if !defined(FACILITY_SETUPAPI)
#define FACILITY_SETUPAPI 15
#endif
#include "windows_nt_shared_types.h"

typedef struct USB_CONFIGURATION_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
USHORT wTotalLength;
UCHAR bNumInterfaces;
UCHAR bConfigurationValue;
UCHAR iConfiguration;
UCHAR bmAttributes;
UCHAR MaxPower;
} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;
/* Windows versions */
enum windows_version {
WINDOWS_UNDEFINED,
WINDOWS_2000,
WINDOWS_XP,
WINDOWS_2003, // Also XP x64
WINDOWS_VISTA,
WINDOWS_7,
WINDOWS_8,
WINDOWS_8_1,
WINDOWS_10,
WINDOWS_11_OR_LATER
};

typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;
extern enum windows_version windows_version;

int windows_common_init(struct libusb_context *ctx);
void windows_common_exit(void);
/* This call is only available from Vista */
extern BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED);

unsigned long htab_hash(const char *str);
int windows_clock_gettime(int clk_id, struct timespec *tp);
struct windows_backend {
int (*init)(struct libusb_context *ctx);
void (*exit)(struct libusb_context *ctx);
int (*get_device_list)(struct libusb_context *ctx,
struct discovered_devs **discdevs);
int (*open)(struct libusb_device_handle *dev_handle);
void (*close)(struct libusb_device_handle *dev_handle);
int (*get_device_descriptor)(struct libusb_device *device, unsigned char *buffer);
int (*get_active_config_descriptor)(struct libusb_device *device,
unsigned char *buffer, size_t len);
int (*get_config_descriptor)(struct libusb_device *device,
uint8_t config_index, unsigned char *buffer, size_t len);
int (*get_config_descriptor_by_value)(struct libusb_device *device,
uint8_t bConfigurationValue, unsigned char **buffer);
int (*get_configuration)(struct libusb_device_handle *dev_handle, int *config);
int (*set_configuration)(struct libusb_device_handle *dev_handle, int config);
int (*claim_interface)(struct libusb_device_handle *dev_handle, int interface_number);
int (*release_interface)(struct libusb_device_handle *dev_handle, int interface_number);
int (*set_interface_altsetting)(struct libusb_device_handle *dev_handle,
int interface_number, int altsetting);
int (*clear_halt)(struct libusb_device_handle *dev_handle,
unsigned char endpoint);
int (*reset_device)(struct libusb_device_handle *dev_handle);
void (*destroy_device)(struct libusb_device *dev);
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);
};

struct windows_context_priv {
const struct windows_backend *backend;
};

typedef void(*CLEAR_TRANSFER_PRIV)(struct usbi_transfer *itransfer);
typedef int(*COPY_TRANSFER_DATA)(struct usbi_transfer *itransfer, uint32_t io_size);
typedef struct winfd *(*GET_FD)(struct usbi_transfer *transfer);
typedef void(*GET_OVERLAPPED_RESULT)(struct usbi_transfer *transfer, struct winfd *pollable_fd, DWORD *io_result, DWORD *io_size);
union windows_device_priv {
struct usbdk_device_priv usbdk_priv;
struct winusb_device_priv winusb_priv;
};

typedef struct win_backend
{
CLEAR_TRANSFER_PRIV clear_transfer_priv;
COPY_TRANSFER_DATA copy_transfer_data;
GET_FD get_fd;
GET_OVERLAPPED_RESULT get_overlapped_result;
} win_backend;
union windows_device_handle_priv {
struct usbdk_device_handle_priv usbdk_priv;
struct winusb_device_handle_priv winusb_priv;
};

void win_nt_init(win_backend *backend);
union windows_transfer_priv {
struct usbdk_transfer_priv usbdk_priv;
struct winusb_transfer_priv winusb_priv;
};

void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size);
int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready);
extern const struct windows_backend usbdk_backend;
extern const struct windows_backend winusb_backend;

unsigned long htab_hash(const char *str);
void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size);

#if defined(ENABLE_LOGGING)
const char *windows_error_str(DWORD retval);
const char *windows_error_str(DWORD error_code);
#endif
@@ -0,0 +1,147 @@
#pragma once

#include "windows_common.h"

#include <pshpack1.h>

typedef struct USB_DEVICE_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
USHORT bcdUSB;
UCHAR bDeviceClass;
UCHAR bDeviceSubClass;
UCHAR bDeviceProtocol;
UCHAR bMaxPacketSize0;
USHORT idVendor;
USHORT idProduct;
USHORT bcdDevice;
UCHAR iManufacturer;
UCHAR iProduct;
UCHAR iSerialNumber;
UCHAR bNumConfigurations;
} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;

typedef struct USB_CONFIGURATION_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
USHORT wTotalLength;
UCHAR bNumInterfaces;
UCHAR bConfigurationValue;
UCHAR iConfiguration;
UCHAR bmAttributes;
UCHAR MaxPower;
} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;

#include <poppack.h>

#define MAX_DEVICE_ID_LEN 200

typedef struct USB_DK_DEVICE_ID {
WCHAR DeviceID[MAX_DEVICE_ID_LEN];
WCHAR InstanceID[MAX_DEVICE_ID_LEN];
} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID;

typedef struct USB_DK_DEVICE_INFO {
USB_DK_DEVICE_ID ID;
ULONG64 FilterID;
ULONG64 Port;
ULONG64 Speed;
USB_DEVICE_DESCRIPTOR DeviceDescriptor;
} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO;

typedef struct USB_DK_ISO_TRANSFER_RESULT {
ULONG64 ActualLength;
ULONG64 TransferResult;
} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT;

typedef struct USB_DK_GEN_TRANSFER_RESULT {
ULONG64 BytesTransferred;
ULONG64 UsbdStatus; // USBD_STATUS code
} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT;

typedef struct USB_DK_TRANSFER_RESULT {
USB_DK_GEN_TRANSFER_RESULT GenResult;
PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT
} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT;

typedef struct USB_DK_TRANSFER_REQUEST {
ULONG64 EndpointAddress;
PVOID64 Buffer;
ULONG64 BufferLength;
ULONG64 TransferType;
ULONG64 IsochronousPacketsArraySize;
PVOID64 IsochronousPacketsArray;
USB_DK_TRANSFER_RESULT Result;
} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST;

struct usbdk_device_priv {
USB_DK_DEVICE_INFO info;
PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors;
HANDLE redirector_handle;
HANDLE system_handle;
uint8_t active_configuration;
};

struct winusb_device_priv {
bool initialized;
bool root_hub;
uint8_t active_config;
uint8_t depth; // distance to HCD
const struct windows_usb_api_backend *apib;
char *dev_id;
char *path; // device interface path
int sub_api; // for WinUSB-like APIs
struct {
char *path; // each interface needs a device interface path,
const struct windows_usb_api_backend *apib; // an API backend (multiple drivers support),
int sub_api;
int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS)
uint8_t *endpoint;
int current_altsetting;
bool restricted_functionality; // indicates if the interface functionality is restricted
// by Windows (eg. HID keyboards or mice cannot do R/W)
} usb_interface[USB_MAXINTERFACES];
struct hid_device_priv *hid;
USB_DEVICE_DESCRIPTOR dev_descriptor;
PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors
};

struct usbdk_device_handle_priv {
// Not currently used
char dummy;
};

struct winusb_device_handle_priv {
int active_interface;
struct {
HANDLE dev_handle; // WinUSB needs an extra handle for the file
HANDLE api_handle; // used by the API to communicate with the device
} interface_handle[USB_MAXINTERFACES];
int autoclaim_count[USB_MAXINTERFACES]; // For auto-release
};

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;

// For isochronous transfers with LibUSBk driver:
void *iso_context;

// For isochronous transfers with Microsoft WinUSB driver:
void *isoch_buffer_handle; // The isoch_buffer_handle to free at the end of the transfer
BOOL iso_break_stream; // Whether the isoch. stream was to be continued in the last call of libusb_submit_transfer.
// As we this structure is zeroed out upon initialization, we need to use inverse logic here.
libusb_transfer_cb_fn iso_user_callback; // Original transfer callback of the user. Might be used for isochronous transfers.
};

Large diffs are not rendered by default.

@@ -23,56 +23,13 @@

#pragma once

typedef struct tag_USB_DK_DEVICE_ID {
WCHAR DeviceID[MAX_DEVICE_ID_LEN];
WCHAR InstanceID[MAX_DEVICE_ID_LEN];
} USB_DK_DEVICE_ID, *PUSB_DK_DEVICE_ID;
#include "windows_nt_common.h"

static inline void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, PCWCHAR DeviceID, PCWCHAR InstanceID)
{
wcsncpy_s(ID->DeviceID, DeviceID, MAX_DEVICE_ID_LEN);
wcsncpy_s(ID->InstanceID, InstanceID, MAX_DEVICE_ID_LEN);
}

typedef struct tag_USB_DK_DEVICE_INFO {
USB_DK_DEVICE_ID ID;
ULONG64 FilterID;
ULONG64 Port;
ULONG64 Speed;
USB_DEVICE_DESCRIPTOR DeviceDescriptor;
} USB_DK_DEVICE_INFO, *PUSB_DK_DEVICE_INFO;

typedef struct tag_USB_DK_CONFIG_DESCRIPTOR_REQUEST {
typedef struct USB_DK_CONFIG_DESCRIPTOR_REQUEST {
USB_DK_DEVICE_ID ID;
ULONG64 Index;
} USB_DK_CONFIG_DESCRIPTOR_REQUEST, *PUSB_DK_CONFIG_DESCRIPTOR_REQUEST;

typedef struct tag_USB_DK_ISO_TRANSFER_RESULT {
ULONG64 ActualLength;
ULONG64 TransferResult;
} USB_DK_ISO_TRANSFER_RESULT, *PUSB_DK_ISO_TRANSFER_RESULT;

typedef struct tag_USB_DK_GEN_TRANSFER_RESULT {
ULONG64 BytesTransferred;
ULONG64 UsbdStatus; // USBD_STATUS code
} USB_DK_GEN_TRANSFER_RESULT, *PUSB_DK_GEN_TRANSFER_RESULT;

typedef struct tag_USB_DK_TRANSFER_RESULT {
USB_DK_GEN_TRANSFER_RESULT GenResult;
PVOID64 IsochronousResultsArray; // array of USB_DK_ISO_TRANSFER_RESULT
} USB_DK_TRANSFER_RESULT, *PUSB_DK_TRANSFER_RESULT;

typedef struct tag_USB_DK_TRANSFER_REQUEST {
ULONG64 EndpointAddress;
PVOID64 Buffer;
ULONG64 BufferLength;
ULONG64 TransferType;
ULONG64 IsochronousPacketsArraySize;
PVOID64 IsochronousPacketsArray;

USB_DK_TRANSFER_RESULT Result;
} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST;

typedef enum {
TransferFailure = 0,
TransferSuccess,
@@ -90,7 +47,7 @@ typedef enum {
typedef enum {
ControlTransferType,
BulkTransferType,
IntertuptTransferType,
InterruptTransferType,
IsochronousTransferType
} USB_DK_TRANSFER_TYPE;

Large diffs are not rendered by default.

Large diffs are not rendered by default.

@@ -38,7 +38,7 @@ static size_t usbi_locale = 0;
* How to add a new \ref libusb_strerror() translation:
* <ol>
* <li> Download the latest \c strerror.c from:<br>
* https://raw.github.com/libusb/libusb/master/libusb/sterror.c </li>
* https://raw.github.com/libusb/libusb/master/libusb/strerror.c </li>
* <li> Open the file in an UTF-8 capable editor </li>
* <li> Add the 2 letter <a href="http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes">ISO 639-1</a>
* code for your locale at the end of \c usbi_locale_supported[]<br>
@@ -60,7 +60,7 @@ static size_t usbi_locale = 0;
* </ol>
*/

static const char* usbi_locale_supported[] = { "en", "nl", "fr", "ru" };
static const char* usbi_locale_supported[] = { "en", "nl", "fr", "ru", "de", "hu" };
static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUSB_ERROR_COUNT] = {
{ /* English (en) */
"Success",
@@ -122,6 +122,37 @@ static const char* usbi_localized_errors[ARRAYSIZE(usbi_locale_supported)][LIBUS
"Память исчерпана",
"Операция не поддерживается данной платформой",
"Неизвестная ошибка"

}, { /* German (de) */
"Erfolgreich",
"Eingabe-/Ausgabefehler",
"Ungültiger Parameter",
"Keine Berechtigung (Zugriffsrechte fehlen)",
"Kein passendes Gerät gefunden (es könnte entfernt worden sein)",
"Entität nicht gefunden",
"Die Ressource ist belegt",
"Die Wartezeit für die Operation ist abgelaufen",
"Mehr Daten empfangen als erwartet",
"Datenübergabe unterbrochen (broken pipe)",
"Unterbrechung während des Betriebssystemaufrufs",
"Nicht genügend Hauptspeicher verfügbar",
"Die Operation wird nicht unterstützt oder ist auf dieser Platform nicht implementiert",
"Allgemeiner Fehler",
}, { /* Hungarian (hu) */
"Sikeres",
"Be-/kimeneti hiba",
"Érvénytelen paraméter",
"Hozzáférés megtagadva",
"Az eszköz nem található (eltávolították?)",
"Nem található",
"Az erőforrás foglalt",
"Időtúllépés",
"Túlcsordulás",
"Törött adatcsatorna",
"Rendszerhívás megszakítva",
"Nincs elég memória",
"A művelet nem támogatott ezen a rendszeren",
"Általános hiba",
}
};

@@ -7,12 +7,12 @@
#define LIBUSB_MINOR 0
#endif
#ifndef LIBUSB_MICRO
#define LIBUSB_MICRO 21
#define LIBUSB_MICRO 23
#endif
#ifndef LIBUSB_NANO
#define LIBUSB_NANO 0
#endif
/* LIBUSB_RC is the release candidate suffix. Should normally be empty. */
#ifndef LIBUSB_RC
#define LIBUSB_RC ""
#define LIBUSB_RC "-rc1"
#endif
@@ -1 +1 @@
#define LIBUSB_NANO 11156
#define LIBUSB_NANO 11367
@@ -67,10 +67,11 @@
<ClInclude Include="libusb\version_nano.h" />
<ClInclude Include="libusb\os\windows_common.h" />
<ClInclude Include="libusb\os\windows_nt_common.h" />
<ClInclude Include="libusb\os\windows_nt_shared_types.h" />
<ClInclude Include="libusb\os\windows_usbdk.h" />
<ClInclude Include="libusb\os\windows_winusb.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

This file was deleted.

@@ -6,16 +6,18 @@
#endif

/* Visual Studio 2015 and later defines timespec */
#if defined(_MSC_VER) && (_MSC_VER >= 1900)
#if (_MSC_VER >= 1900)
#define _TIMESPEC_DEFINED 1
#endif

/* Disable: warning C4200: nonstandard extension used : zero-sized array in struct/union */
#pragma warning(disable:4200)
/* Disable: warning C4324: structure was padded due to __declspec(align()) */
#pragma warning(disable:4324)
/* Disable: warning C6258: Using TerminateThread does not allow proper thread clean up */
#pragma warning(disable: 6258)
#pragma warning(disable:6258)
/* Disable: warning C4996: 'GetVersionA': was declared deprecated */
#pragma warning(disable: 4996)
#pragma warning(disable:4996)

#if defined(_PREFAST_)
/* Disable "Banned API" errors when using the MS's WDK OACR/Prefast */
@@ -45,6 +47,5 @@
#define HAVE_MISSING_H
#else
#define OS_WINDOWS 1
#define HAVE_SIGNAL_H 1
#define HAVE_SYS_TYPES_H 1
#endif

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.