Windows: Source file cleanup

This commit addresses a few different issues:

1) Whitespace made consistent with the rest of the library source
2) Formatting of function and variable declarations made consistent
   with the rest of the library source
3) Functions and variables made static where possible
4) Definitions in header files moved if not used publicly

Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
This commit is contained in:
Chris Dickens
2016-01-26 23:40:33 -08:00
parent 48bfef6c1d
commit a3ec36d3ec
8 changed files with 1909 additions and 1890 deletions
+1 -3
View File
@@ -58,9 +58,7 @@
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
#define ERR_BUFFER_SIZE 256
#define TIMER_REQUEST_RETRY_MS 100
#define MAX_TIMER_SEMAPHORES 128
#define ERR_BUFFER_SIZE 256
/*
+333 -346
View File
@@ -23,10 +23,10 @@
*/
#include <config.h>
#include <stdio.h>
#include <inttypes.h>
#include <process.h>
#include <stdio.h>
#include "libusbi.h"
#include "windows_common.h"
@@ -36,91 +36,96 @@
const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
// Global variables for clock_gettime mechanism
uint64_t hires_ticks_to_ps;
uint64_t hires_frequency;
static uint64_t hires_ticks_to_ps;
static uint64_t hires_frequency;
#define WM_TIMER_REQUEST (WM_USER + 1)
#define WM_TIMER_EXIT (WM_USER + 2)
#define TIMER_REQUEST_RETRY_MS 100
#define WM_TIMER_REQUEST (WM_USER + 1)
#define WM_TIMER_EXIT (WM_USER + 2)
// used for monotonic clock_gettime()
struct timer_request {
struct timespec *tp;
HANDLE event;
struct timespec *tp;
HANDLE event;
};
// Timer thread
HANDLE timer_thread = NULL;
DWORD timer_thread_id = 0;
static HANDLE timer_thread = NULL;
static DWORD timer_thread_id = 0;
/* User32 dependencies */
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT));
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, PeekMessageA, (LPMSG, HWND, UINT, UINT, UINT));
DLL_DECLARE_PREFIXED(WINAPI, BOOL, p, PostThreadMessageA, (DWORD, UINT, WPARAM, LPARAM));
static unsigned __stdcall windows_clock_gettime_threaded(void* param);
static unsigned __stdcall windows_clock_gettime_threaded(void *param);
/*
* Converts a windows error to human readable string
* uses retval as errorcode, or, if 0, use GetLastError()
*/
#if defined(ENABLE_LOGGING)
char *windows_error_str(uint32_t retval)
const char *windows_error_str(DWORD retval)
{
static char err_string[ERR_BUFFER_SIZE];
static char err_string[ERR_BUFFER_SIZE];
DWORD size;
ssize_t i;
uint32_t error_code, format_error;
DWORD error_code, format_error;
DWORD size;
ssize_t i;
error_code = retval ? retval : GetLastError();
error_code = retval ? retval : GetLastError();
safe_sprintf(err_string, ERR_BUFFER_SIZE, "[%u] ", error_code);
safe_sprintf(err_string, ERR_BUFFER_SIZE, "[%u] ", error_code);
// Translate codes returned by SetupAPI. The ones we are dealing with are either
// in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
// See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
switch (error_code & 0xE0000000) {
case 0:
error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
break;
case 0xE0000000:
error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
break;
default:
break;
}
// Translate codes returned by SetupAPI. The ones we are dealing with are either
// in 0x0000xxxx or 0xE000xxxx and can be distinguished from standard error codes.
// See http://msdn.microsoft.com/en-us/library/windows/hardware/ff545011.aspx
switch (error_code & 0xE0000000) {
case 0:
error_code = HRESULT_FROM_WIN32(error_code); // Still leaves ERROR_SUCCESS unmodified
break;
case 0xE0000000:
error_code = 0x80000000 | (FACILITY_SETUPAPI << 16) | (error_code & 0x0000FFFF);
break;
default:
break;
}
size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_string[safe_strlen(err_string)],
ERR_BUFFER_SIZE - (DWORD)safe_strlen(err_string), NULL);
if (size == 0) {
format_error = GetLastError();
if (format_error)
safe_sprintf(err_string, ERR_BUFFER_SIZE,
"Windows error code %u (FormatMessage error code %u)", error_code, format_error);
else
safe_sprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", error_code);
}
else {
// Remove CR/LF terminators
for (i = safe_strlen(err_string) - 1; (i >= 0) && ((err_string[i] == 0x0A) || (err_string[i] == 0x0D)); i--) {
err_string[i] = 0;
}
}
return err_string;
size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_string[safe_strlen(err_string)],
ERR_BUFFER_SIZE - (DWORD)safe_strlen(err_string), NULL);
if (size == 0) {
format_error = GetLastError();
if (format_error)
safe_sprintf(err_string, ERR_BUFFER_SIZE,
"Windows error code %u (FormatMessage error code %u)", error_code, format_error);
else
safe_sprintf(err_string, ERR_BUFFER_SIZE, "Unknown error code %u", error_code);
}
else {
// Remove CR/LF terminators
for (i = safe_strlen(err_string) - 1; (i >= 0) && ((err_string[i] == 0x0A) || (err_string[i] == 0x0D)); i--)
err_string[i] = 0;
}
return err_string;
}
#endif
/* Hash table functions - modified From glibc 2.3.2:
[Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
[Knuth] The Art of Computer Programming, part 3 (6.4) */
#define HTAB_SIZE 1021
typedef struct htab_entry {
unsigned long used;
char* str;
} htab_entry;
htab_entry* htab_table = NULL;
usbi_mutex_t htab_write_mutex = NULL;
unsigned long htab_size, htab_filled;
static htab_entry *htab_table = NULL;
static usbi_mutex_t htab_write_mutex = NULL;
static unsigned long htab_size, htab_filled;
/* For the used double hash method the table size has to be a prime. To
correct the user given table size we need a prime test. This trivial
@@ -141,7 +146,7 @@ static int isprime(unsigned long number)
We allocate one element more as the found prime number says.
This is done for more effective indexing as explained in the
comment for the hash function. */
int htab_create(struct libusb_context *ctx, unsigned long nel)
static bool htab_create(struct libusb_context *ctx, unsigned long nel)
{
if (htab_table != NULL) {
usbi_err(ctx, "hash table already allocated");
@@ -152,7 +157,7 @@ int htab_create(struct libusb_context *ctx, unsigned long nel)
// Change nel to the first prime number not smaller as nel.
nel |= 1;
while(!isprime(nel))
while (!isprime(nel))
nel += 2;
htab_size = nel;
@@ -160,47 +165,47 @@ int htab_create(struct libusb_context *ctx, unsigned long nel)
htab_filled = 0;
// allocate memory and zero out.
htab_table = (htab_entry*) calloc(htab_size + 1, sizeof(htab_entry));
htab_table = calloc(htab_size + 1, sizeof(htab_entry));
if (htab_table == NULL) {
usbi_err(ctx, "could not allocate space for hash table");
return 0;
return false;
}
return 1;
return true;
}
/* After using the hash table it has to be destroyed. */
void htab_destroy(void)
static void htab_destroy(void)
{
size_t i;
if (htab_table == NULL) {
unsigned long i;
if (htab_table == NULL)
return;
for (i = 0; i < htab_size; i++) {
if (htab_table[i].used)
safe_free(htab_table[i].str);
}
for (i=0; i<htab_size; i++) {
if (htab_table[i].used) {
safe_free(htab_table[i].str);
}
}
usbi_mutex_destroy(&htab_write_mutex);
safe_free(htab_table);
}
/* This is the search function. It uses double hashing with open addressing.
We use an trick to speed up the lookup. The table is created with one
We use a trick to speed up the lookup. The table is created with one
more element available. This enables us to use the index zero special.
This index will never be used because we store the first hash index in
the field used where zero means not used. Every other value means used.
The used field can be used as a first fast comparison for equality of
the stored and the parameter value. This helps to prevent unnecessary
expensive calls of strcmp. */
unsigned long htab_hash(char* str)
unsigned long htab_hash(const char *str)
{
unsigned long hval, hval2;
unsigned long idx;
unsigned long r = 5381;
int c;
char* sz = str;
const char *sz = str;
if (str == NULL)
return 0;
@@ -220,11 +225,9 @@ unsigned long htab_hash(char* str)
idx = hval;
if (htab_table[idx].used) {
if ( (htab_table[idx].used == hval)
&& (safe_strcmp(str, htab_table[idx].str) == 0) ) {
// existing hash
return idx;
}
if ((htab_table[idx].used == hval) && (safe_strcmp(str, htab_table[idx].str) == 0))
return idx; // existing hash
usbi_dbg("hash collision ('%s' vs '%s')", str, htab_table[idx].str);
// Second hash function, as suggested in [Knuth]
@@ -232,22 +235,18 @@ unsigned long htab_hash(char* str)
do {
// Because size is prime this guarantees to step through all available indexes
if (idx <= hval2) {
if (idx <= hval2)
idx = htab_size + idx - hval2;
} else {
else
idx -= hval2;
}
// If we visited all entries leave the loop unsuccessfully
if (idx == hval) {
if (idx == hval)
break;
}
// If entry is found use it.
if ( (htab_table[idx].used == hval)
&& (safe_strcmp(str, htab_table[idx].str) == 0) ) {
if ((htab_table[idx].used == hval) && (safe_strcmp(str, htab_table[idx].str) == 0))
return idx;
}
}
while (htab_table[idx].used);
}
@@ -268,13 +267,13 @@ unsigned long htab_hash(char* str)
// string (same hash, different string) at the same time is extremely low
safe_free(htab_table[idx].str);
htab_table[idx].used = hval;
htab_table[idx].str = (char*) malloc(safe_strlen(str)+1);
htab_table[idx].str = malloc(safe_strlen(str) + 1);
if (htab_table[idx].str == NULL) {
usbi_err(NULL, "could not duplicate string for hash table");
usbi_mutex_unlock(&htab_write_mutex);
return 0;
}
memcpy(htab_table[idx].str, str, safe_strlen(str)+1);
memcpy(htab_table[idx].str, str, safe_strlen(str) + 1);
++htab_filled;
usbi_mutex_unlock(&htab_write_mutex);
@@ -283,334 +282,322 @@ unsigned long htab_hash(char* str)
static int windows_init_dlls(void)
{
DLL_LOAD_PREFIXED(User32.dll, p, GetMessageA, TRUE);
DLL_LOAD_PREFIXED(User32.dll, p, PeekMessageA, TRUE);
DLL_LOAD_PREFIXED(User32.dll, p, PostThreadMessageA, TRUE);
return LIBUSB_SUCCESS;
DLL_LOAD_PREFIXED(User32.dll, p, GetMessageA, TRUE);
DLL_LOAD_PREFIXED(User32.dll, p, PeekMessageA, TRUE);
DLL_LOAD_PREFIXED(User32.dll, p, PostThreadMessageA, TRUE);
return LIBUSB_SUCCESS;
}
bool windows_init_clock(struct libusb_context *ctx)
static bool windows_init_clock(struct libusb_context *ctx)
{
DWORD_PTR affinity, dummy;
HANDLE event = NULL;
LARGE_INTEGER li_frequency;
int i;
DWORD_PTR affinity, dummy;
HANDLE event = NULL;
LARGE_INTEGER li_frequency;
int i;
if (QueryPerformanceFrequency(&li_frequency)) {
// Load DLL imports
if (windows_init_dlls() != LIBUSB_SUCCESS) {
usbi_err(ctx, "could not resolve DLL functions");
return false;
}
if (QueryPerformanceFrequency(&li_frequency)) {
// Load DLL imports
if (windows_init_dlls() != LIBUSB_SUCCESS) {
usbi_err(ctx, "could not resolve DLL functions");
return false;
}
// The hires frequency can go as high as 4 GHz, so we'll use a conversion
// to picoseconds to compute the tv_nsecs part in clock_gettime
hires_frequency = li_frequency.QuadPart;
hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
// The hires frequency can go as high as 4 GHz, so we'll use a conversion
// to picoseconds to compute the tv_nsecs part in clock_gettime
hires_frequency = li_frequency.QuadPart;
hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
// Because QueryPerformanceCounter might report different values when
// running on different cores, we create a separate thread for the timer
// calls, which we glue to the first available core always to prevent timing discrepancies.
if (!GetProcessAffinityMask(GetCurrentProcess(), &affinity, &dummy) || (affinity == 0)) {
usbi_err(ctx, "could not get process affinity: %s", windows_error_str(0));
return false;
}
// The process affinity mask is a bitmask where each set bit represents a core on
// which this process is allowed to run, so we find the first set bit
for (i = 0; !(affinity & (DWORD_PTR)(1 << i)); i++);
affinity = (DWORD_PTR)(1 << i);
// Because QueryPerformanceCounter might report different values when
// running on different cores, we create a separate thread for the timer
// calls, which we glue to the first available core always to prevent timing discrepancies.
if (!GetProcessAffinityMask(GetCurrentProcess(), &affinity, &dummy) || (affinity == 0)) {
usbi_err(ctx, "could not get process affinity: %s", windows_error_str(0));
return false;
}
usbi_dbg("timer thread will run on core #%d", i);
// The process affinity mask is a bitmask where each set bit represents a core on
// which this process is allowed to run, so we find the first set bit
for (i = 0; !(affinity & (DWORD_PTR)(1 << i)); i++);
affinity = (DWORD_PTR)(1 << i);
event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (event == NULL) {
usbi_err(ctx, "could not create event: %s", windows_error_str(0));
return false;
}
timer_thread = (HANDLE)_beginthreadex(NULL, 0, windows_clock_gettime_threaded, (void *)event,
0, (unsigned int *)&timer_thread_id);
if (timer_thread == NULL) {
usbi_err(ctx, "unable to create timer thread - aborting");
CloseHandle(event);
return false;
}
if (!SetThreadAffinityMask(timer_thread, affinity)) {
usbi_warn(ctx, "unable to set timer thread affinity, timer discrepancies may arise");
}
usbi_dbg("timer thread will run on core #%d", i);
// Wait for timer thread to init before continuing.
if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) {
usbi_err(ctx, "failed to wait for timer thread to become ready - aborting");
CloseHandle(event);
return false;
}
event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (event == NULL) {
usbi_err(ctx, "could not create event: %s", windows_error_str(0));
return false;
}
CloseHandle(event);
} else {
usbi_dbg("no hires timer available on this platform");
hires_frequency = 0;
hires_ticks_to_ps = UINT64_C(0);
}
timer_thread = (HANDLE)_beginthreadex(NULL, 0, windows_clock_gettime_threaded, (void *)event,
0, (unsigned int *)&timer_thread_id);
if (timer_thread == NULL) {
usbi_err(ctx, "unable to create timer thread - aborting");
CloseHandle(event);
return false;
}
return true;
if (!SetThreadAffinityMask(timer_thread, affinity))
usbi_warn(ctx, "unable to set timer thread affinity, timer discrepancies may arise");
// Wait for timer thread to init before continuing.
if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) {
usbi_err(ctx, "failed to wait for timer thread to become ready - aborting");
CloseHandle(event);
return false;
}
CloseHandle(event);
} else {
usbi_dbg("no hires timer available on this platform");
hires_frequency = 0;
hires_ticks_to_ps = UINT64_C(0);
}
return true;
}
void windows_destroy_clock(void)
{
if (timer_thread) {
// actually the signal to quit the thread.
if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0) ||
(WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) {
usbi_dbg("could not wait for timer thread to quit");
TerminateThread(timer_thread, 1);
// shouldn't happen, but we're destroying
// all objects it might have held anyway.
}
CloseHandle(timer_thread);
timer_thread = NULL;
timer_thread_id = 0;
}
if (timer_thread) {
// actually the signal to quit the thread.
if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0)
|| (WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) {
usbi_dbg("could not wait for timer thread to quit");
TerminateThread(timer_thread, 1);
// shouldn't happen, but we're destroying
// all objects it might have held anyway.
}
CloseHandle(timer_thread);
timer_thread = NULL;
timer_thread_id = 0;
}
}
/*
* Monotonic and real time functions
*/
static unsigned __stdcall windows_clock_gettime_threaded(void* param)
static unsigned __stdcall windows_clock_gettime_threaded(void *param)
{
struct timer_request *request;
LARGE_INTEGER hires_counter;
MSG msg;
struct timer_request *request;
LARGE_INTEGER hires_counter;
MSG msg;
// The following call will create this thread's message queue
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644946.aspx
pPeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
// The following call will create this thread's message queue
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644946.aspx
pPeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
// Signal windows_init() that we're ready to service requests
if (!SetEvent((HANDLE)param)) {
usbi_dbg("SetEvent failed for timer init event: %s", windows_error_str(0));
}
param = NULL;
// Signal windows_init_clock() that we're ready to service requests
if (!SetEvent((HANDLE)param))
usbi_dbg("SetEvent failed for timer init event: %s", windows_error_str(0));
param = NULL;
// Main loop - wait for requests
while (1) {
// Main loop - wait for requests
while (1) {
if (pGetMessageA(&msg, NULL, WM_TIMER_REQUEST, WM_TIMER_EXIT) == -1) {
usbi_err(NULL, "GetMessage failed for timer thread: %s", windows_error_str(0));
return 1;
}
if (pGetMessageA(&msg, NULL, WM_TIMER_REQUEST, WM_TIMER_EXIT) == -1) {
usbi_err(NULL, "GetMessage failed for timer thread: %s", windows_error_str(0));
return 1;
}
switch (msg.message) {
case WM_TIMER_REQUEST:
// Requests to this thread are for hires always
// Microsoft says that this function always succeeds on XP and later
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904.aspx
request = (struct timer_request *)msg.lParam;
QueryPerformanceCounter(&hires_counter);
request->tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
request->tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps);
if (!SetEvent(request->event)) {
usbi_err(NULL, "SetEvent failed for timer request: %s", windows_error_str(0));
}
break;
case WM_TIMER_EXIT:
usbi_dbg("timer thread quitting");
return 0;
}
}
switch (msg.message) {
case WM_TIMER_REQUEST:
// Requests to this thread are for hires always
// Microsoft says that this function always succeeds on XP and later
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904.aspx
request = (struct timer_request *)msg.lParam;
QueryPerformanceCounter(&hires_counter);
request->tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
request->tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps);
if (!SetEvent(request->event))
usbi_err(NULL, "SetEvent failed for timer request: %s", windows_error_str(0));
break;
case WM_TIMER_EXIT:
usbi_dbg("timer thread quitting");
return 0;
}
}
}
int windows_clock_gettime(int clk_id, struct timespec *tp)
{
struct timer_request request;
FILETIME filetime;
ULARGE_INTEGER rtime;
DWORD r;
switch (clk_id) {
case USBI_CLOCK_MONOTONIC:
if (timer_thread) {
request.tp = tp;
request.event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (request.event == NULL) {
return LIBUSB_ERROR_NO_MEM;
}
struct timer_request request;
FILETIME filetime;
ULARGE_INTEGER rtime;
DWORD r;
if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) {
usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0));
CloseHandle(request.event);
return LIBUSB_ERROR_OTHER;
}
switch (clk_id) {
case USBI_CLOCK_MONOTONIC:
if (timer_thread) {
request.tp = tp;
request.event = CreateEvent(NULL, FALSE, FALSE, NULL);
if (request.event == NULL)
return LIBUSB_ERROR_NO_MEM;
do {
r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS);
if (r == WAIT_TIMEOUT) {
usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?");
}
else if (r == WAIT_FAILED) {
usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0));
}
} while (r == WAIT_TIMEOUT);
CloseHandle(request.event);
if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) {
usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0));
CloseHandle(request.event);
return LIBUSB_ERROR_OTHER;
}
if (r == WAIT_OBJECT_0) {
return LIBUSB_SUCCESS;
} else {
return LIBUSB_ERROR_OTHER;
}
}
// Fall through and return real-time if monotonic was not detected @ timer 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
// 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)
GetSystemTimeAsFileTime(&filetime);
rtime.LowPart = filetime.dwLowDateTime;
rtime.HighPart = filetime.dwHighDateTime;
rtime.QuadPart -= epoch_time;
tp->tv_sec = (long)(rtime.QuadPart / 10000000);
tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100);
return LIBUSB_SUCCESS;
default:
return LIBUSB_ERROR_INVALID_PARAM;
}
do {
r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS);
if (r == WAIT_TIMEOUT)
usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?");
else if (r == WAIT_FAILED)
usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0));
} while (r == WAIT_TIMEOUT);
CloseHandle(request.event);
if (r == WAIT_OBJECT_0)
return LIBUSB_SUCCESS;
else
return LIBUSB_ERROR_OTHER;
}
// Fall through and return real-time if monotonic was not detected @ timer 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
// 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)
GetSystemTimeAsFileTime(&filetime);
rtime.LowPart = filetime.dwLowDateTime;
rtime.HighPart = filetime.dwHighDateTime;
rtime.QuadPart -= epoch_time;
tp->tv_sec = (long)(rtime.QuadPart / 10000000);
tp->tv_nsec = (long)((rtime.QuadPart % 10000000) * 100);
return LIBUSB_SUCCESS;
default:
return LIBUSB_ERROR_INVALID_PARAM;
}
}
static void windows_transfer_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size)
{
int status, istatus;
int status, istatus;
usbi_dbg("handling I/O completion with errcode %u, size %u", io_result, io_size);
usbi_dbg("handling I/O completion with errcode %u, size %u", io_result, io_size);
switch (io_result) {
case NO_ERROR:
status = windows_copy_transfer_data(itransfer, io_size);
break;
case ERROR_GEN_FAILURE:
usbi_dbg("detected endpoint stall");
status = LIBUSB_TRANSFER_STALL;
break;
case ERROR_SEM_TIMEOUT:
usbi_dbg("detected semaphore timeout");
status = LIBUSB_TRANSFER_TIMED_OUT;
break;
case ERROR_OPERATION_ABORTED:
istatus = windows_copy_transfer_data(itransfer, io_size);
if (istatus != LIBUSB_TRANSFER_COMPLETED) {
usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus);
}
if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) {
usbi_dbg("detected timeout");
status = LIBUSB_TRANSFER_TIMED_OUT;
}
else {
usbi_dbg("detected operation aborted");
status = LIBUSB_TRANSFER_CANCELLED;
}
break;
default:
usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", io_result, windows_error_str(io_result));
status = LIBUSB_TRANSFER_ERROR;
break;
}
windows_clear_transfer_priv(itransfer); // Cancel polling
usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status);
switch (io_result) {
case NO_ERROR:
status = windows_copy_transfer_data(itransfer, io_size);
break;
case ERROR_GEN_FAILURE:
usbi_dbg("detected endpoint stall");
status = LIBUSB_TRANSFER_STALL;
break;
case ERROR_SEM_TIMEOUT:
usbi_dbg("detected semaphore timeout");
status = LIBUSB_TRANSFER_TIMED_OUT;
break;
case ERROR_OPERATION_ABORTED:
istatus = windows_copy_transfer_data(itransfer, io_size);
if (istatus != LIBUSB_TRANSFER_COMPLETED)
usbi_dbg("Failed to copy partial data in aborted operation: %d", istatus);
if (itransfer->flags & USBI_TRANSFER_TIMED_OUT) {
usbi_dbg("detected timeout");
status = LIBUSB_TRANSFER_TIMED_OUT;
}
else {
usbi_dbg("detected operation aborted");
status = LIBUSB_TRANSFER_CANCELLED;
}
break;
default:
usbi_err(ITRANSFER_CTX(itransfer), "detected I/O error %u: %s", io_result, windows_error_str(io_result));
status = LIBUSB_TRANSFER_ERROR;
break;
}
windows_clear_transfer_priv(itransfer); // Cancel polling
usbi_handle_transfer_completion(itransfer, (enum libusb_transfer_status)status);
}
void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result, uint32_t io_size)
{
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
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(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);
}
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(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);
}
}
int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready)
{
POLL_NFDS_TYPE i = 0;
bool found = false;
struct usbi_transfer *transfer;
struct winfd *pollable_fd = NULL;
DWORD io_size, io_result;
POLL_NFDS_TYPE i = 0;
bool found = false;
struct usbi_transfer *transfer;
struct winfd *pollable_fd = NULL;
DWORD io_size, io_result;
usbi_mutex_lock(&ctx->open_devs_lock);
for (i = 0; i < nfds && num_ready > 0; i++) {
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);
usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents);
if (!fds[i].revents) {
continue;
}
if (!fds[i].revents)
continue;
num_ready--;
num_ready--;
// 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);
found = false;
list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
pollable_fd = windows_get_fd(transfer);
if (pollable_fd->fd == fds[i].fd) {
found = true;
break;
}
}
usbi_mutex_unlock(&ctx->flying_transfers_lock);
// 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);
found = false;
list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
pollable_fd = windows_get_fd(transfer);
if (pollable_fd->fd == fds[i].fd) {
found = true;
break;
}
}
usbi_mutex_unlock(&ctx->flying_transfers_lock);
if (found) {
windows_get_overlapped_result(transfer, pollable_fd, &io_result, &io_size);
if (found) {
windows_get_overlapped_result(transfer, pollable_fd, &io_result, &io_size);
usbi_remove_pollfd(ctx, pollable_fd->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(transfer, io_result, io_size);
} else {
usbi_mutex_unlock(&ctx->open_devs_lock);
usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]);
return LIBUSB_ERROR_NOT_FOUND;
}
}
usbi_remove_pollfd(ctx, pollable_fd->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(transfer, io_result, io_size);
} else {
usbi_mutex_unlock(&ctx->open_devs_lock);
usbi_err(ctx, "could not find a matching transfer for fd %d", fds[i]);
return LIBUSB_ERROR_NOT_FOUND;
}
}
usbi_mutex_unlock(&ctx->open_devs_lock);
usbi_mutex_unlock(&ctx->open_devs_lock);
return LIBUSB_SUCCESS;
return LIBUSB_SUCCESS;
}
int windows_common_init(struct libusb_context *ctx)
{
static const unsigned long HTAB_SIZE = 1021;
if (!windows_init_clock(ctx))
goto error_roll_back;
if (!windows_init_clock(ctx)){
goto error_roll_back;
}
if (!htab_create(ctx, HTAB_SIZE))
goto error_roll_back;
if (!htab_create(ctx, HTAB_SIZE)) {
goto error_roll_back;
}
return LIBUSB_SUCCESS;
return LIBUSB_SUCCESS;
error_roll_back:
windows_common_exit();
return LIBUSB_ERROR_NO_MEM;
windows_common_exit();
return LIBUSB_ERROR_NO_MEM;
}
void windows_common_exit(void)
{
htab_destroy();
windows_destroy_clock();
htab_destroy();
windows_destroy_clock();
}
+2 -2
View File
@@ -42,7 +42,7 @@ typedef struct libusb_device_descriptor USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESC
int windows_common_init(struct libusb_context *ctx);
void windows_common_exit(void);
unsigned long htab_hash(char* str);
unsigned long htab_hash(const char *str);
int windows_clock_gettime(int clk_id, struct timespec *tp);
void windows_clear_transfer_priv(struct usbi_transfer *itransfer);
@@ -54,5 +54,5 @@ void windows_handle_callback(struct usbi_transfer *itransfer, uint32_t io_result
int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready);
#if defined(ENABLE_LOGGING)
char *windows_error_str(uint32_t retval);
const char *windows_error_str(DWORD retval);
#endif
+558 -607
View File
File diff suppressed because it is too large Load Diff
+97 -77
View File
@@ -23,104 +23,124 @@
#pragma once
typedef struct tag_USB_DK_DEVICE_ID
{
WCHAR DeviceID[MAX_DEVICE_ID_LEN];
WCHAR InstanceID[MAX_DEVICE_ID_LEN];
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;
static inline
void UsbDkFillIDStruct(USB_DK_DEVICE_ID *ID, PCWCHAR DeviceID, PCWCHAR InstanceID)
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);
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;
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
{
USB_DK_DEVICE_ID ID;
ULONG64 Index;
typedef struct tag_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;
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
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
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;
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_RESULT Result;
} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST;
typedef enum
{
TransferFailure = 0,
TransferSuccess,
TransferSuccessAsync
typedef enum {
TransferFailure = 0,
TransferSuccess,
TransferSuccessAsync
} TransferResult;
typedef enum
{
NoSpeed = 0,
LowSpeed,
FullSpeed,
HighSpeed,
SuperSpeed
typedef enum {
NoSpeed = 0,
LowSpeed,
FullSpeed,
HighSpeed,
SuperSpeed
} USB_DK_DEVICE_SPEED;
typedef enum
{
ControlTransferType,
BulkTransferType,
IntertuptTransferType,
IsochronousTransferType
typedef enum {
ControlTransferType,
BulkTransferType,
IntertuptTransferType,
IsochronousTransferType
} USB_DK_TRANSFER_TYPE;
typedef BOOL (__cdecl *USBDK_GET_DEVICES_LIST) (PUSB_DK_DEVICE_INFO *, PULONG);
typedef void (__cdecl *USBDK_RELEASE_DEVICES_LIST) (PUSB_DK_DEVICE_INFO);
typedef HANDLE (__cdecl *USBDK_START_REDIRECT) (PUSB_DK_DEVICE_ID);
typedef BOOL (__cdecl *USBDK_STOP_REDIRECT) (HANDLE);
typedef BOOL (__cdecl *USBDK_GET_CONFIGURATION_DESCRIPTOR) (PUSB_DK_CONFIG_DESCRIPTOR_REQUEST Request,
PUSB_CONFIGURATION_DESCRIPTOR *Descriptor,
PULONG Length);
typedef void (__cdecl *USBDK_RELEASE_CONFIGURATION_DESCRIPTOR) (PUSB_CONFIGURATION_DESCRIPTOR Descriptor);
typedef TransferResult (__cdecl *USBDK_WRITE_PIPE) (HANDLE DeviceHandle, PUSB_DK_TRANSFER_REQUEST Request, LPOVERLAPPED lpOverlapped);
typedef TransferResult (__cdecl *USBDK_READ_PIPE) (HANDLE DeviceHandle, PUSB_DK_TRANSFER_REQUEST Request, LPOVERLAPPED lpOverlapped);
typedef BOOL (__cdecl *USBDK_ABORT_PIPE) (HANDLE DeviceHandle, ULONG64 PipeAddress);
typedef BOOL (__cdecl *USBDK_RESET_PIPE) (HANDLE DeviceHandle, ULONG64 PipeAddress);
typedef BOOL (__cdecl *USBDK_SET_ALTSETTING) (HANDLE DeviceHandle, ULONG64 InterfaceIdx, ULONG64 AltSettingIdx);
typedef BOOL (__cdecl *USBDK_RESET_DEVICE) (HANDLE DeviceHandle);
typedef HANDLE (__cdecl *USBDK_GET_REDIRECTOR_SYSTEM_HANDLE) (HANDLE DeviceHandle);
typedef BOOL (__cdecl *USBDK_GET_DEVICES_LIST)(
PUSB_DK_DEVICE_INFO *DeviceInfo,
PULONG DeviceNumber
);
typedef void (__cdecl *USBDK_RELEASE_DEVICES_LIST)(
PUSB_DK_DEVICE_INFO DeviceInfo
);
typedef HANDLE (__cdecl *USBDK_START_REDIRECT)(
PUSB_DK_DEVICE_ID DeviceId
);
typedef BOOL (__cdecl *USBDK_STOP_REDIRECT)(
HANDLE DeviceHandle
);
typedef BOOL (__cdecl *USBDK_GET_CONFIGURATION_DESCRIPTOR)(
PUSB_DK_CONFIG_DESCRIPTOR_REQUEST Request,
PUSB_CONFIGURATION_DESCRIPTOR *Descriptor,
PULONG Length
);
typedef void (__cdecl *USBDK_RELEASE_CONFIGURATION_DESCRIPTOR)(
PUSB_CONFIGURATION_DESCRIPTOR Descriptor
);
typedef TransferResult (__cdecl *USBDK_WRITE_PIPE)(
HANDLE DeviceHandle,
PUSB_DK_TRANSFER_REQUEST Request,
LPOVERLAPPED lpOverlapped
);
typedef TransferResult (__cdecl *USBDK_READ_PIPE)(
HANDLE DeviceHandle,
PUSB_DK_TRANSFER_REQUEST Request,
LPOVERLAPPED lpOverlapped
);
typedef BOOL (__cdecl *USBDK_ABORT_PIPE)(
HANDLE DeviceHandle,
ULONG64 PipeAddress
);
typedef BOOL (__cdecl *USBDK_RESET_PIPE)(
HANDLE DeviceHandle,
ULONG64 PipeAddress
);
typedef BOOL (__cdecl *USBDK_SET_ALTSETTING)(
HANDLE DeviceHandle,
ULONG64 InterfaceIdx,
ULONG64 AltSettingIdx
);
typedef BOOL (__cdecl *USBDK_RESET_DEVICE)(
HANDLE DeviceHandle
);
typedef HANDLE (__cdecl *USBDK_GET_REDIRECTOR_SYSTEM_HANDLE)(
HANDLE DeviceHandle
);
+665 -607
View File
File diff suppressed because it is too large Load Diff
+252 -247
View File
@@ -37,7 +37,7 @@
// Missing from MSVC6 setupapi.h
#if !defined(SPDRP_ADDRESS)
#define SPDRP_ADDRESS 28
#define SPDRP_ADDRESS 28
#endif
#if !defined(SPDRP_INSTALL_STATE)
#define SPDRP_INSTALL_STATE 34
@@ -56,20 +56,20 @@
#define _beginthreadex(a, b, c, d, e, f) CreateThread(a, b, (LPTHREAD_START_ROUTINE)c, d, e, (LPDWORD)f)
#endif
#define MAX_CTRL_BUFFER_LENGTH 4096
#define MAX_USB_DEVICES 256
#define MAX_USB_STRING_LENGTH 128
#define MAX_HID_REPORT_SIZE 1024
#define MAX_HID_DESCRIPTOR_SIZE 256
#define MAX_GUID_STRING_LENGTH 40
#define MAX_PATH_LENGTH 128
#define MAX_KEY_LENGTH 256
#define LIST_SEPARATOR ';'
#define MAX_CTRL_BUFFER_LENGTH 4096
#define MAX_USB_DEVICES 256
#define MAX_USB_STRING_LENGTH 128
#define MAX_HID_REPORT_SIZE 1024
#define MAX_HID_DESCRIPTOR_SIZE 256
#define MAX_GUID_STRING_LENGTH 40
#define MAX_PATH_LENGTH 128
#define MAX_KEY_LENGTH 256
#define LIST_SEPARATOR ';'
// Handle code for HID interface that have been claimed ("dibs")
#define INTERFACE_CLAIMED ((HANDLE)(intptr_t)0xD1B5)
#define INTERFACE_CLAIMED ((HANDLE)(intptr_t)0xD1B5)
// Additional return code for HID operations that completed synchronously
#define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1)
#define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1)
// http://msdn.microsoft.com/en-us/library/ff545978.aspx
// http://msdn.microsoft.com/en-us/library/ff545972.aspx
@@ -91,28 +91,28 @@ const GUID GUID_DEVINTERFACE_LIBUSB0_FILTER = { 0xF9F3FF14, 0xAE21, 0x48A0, {0x8
/*
* Multiple USB API backend support
*/
#define USB_API_UNSUPPORTED 0
#define USB_API_HUB 1
#define USB_API_COMPOSITE 2
#define USB_API_WINUSBX 3
#define USB_API_HID 4
#define USB_API_MAX 5
#define USB_API_UNSUPPORTED 0
#define USB_API_HUB 1
#define USB_API_COMPOSITE 2
#define USB_API_WINUSBX 3
#define USB_API_HID 4
#define USB_API_MAX 5
// The following is used to indicate if the HID or composite extra props have already been set.
#define USB_API_SET (1<<USB_API_MAX)
#define USB_API_SET (1 << USB_API_MAX)
// Sub-APIs for WinUSB-like driver APIs (WinUSB, libusbK, libusb-win32 through the libusbK DLL)
// Must have the same values as the KUSB_DRVID enum from libusbk.h
#define SUB_API_NOTSET -1
#define SUB_API_LIBUSBK 0
#define SUB_API_LIBUSB0 1
#define SUB_API_WINUSB 2
#define SUB_API_MAX 3
#define SUB_API_NOTSET -1
#define SUB_API_LIBUSBK 0
#define SUB_API_LIBUSB0 1
#define SUB_API_WINUSB 2
#define SUB_API_MAX 3
#define WINUSBX_DRV_NAMES { "libusbK", "libusb0", "WinUSB"}
#define WINUSBX_DRV_NAMES {"libusbK", "libusb0", "WinUSB"}
struct windows_usb_api_backend {
const uint8_t id;
const char* designation;
const char *designation;
const char **driver_name_list; // Driver name, without .sys, e.g. "usbccgp"
const uint8_t nb_driver_names;
int (*init)(int sub_api, struct libusb_context *ctx);
@@ -135,9 +135,9 @@ struct windows_usb_api_backend {
extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX];
#define PRINT_UNSUPPORTED_API(fname) \
usbi_dbg("unsupported API call for '" \
#fname "' (unrecognized device driver)"); \
#define PRINT_UNSUPPORTED_API(fname) \
usbi_dbg("unsupported API call for '" \
#fname "' (unrecognized device driver)"); \
return LIBUSB_ERROR_NOT_SUPPORTED;
/*
@@ -147,39 +147,40 @@ extern const struct windows_usb_api_backend usb_api_backend[USB_API_MAX];
// TODO (v2+): move hid desc to libusb.h?
struct libusb_hid_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t bcdHID;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bClassDescriptorType;
uint8_t bCountryCode;
uint8_t bNumDescriptors;
uint8_t bClassDescriptorType;
uint16_t wClassDescriptorLength;
};
#define LIBUSB_DT_HID_SIZE 9
#define LIBUSB_DT_HID_SIZE 9
#define HID_MAX_CONFIG_DESC_SIZE (LIBUSB_DT_CONFIG_SIZE + LIBUSB_DT_INTERFACE_SIZE \
+ LIBUSB_DT_HID_SIZE + 2 * LIBUSB_DT_ENDPOINT_SIZE)
#define HID_MAX_REPORT_SIZE 1024
#define HID_IN_EP 0x81
#define HID_OUT_EP 0x02
#define LIBUSB_REQ_RECIPIENT(request_type) ((request_type) & 0x1F)
#define LIBUSB_REQ_TYPE(request_type) ((request_type) & (0x03 << 5))
#define LIBUSB_REQ_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN)
#define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type))
#define HID_MAX_REPORT_SIZE 1024
#define HID_IN_EP 0x81
#define HID_OUT_EP 0x02
#define LIBUSB_REQ_RECIPIENT(request_type) ((request_type) & 0x1F)
#define LIBUSB_REQ_TYPE(request_type) ((request_type) & (0x03 << 5))
#define LIBUSB_REQ_IN(request_type) ((request_type) & LIBUSB_ENDPOINT_IN)
#define LIBUSB_REQ_OUT(request_type) (!LIBUSB_REQ_IN(request_type))
// The following are used for HID reports IOCTLs
#define HID_CTL_CODE(id) \
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS)
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_NEITHER, FILE_ANY_ACCESS)
#define HID_BUFFER_CTL_CODE(id) \
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define HID_IN_CTL_CODE(id) \
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS)
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define HID_OUT_CTL_CODE(id) \
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
CTL_CODE (FILE_DEVICE_KEYBOARD, (id), METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104)
#define IOCTL_HID_SET_FEATURE HID_IN_CTL_CODE(100)
#define IOCTL_HID_SET_OUTPUT_REPORT HID_IN_CTL_CODE(101)
#define IOCTL_HID_GET_FEATURE HID_OUT_CTL_CODE(100)
#define IOCTL_HID_GET_INPUT_REPORT HID_OUT_CTL_CODE(104)
#define IOCTL_HID_SET_FEATURE HID_IN_CTL_CODE(100)
#define IOCTL_HID_SET_OUTPUT_REPORT HID_IN_CTL_CODE(101)
enum libusb_hid_request_type {
HID_REQ_GET_REPORT = 0x01,
@@ -201,43 +202,46 @@ struct hid_device_priv {
uint16_t pid;
uint8_t config;
uint8_t nb_interfaces;
bool uses_report_ids[3]; // input, ouptput, feature
bool uses_report_ids[3]; // input, ouptput, feature
uint16_t input_report_size;
uint16_t output_report_size;
uint16_t feature_report_size;
WCHAR string[3][MAX_USB_STRING_LENGTH];
uint8_t string_index[3]; // man, prod, ser
uint8_t string_index[3]; // man, prod, ser
};
struct windows_device_priv {
uint8_t depth; // distance to HCD
uint8_t port; // port number on the hub
uint8_t depth; // distance to HCD
uint8_t port; // port number on the hub
uint8_t active_config;
struct libusb_device *parent_dev; // access to parent is required for usermode ops
struct libusb_device *parent_dev; // access to parent is required for usermode ops
struct windows_usb_api_backend const *apib;
char *path; // device interface path
int sub_api; // for WinUSB-like APIs
char *path; // device interface path
int sub_api; // for WinUSB-like APIs
struct {
char *path; // each interface needs a device interface path,
char *path; // each interface needs a device interface path,
struct windows_usb_api_backend const *apib; // an API backend (multiple drivers support),
int sub_api;
int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS)
int8_t nb_endpoints; // and a set of endpoint addresses (USB_MAXENDPOINTS)
uint8_t *endpoint;
bool restricted_functionality; // indicates if the interface functionality is restricted
// by Windows (eg. HID keyboards or mice cannot do R/W)
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;
unsigned char **config_descriptor; // list of pointers to the cached config descriptors
unsigned char **config_descriptor; // list of pointers to the cached config descriptors
};
static inline struct windows_device_priv *_device_priv(struct libusb_device *dev) {
static inline struct windows_device_priv *_device_priv(struct libusb_device *dev)
{
return (struct windows_device_priv *)dev->os_priv;
}
static inline void windows_device_priv_init(libusb_device* dev) {
struct windows_device_priv* p = _device_priv(dev);
static inline void windows_device_priv_init(struct libusb_device *dev)
{
struct windows_device_priv *p = _device_priv(dev);
int i;
p->depth = 0;
p->port = 0;
p->parent_dev = NULL;
@@ -247,8 +251,8 @@ static inline void windows_device_priv_init(libusb_device* dev) {
p->hid = NULL;
p->active_config = 0;
p->config_descriptor = NULL;
memset(&(p->dev_descriptor), 0, sizeof(USB_DEVICE_DESCRIPTOR));
for (i=0; i<USB_MAXINTERFACES; i++) {
memset(&p->dev_descriptor, 0, sizeof(USB_DEVICE_DESCRIPTOR));
for (i = 0; i < USB_MAXINTERFACES; i++) {
p->usb_interface[i].path = NULL;
p->usb_interface[i].apib = &usb_api_backend[USB_API_UNSUPPORTED];
p->usb_interface[i].sub_api = SUB_API_NOTSET;
@@ -258,17 +262,19 @@ static inline void windows_device_priv_init(libusb_device* dev) {
}
}
static inline void windows_device_priv_release(libusb_device* dev) {
struct windows_device_priv* p = _device_priv(dev);
static inline void windows_device_priv_release(struct libusb_device *dev)
{
struct windows_device_priv *p = _device_priv(dev);
int i;
safe_free(p->path);
if ((dev->num_configurations > 0) && (p->config_descriptor != NULL)) {
for (i=0; i < dev->num_configurations; i++)
for (i = 0; i < dev->num_configurations; i++)
safe_free(p->config_descriptor[i]);
}
safe_free(p->config_descriptor);
safe_free(p->hid);
for (i=0; i<USB_MAXINTERFACES; i++) {
for (i = 0; i < USB_MAXINTERFACES; i++) {
safe_free(p->usb_interface[i].path);
safe_free(p->usb_interface[i].endpoint);
}
@@ -288,7 +294,7 @@ struct windows_device_handle_priv {
static inline struct windows_device_handle_priv *_device_handle_priv(
struct libusb_device_handle *handle)
{
return (struct windows_device_handle_priv *) handle->os_priv;
return (struct windows_device_handle_priv *)handle->os_priv;
}
// used for async polling functions
@@ -302,9 +308,9 @@ struct windows_transfer_priv {
// used to match a device driver (including filter drivers) against a supported API
struct driver_lookup {
char list[MAX_KEY_LENGTH+1];// REG_MULTI_SZ list of services (driver) names
const DWORD reg_prop; // SPDRP registry key to use to retrieve list
const char* designation; // internal designation (for debug output)
char list[MAX_KEY_LENGTH + 1]; // REG_MULTI_SZ list of services (driver) names
const DWORD reg_prop; // SPDRP registry key to use to retrieve list
const char* designation; // internal designation (for debug output)
};
/* OLE32 dependency */
@@ -336,57 +342,57 @@ typedef DEVNODE *PDEVNODE, *PDEVINST;
typedef DWORD RETURN_TYPE;
typedef RETURN_TYPE CONFIGRET;
#define CR_SUCCESS 0x00000000
#define CR_NO_SUCH_DEVNODE 0x0000000D
#define CR_SUCCESS 0x00000000
#define CR_NO_SUCH_DEVNODE 0x0000000D
#define USB_DEVICE_DESCRIPTOR_TYPE LIBUSB_DT_DEVICE
#define USB_CONFIGURATION_DESCRIPTOR_TYPE LIBUSB_DT_CONFIG
#define USB_STRING_DESCRIPTOR_TYPE LIBUSB_DT_STRING
#define USB_INTERFACE_DESCRIPTOR_TYPE LIBUSB_DT_INTERFACE
#define USB_ENDPOINT_DESCRIPTOR_TYPE LIBUSB_DT_ENDPOINT
#define USB_DEVICE_DESCRIPTOR_TYPE LIBUSB_DT_DEVICE
#define USB_CONFIGURATION_DESCRIPTOR_TYPE LIBUSB_DT_CONFIG
#define USB_STRING_DESCRIPTOR_TYPE LIBUSB_DT_STRING
#define USB_INTERFACE_DESCRIPTOR_TYPE LIBUSB_DT_INTERFACE
#define USB_ENDPOINT_DESCRIPTOR_TYPE LIBUSB_DT_ENDPOINT
#define USB_REQUEST_GET_STATUS LIBUSB_REQUEST_GET_STATUS
#define USB_REQUEST_CLEAR_FEATURE LIBUSB_REQUEST_CLEAR_FEATURE
#define USB_REQUEST_SET_FEATURE LIBUSB_REQUEST_SET_FEATURE
#define USB_REQUEST_SET_ADDRESS LIBUSB_REQUEST_SET_ADDRESS
#define USB_REQUEST_GET_DESCRIPTOR LIBUSB_REQUEST_GET_DESCRIPTOR
#define USB_REQUEST_SET_DESCRIPTOR LIBUSB_REQUEST_SET_DESCRIPTOR
#define USB_REQUEST_GET_CONFIGURATION LIBUSB_REQUEST_GET_CONFIGURATION
#define USB_REQUEST_SET_CONFIGURATION LIBUSB_REQUEST_SET_CONFIGURATION
#define USB_REQUEST_GET_INTERFACE LIBUSB_REQUEST_GET_INTERFACE
#define USB_REQUEST_SET_INTERFACE LIBUSB_REQUEST_SET_INTERFACE
#define USB_REQUEST_SYNC_FRAME LIBUSB_REQUEST_SYNCH_FRAME
#define USB_REQUEST_GET_STATUS LIBUSB_REQUEST_GET_STATUS
#define USB_REQUEST_CLEAR_FEATURE LIBUSB_REQUEST_CLEAR_FEATURE
#define USB_REQUEST_SET_FEATURE LIBUSB_REQUEST_SET_FEATURE
#define USB_REQUEST_SET_ADDRESS LIBUSB_REQUEST_SET_ADDRESS
#define USB_REQUEST_GET_DESCRIPTOR LIBUSB_REQUEST_GET_DESCRIPTOR
#define USB_REQUEST_SET_DESCRIPTOR LIBUSB_REQUEST_SET_DESCRIPTOR
#define USB_REQUEST_GET_CONFIGURATION LIBUSB_REQUEST_GET_CONFIGURATION
#define USB_REQUEST_SET_CONFIGURATION LIBUSB_REQUEST_SET_CONFIGURATION
#define USB_REQUEST_GET_INTERFACE LIBUSB_REQUEST_GET_INTERFACE
#define USB_REQUEST_SET_INTERFACE LIBUSB_REQUEST_SET_INTERFACE
#define USB_REQUEST_SYNC_FRAME LIBUSB_REQUEST_SYNCH_FRAME
#define USB_GET_NODE_INFORMATION 258
#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260
#define USB_GET_NODE_CONNECTION_NAME 261
#define USB_GET_HUB_CAPABILITIES 271
#define USB_GET_NODE_INFORMATION 258
#define USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION 260
#define USB_GET_NODE_CONNECTION_NAME 261
#define USB_GET_HUB_CAPABILITIES 271
#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX)
#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274
#define USB_GET_NODE_CONNECTION_INFORMATION_EX 274
#endif
#if !defined(USB_GET_HUB_CAPABILITIES_EX)
#define USB_GET_HUB_CAPABILITIES_EX 276
#define USB_GET_HUB_CAPABILITIES_EX 276
#endif
#if !defined(USB_GET_NODE_CONNECTION_INFORMATION_EX_V2)
#define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279
#define USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 279
#endif
#ifndef METHOD_BUFFERED
#define METHOD_BUFFERED 0
#define METHOD_BUFFERED 0
#endif
#ifndef FILE_ANY_ACCESS
#define FILE_ANY_ACCESS 0x00000000
#define FILE_ANY_ACCESS 0x00000000
#endif
#ifndef FILE_DEVICE_UNKNOWN
#define FILE_DEVICE_UNKNOWN 0x00000022
#define FILE_DEVICE_UNKNOWN 0x00000022
#endif
#ifndef FILE_DEVICE_USB
#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN
#define FILE_DEVICE_USB FILE_DEVICE_UNKNOWN
#endif
#ifndef CTL_CODE
#define CTL_CODE(DeviceType, Function, Method, Access)( \
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
#define CTL_CODE(DeviceType, Function, Method, Access) \
(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
#endif
typedef enum USB_CONNECTION_STATUS {
@@ -413,45 +419,45 @@ DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Sibling, (PDEVINST, DEVINST, ULONG));
DLL_DECLARE(WINAPI, CONFIGRET, CM_Get_Device_IDA, (DEVINST, PCHAR, ULONG, ULONG));
#define IOCTL_USB_GET_HUB_CAPABILITIES_EX \
CTL_CODE( FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES_EX, METHOD_BUFFERED, FILE_ANY_ACCESS)
CTL_CODE( FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES_EX, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_USB_GET_HUB_CAPABILITIES \
CTL_CODE(FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES, METHOD_BUFFERED, FILE_ANY_ACCESS)
CTL_CODE(FILE_DEVICE_USB, USB_GET_HUB_CAPABILITIES, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION \
CTL_CODE(FILE_DEVICE_USB, USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, METHOD_BUFFERED, FILE_ANY_ACCESS)
CTL_CODE(FILE_DEVICE_USB, USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_USB_GET_ROOT_HUB_NAME \
CTL_CODE(FILE_DEVICE_USB, HCD_GET_ROOT_HUB_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS)
CTL_CODE(FILE_DEVICE_USB, HCD_GET_ROOT_HUB_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_USB_GET_NODE_INFORMATION \
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS)
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX \
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX, METHOD_BUFFERED, FILE_ANY_ACCESS)
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2 \
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, METHOD_BUFFERED, FILE_ANY_ACCESS)
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_INFORMATION_EX_V2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES \
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_ATTRIBUTES, METHOD_BUFFERED, FILE_ANY_ACCESS)
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_ATTRIBUTES, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_USB_GET_NODE_CONNECTION_NAME \
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS)
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_NAME, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Most of the structures below need to be packed
#pragma pack(push, 1)
typedef struct USB_INTERFACE_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bInterfaceNumber;
UCHAR bAlternateSetting;
UCHAR bNumEndpoints;
UCHAR bInterfaceClass;
UCHAR bInterfaceSubClass;
UCHAR bInterfaceProtocol;
UCHAR iInterface;
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bInterfaceNumber;
UCHAR bAlternateSetting;
UCHAR bNumEndpoints;
UCHAR bInterfaceClass;
UCHAR bInterfaceSubClass;
UCHAR bInterfaceProtocol;
UCHAR iInterface;
} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;
typedef struct USB_CONFIGURATION_DESCRIPTOR_SHORT {
@@ -469,39 +475,39 @@ typedef struct USB_CONFIGURATION_DESCRIPTOR_SHORT {
} USB_CONFIGURATION_DESCRIPTOR_SHORT;
typedef struct USB_ENDPOINT_DESCRIPTOR {
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bEndpointAddress;
UCHAR bmAttributes;
USHORT wMaxPacketSize;
UCHAR bInterval;
UCHAR bLength;
UCHAR bDescriptorType;
UCHAR bEndpointAddress;
UCHAR bmAttributes;
USHORT wMaxPacketSize;
UCHAR bInterval;
} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR;
typedef struct USB_DESCRIPTOR_REQUEST {
ULONG ConnectionIndex;
ULONG ConnectionIndex;
struct {
UCHAR bmRequest;
UCHAR bRequest;
USHORT wValue;
USHORT wIndex;
USHORT wLength;
UCHAR bmRequest;
UCHAR bRequest;
USHORT wValue;
USHORT wIndex;
USHORT wLength;
} SetupPacket;
// UCHAR Data[0];
// UCHAR Data[0];
} USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST;
typedef struct USB_HUB_DESCRIPTOR {
UCHAR bDescriptorLength;
UCHAR bDescriptorType;
UCHAR bNumberOfPorts;
USHORT wHubCharacteristics;
UCHAR bPowerOnToPowerGood;
UCHAR bHubControlCurrent;
UCHAR bRemoveAndPowerMask[64];
UCHAR bDescriptorLength;
UCHAR bDescriptorType;
UCHAR bNumberOfPorts;
USHORT wHubCharacteristics;
UCHAR bPowerOnToPowerGood;
UCHAR bHubControlCurrent;
UCHAR bRemoveAndPowerMask[64];
} USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR;
typedef struct USB_ROOT_HUB_NAME {
ULONG ActualLength;
WCHAR RootHubName[1];
ULONG ActualLength;
WCHAR RootHubName[1];
} USB_ROOT_HUB_NAME, *PUSB_ROOT_HUB_NAME;
typedef struct USB_ROOT_HUB_NAME_FIXED {
@@ -510,9 +516,9 @@ typedef struct USB_ROOT_HUB_NAME_FIXED {
} USB_ROOT_HUB_NAME_FIXED;
typedef struct USB_NODE_CONNECTION_NAME {
ULONG ConnectionIndex;
ULONG ActualLength;
WCHAR NodeName[1];
ULONG ConnectionIndex;
ULONG ActualLength;
WCHAR NodeName[1];
} USB_NODE_CONNECTION_NAME, *PUSB_NODE_CONNECTION_NAME;
typedef struct USB_NODE_CONNECTION_NAME_FIXED {
@@ -529,41 +535,41 @@ typedef struct USB_HUB_NAME_FIXED {
} USB_HUB_NAME_FIXED;
typedef struct USB_HUB_INFORMATION {
USB_HUB_DESCRIPTOR HubDescriptor;
BOOLEAN HubIsBusPowered;
USB_HUB_DESCRIPTOR HubDescriptor;
BOOLEAN HubIsBusPowered;
} USB_HUB_INFORMATION, *PUSB_HUB_INFORMATION;
typedef struct USB_MI_PARENT_INFORMATION {
ULONG NumberOfInterfaces;
ULONG NumberOfInterfaces;
} USB_MI_PARENT_INFORMATION, *PUSB_MI_PARENT_INFORMATION;
typedef struct USB_NODE_INFORMATION {
USB_HUB_NODE NodeType;
USB_HUB_NODE NodeType;
union {
USB_HUB_INFORMATION HubInformation;
USB_MI_PARENT_INFORMATION MiParentInformation;
USB_HUB_INFORMATION HubInformation;
USB_MI_PARENT_INFORMATION MiParentInformation;
} u;
} USB_NODE_INFORMATION, *PUSB_NODE_INFORMATION;
typedef struct USB_PIPE_INFO {
USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
ULONG ScheduleOffset;
USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
ULONG ScheduleOffset;
} USB_PIPE_INFO, *PUSB_PIPE_INFO;
typedef struct USB_NODE_CONNECTION_INFORMATION_EX {
ULONG ConnectionIndex;
USB_DEVICE_DESCRIPTOR DeviceDescriptor;
UCHAR CurrentConfigurationValue;
UCHAR Speed;
BOOLEAN DeviceIsHub;
USHORT DeviceAddress;
ULONG NumberOfOpenPipes;
USB_CONNECTION_STATUS ConnectionStatus;
// USB_PIPE_INFO PipeList[0];
ULONG ConnectionIndex;
USB_DEVICE_DESCRIPTOR DeviceDescriptor;
UCHAR CurrentConfigurationValue;
UCHAR Speed;
BOOLEAN DeviceIsHub;
USHORT DeviceAddress;
ULONG NumberOfOpenPipes;
USB_CONNECTION_STATUS ConnectionStatus;
// USB_PIPE_INFO PipeList[0];
} USB_NODE_CONNECTION_INFORMATION_EX, *PUSB_NODE_CONNECTION_INFORMATION_EX;
typedef union _USB_PROTOCOLS {
ULONG ul;
ULONG ul;
struct {
ULONG Usb110:1;
ULONG Usb200:1;
@@ -599,7 +605,7 @@ typedef struct USB_HUB_CAP_FLAGS {
} USB_HUB_CAP_FLAGS, *PUSB_HUB_CAP_FLAGS;
typedef struct USB_HUB_CAPABILITIES {
ULONG HubIs2xCapable : 1;
ULONG HubIs2xCapable:1;
} USB_HUB_CAPABILITIES, *PUSB_HUB_CAPABILITIES;
typedef struct USB_HUB_CAPABILITIES_EX {
@@ -610,20 +616,20 @@ typedef struct USB_HUB_CAPABILITIES_EX {
/* winusb.dll interface */
#define SHORT_PACKET_TERMINATE 0x01
#define AUTO_CLEAR_STALL 0x02
#define PIPE_TRANSFER_TIMEOUT 0x03
#define IGNORE_SHORT_PACKETS 0x04
#define ALLOW_PARTIAL_READS 0x05
#define AUTO_FLUSH 0x06
#define RAW_IO 0x07
#define MAXIMUM_TRANSFER_SIZE 0x08
#define AUTO_SUSPEND 0x81
#define SUSPEND_DELAY 0x83
#define DEVICE_SPEED 0x01
#define LowSpeed 0x01
#define FullSpeed 0x02
#define HighSpeed 0x03
#define SHORT_PACKET_TERMINATE 0x01
#define AUTO_CLEAR_STALL 0x02
#define PIPE_TRANSFER_TIMEOUT 0x03
#define IGNORE_SHORT_PACKETS 0x04
#define ALLOW_PARTIAL_READS 0x05
#define AUTO_FLUSH 0x06
#define RAW_IO 0x07
#define MAXIMUM_TRANSFER_SIZE 0x08
#define AUTO_SUSPEND 0x81
#define SUSPEND_DELAY 0x83
#define DEVICE_SPEED 0x01
#define LowSpeed 0x01
#define FullSpeed 0x02
#define HighSpeed 0x03
typedef enum USBD_PIPE_TYPE {
UsbdPipeTypeControl,
@@ -633,19 +639,19 @@ typedef enum USBD_PIPE_TYPE {
} USBD_PIPE_TYPE;
typedef struct {
USBD_PIPE_TYPE PipeType;
UCHAR PipeId;
USHORT MaximumPacketSize;
UCHAR Interval;
USBD_PIPE_TYPE PipeType;
UCHAR PipeId;
USHORT MaximumPacketSize;
UCHAR Interval;
} WINUSB_PIPE_INFORMATION, *PWINUSB_PIPE_INFORMATION;
#pragma pack(1)
typedef struct {
UCHAR request_type;
UCHAR request;
USHORT value;
USHORT index;
USHORT length;
UCHAR request_type;
UCHAR request;
USHORT value;
USHORT index;
USHORT length;
} WINUSB_SETUP_PACKET, *PWINUSB_SETUP_PACKET;
#pragma pack()
@@ -770,8 +776,7 @@ typedef BOOL (WINAPI *WinUsb_ResetDevice_t)(
);
/* /!\ These must match the ones from the official libusbk.h */
typedef enum _KUSB_FNID
{
typedef enum _KUSB_FNID {
KUSB_FNID_Init,
KUSB_FNID_Free,
KUSB_FNID_ClaimInterface,
@@ -818,7 +823,7 @@ typedef struct _KLIB_VERSION {
typedef KLIB_VERSION* PKLIB_VERSION;
typedef BOOL (WINAPI *LibK_GetProcAddress_t)(
PVOID* ProcAddress,
PVOID *ProcAddress,
ULONG DriverID,
ULONG FunctionID
);
@@ -854,8 +859,8 @@ struct winusb_interface {
/* hid.dll interface */
#define HIDP_STATUS_SUCCESS 0x110000
typedef void* PHIDP_PREPARSED_DATA;
#define HIDP_STATUS_SUCCESS 0x110000
typedef void * PHIDP_PREPARSED_DATA;
#pragma pack(1)
typedef struct {
@@ -868,64 +873,64 @@ typedef struct {
typedef USHORT USAGE;
typedef struct {
USAGE Usage;
USAGE UsagePage;
USHORT InputReportByteLength;
USHORT OutputReportByteLength;
USHORT FeatureReportByteLength;
USHORT Reserved[17];
USHORT NumberLinkCollectionNodes;
USHORT NumberInputButtonCaps;
USHORT NumberInputValueCaps;
USHORT NumberInputDataIndices;
USHORT NumberOutputButtonCaps;
USHORT NumberOutputValueCaps;
USHORT NumberOutputDataIndices;
USHORT NumberFeatureButtonCaps;
USHORT NumberFeatureValueCaps;
USHORT NumberFeatureDataIndices;
USAGE Usage;
USAGE UsagePage;
USHORT InputReportByteLength;
USHORT OutputReportByteLength;
USHORT FeatureReportByteLength;
USHORT Reserved[17];
USHORT NumberLinkCollectionNodes;
USHORT NumberInputButtonCaps;
USHORT NumberInputValueCaps;
USHORT NumberInputDataIndices;
USHORT NumberOutputButtonCaps;
USHORT NumberOutputValueCaps;
USHORT NumberOutputDataIndices;
USHORT NumberFeatureButtonCaps;
USHORT NumberFeatureValueCaps;
USHORT NumberFeatureDataIndices;
} HIDP_CAPS, *PHIDP_CAPS;
typedef enum _HIDP_REPORT_TYPE {
HidP_Input,
HidP_Output,
HidP_Feature
HidP_Input,
HidP_Output,
HidP_Feature
} HIDP_REPORT_TYPE;
typedef struct _HIDP_VALUE_CAPS {
USAGE UsagePage;
UCHAR ReportID;
BOOLEAN IsAlias;
USHORT BitField;
USHORT LinkCollection;
USAGE LinkUsage;
USAGE LinkUsagePage;
BOOLEAN IsRange;
BOOLEAN IsStringRange;
BOOLEAN IsDesignatorRange;
BOOLEAN IsAbsolute;
BOOLEAN HasNull;
UCHAR Reserved;
USHORT BitSize;
USHORT ReportCount;
USHORT Reserved2[5];
ULONG UnitsExp;
ULONG Units;
LONG LogicalMin, LogicalMax;
LONG PhysicalMin, PhysicalMax;
USAGE UsagePage;
UCHAR ReportID;
BOOLEAN IsAlias;
USHORT BitField;
USHORT LinkCollection;
USAGE LinkUsage;
USAGE LinkUsagePage;
BOOLEAN IsRange;
BOOLEAN IsStringRange;
BOOLEAN IsDesignatorRange;
BOOLEAN IsAbsolute;
BOOLEAN HasNull;
UCHAR Reserved;
USHORT BitSize;
USHORT ReportCount;
USHORT Reserved2[5];
ULONG UnitsExp;
ULONG Units;
LONG LogicalMin, LogicalMax;
LONG PhysicalMin, PhysicalMax;
union {
struct {
USAGE UsageMin, UsageMax;
USHORT StringMin, StringMax;
USHORT DesignatorMin, DesignatorMax;
USHORT DataIndexMin, DataIndexMax;
} Range;
struct {
USAGE Usage, Reserved1;
USHORT StringIndex, Reserved2;
USHORT DesignatorIndex, Reserved3;
USHORT DataIndex, Reserved4;
} NotRange;
struct {
USAGE UsageMin, UsageMax;
USHORT StringMin, StringMax;
USHORT DesignatorMin, DesignatorMax;
USHORT DataIndexMin, DataIndexMax;
} Range;
struct {
USAGE Usage, Reserved1;
USHORT StringIndex, Reserved2;
USHORT DesignatorIndex, Reserved3;
USHORT DataIndex, Reserved4;
} NotRange;
} u;
} HIDP_VALUE_CAPS, *PHIDP_VALUE_CAPS;
+1 -1
View File
@@ -1 +1 @@
#define LIBUSB_NANO 11032
#define LIBUSB_NANO 11033