libusb 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.travis.yml +1 -0
- data/History.md +8 -0
- data/README.md +5 -15
- data/Rakefile +8 -1
- data/ext/extconf.rb +49 -12
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/AUTHORS +12 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/COPYING +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/ChangeLog +18 -2
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/INSTALL +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Makefile.am +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Makefile.in +31 -18
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/NEWS +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/PORTING +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/README +5 -3
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/TODO +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/common.xcconfig +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/config.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/debug.xcconfig +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/libusb.xcconfig +0 -0
- data/ext/libusb-1.0.20/Xcode/libusb.xcodeproj/project.pbxproj +865 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/libusb_debug.xcconfig +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/libusb_release.xcconfig +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/Xcode/release.xcconfig +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/aclocal.m4 +35 -32
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/README +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/config.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/Android.mk +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/Application.mk +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/examples.mk +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/libusb.mk +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/android/jni/tests.mk +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/compile +1 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/config.guess +13 -160
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/config.h.in +6 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/config.sub +26 -12
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/configure +244 -20
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/configure.ac +27 -4
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/depcomp +1 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/doc/Makefile.am +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/doc/Makefile.in +19 -6
- data/ext/libusb-1.0.20/doc/doxygen.cfg.in +2334 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/Makefile.am +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/Makefile.in +19 -6
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/dpfp.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/dpfp_threaded.c +15 -10
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/ezusb.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/ezusb.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/fxload.c +28 -7
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/getopt/getopt.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/getopt/getopt.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/getopt/getopt1.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/hotplugtest.c +21 -3
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/listdevs.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/sam3u_benchmark.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/examples/xusb.c +2 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/install-sh +170 -196
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb-1.0.pc.in +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/Makefile.am +15 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/Makefile.in +192 -53
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/core.c +218 -100
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/descriptor.c +3 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/hotplug.c +26 -9
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/hotplug.h +8 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/io.c +432 -290
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/libusb-1.0.def +2 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/libusb-1.0.rc +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/libusb.h +11 -10
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/libusbi.h +106 -29
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/darwin_usb.c +27 -67
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/darwin_usb.h +3 -7
- data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.am +5 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/Makefile.in +810 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/aclocal.m4 +1193 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/compile +347 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/config.guess +1421 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/config.sub +1807 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/configure +17579 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/configure.ac +8 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/depcomp +791 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_pollfs.cpp +378 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb.h +112 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_backend.cpp +550 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.cpp +255 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/haiku_usb_raw.h +180 -0
- data/ext/libusb-1.0.20/libusb/os/haiku/install-sh +501 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/ltmain.sh +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/libtool.m4 +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/ltoptions.m4 +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/ltsugar.m4 +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/ltversion.m4 +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/m4/lt~obsolete.m4 +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20/libusb/os/haiku}/missing +1 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/linux_netlink.c +4 -4
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/linux_udev.c +1 -2
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/linux_usbfs.c +46 -49
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/linux_usbfs.h +1 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/netbsd_usb.c +9 -73
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/openbsd_usb.c +9 -73
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/poll_posix.c +2 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/poll_posix.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/poll_windows.c +3 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/poll_windows.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/threads_posix.c +3 -3
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/threads_posix.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/threads_windows.c +3 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/threads_windows.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/wince_usb.c +87 -250
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/wince_usb.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/windows_common.h +1 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/windows_usb.c +267 -181
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/os/windows_usb.h +22 -7
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/strerror.c +5 -2
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/sync.c +2 -1
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/libusb/version.h +1 -1
- data/ext/libusb-1.0.20/libusb/version_nano.h +1 -0
- data/ext/libusb-1.0.20/ltmain.sh +9655 -0
- data/ext/libusb-1.0.20/m4/libtool.m4 +7992 -0
- data/ext/libusb-1.0.20/m4/ltoptions.m4 +384 -0
- data/ext/libusb-1.0.20/m4/ltsugar.m4 +123 -0
- data/ext/libusb-1.0.20/m4/ltversion.m4 +23 -0
- data/ext/libusb-1.0.20/m4/lt~obsolete.m4 +98 -0
- data/ext/libusb-1.0.20/missing +215 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/Makefile.am +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/Makefile.in +19 -6
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/libusb_testlib.h +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/stress.c +0 -0
- data/ext/{libusb-1.0.19 → libusb-1.0.20}/tests/testlib.c +0 -0
- data/lib/libusb.rb +1 -0
- data/lib/libusb/call.rb +1 -0
- data/lib/libusb/context.rb +5 -2
- data/lib/libusb/stdio.rb +25 -0
- data/lib/libusb/version_gem.rb +1 -1
- data/libusb.gemspec +2 -1
- metadata +152 -115
- metadata.gz.sig +0 -0
- data/ext/libusb-1.0.19/Xcode/libusb.xcodeproj/project.pbxproj +0 -1
- data/ext/libusb-1.0.19/doc/doxygen.cfg.in +0 -1288
- data/ext/libusb-1.0.19/libusb/version_nano.h +0 -1
File without changes
|
@@ -39,7 +39,7 @@
|
|
39
39
|
|
40
40
|
#define safe_free(p) do {if (p != NULL) {free((void*)p); p = NULL;}} while(0)
|
41
41
|
#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
|
42
|
-
#define safe_min(a, b)
|
42
|
+
#define safe_min(a, b) MIN((size_t)(a), (size_t)(b))
|
43
43
|
#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
|
44
44
|
((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
|
45
45
|
#define safe_strcpy(dst, dst_max, src) safe_strcp(dst, dst_max, src, safe_strlen(src)+1)
|
@@ -23,6 +23,7 @@
|
|
23
23
|
*/
|
24
24
|
|
25
25
|
#include <config.h>
|
26
|
+
|
26
27
|
#include <windows.h>
|
27
28
|
#include <setupapi.h>
|
28
29
|
#include <ctype.h>
|
@@ -106,13 +107,8 @@ static char windows_version_str[128] = "Windows Undefined";
|
|
106
107
|
static int concurrent_usage = -1;
|
107
108
|
usbi_mutex_t autoclaim_lock;
|
108
109
|
// Timer thread
|
109
|
-
// NB: index 0 is for monotonic and 1 is for the thread exit event
|
110
110
|
HANDLE timer_thread = NULL;
|
111
|
-
|
112
|
-
struct timespec timer_tp;
|
113
|
-
volatile LONG request_count[2] = {0, 1}; // last one must be > 0
|
114
|
-
HANDLE timer_request[2] = { NULL, NULL };
|
115
|
-
HANDLE timer_response = NULL;
|
111
|
+
DWORD timer_thread_id = 0;
|
116
112
|
// API globals
|
117
113
|
#define CHECK_WINUSBX_AVAILABLE(sub_api) do { if (sub_api == SUB_API_NOTSET) sub_api = priv->sub_api; \
|
118
114
|
if (!WinUSBX[sub_api].initialized) return LIBUSB_ERROR_ACCESS; } while(0)
|
@@ -257,6 +253,9 @@ static int init_dlls(void)
|
|
257
253
|
DLL_LOAD_PREFIXED(SetupAPI.dll, p, SetupDiOpenDeviceInterfaceRegKey, TRUE);
|
258
254
|
DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegQueryValueExW, TRUE);
|
259
255
|
DLL_LOAD_PREFIXED(AdvAPI32.dll, p, RegCloseKey, TRUE);
|
256
|
+
DLL_LOAD_PREFIXED(User32.dll, p, GetMessageA, TRUE);
|
257
|
+
DLL_LOAD_PREFIXED(User32.dll, p, PeekMessageA, TRUE);
|
258
|
+
DLL_LOAD_PREFIXED(User32.dll, p, PostThreadMessageA, TRUE);
|
260
259
|
return LIBUSB_SUCCESS;
|
261
260
|
}
|
262
261
|
|
@@ -661,6 +660,32 @@ static unsigned long get_ancestor_session_id(DWORD devinst, unsigned level)
|
|
661
660
|
return session_id;
|
662
661
|
}
|
663
662
|
|
663
|
+
/*
|
664
|
+
* Determine which interface the given endpoint address belongs to
|
665
|
+
*/
|
666
|
+
static int get_interface_by_endpoint(struct libusb_config_descriptor *conf_desc, uint8_t ep)
|
667
|
+
{
|
668
|
+
const struct libusb_interface *intf;
|
669
|
+
const struct libusb_interface_descriptor *intf_desc;
|
670
|
+
int i, j, k;
|
671
|
+
|
672
|
+
for (i = 0; i < conf_desc->bNumInterfaces; i++) {
|
673
|
+
intf = &conf_desc->interface[i];
|
674
|
+
for (j = 0; j < intf->num_altsetting; j++) {
|
675
|
+
intf_desc = &intf->altsetting[j];
|
676
|
+
for (k = 0; k < intf_desc->bNumEndpoints; k++) {
|
677
|
+
if (intf_desc->endpoint[k].bEndpointAddress == ep) {
|
678
|
+
usbi_dbg("found endpoint %02X on interface %d", intf_desc->bInterfaceNumber);
|
679
|
+
return intf_desc->bInterfaceNumber;
|
680
|
+
}
|
681
|
+
}
|
682
|
+
}
|
683
|
+
}
|
684
|
+
|
685
|
+
usbi_dbg("endpoint %02X not found on any interface", ep);
|
686
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
687
|
+
}
|
688
|
+
|
664
689
|
/*
|
665
690
|
* Populate the endpoints addresses of the device_priv interface helper structs
|
666
691
|
*/
|
@@ -672,7 +697,7 @@ static int windows_assign_endpoints(struct libusb_device_handle *dev_handle, int
|
|
672
697
|
const struct libusb_interface_descriptor *if_desc;
|
673
698
|
struct libusb_context *ctx = DEVICE_CTX(dev_handle->dev);
|
674
699
|
|
675
|
-
r = libusb_get_config_descriptor(dev_handle->dev,
|
700
|
+
r = libusb_get_config_descriptor(dev_handle->dev, (uint8_t)(priv->active_config-1), &conf_desc);
|
676
701
|
if (r != LIBUSB_SUCCESS) {
|
677
702
|
usbi_warn(ctx, "could not read config descriptor: error %d", r);
|
678
703
|
return r;
|
@@ -889,13 +914,13 @@ static void get_windows_version(void)
|
|
889
914
|
break;
|
890
915
|
case 0x63: w = (ws?"8.1":"2012_R2");
|
891
916
|
break;
|
892
|
-
case 0x64: w = (ws?"
|
917
|
+
case 0x64: w = (ws?"10":"2015");
|
893
918
|
break;
|
894
919
|
default:
|
895
920
|
if (windows_version < 0x50)
|
896
921
|
windows_version = WINDOWS_UNSUPPORTED;
|
897
922
|
else
|
898
|
-
w = "
|
923
|
+
w = "11 or later";
|
899
924
|
break;
|
900
925
|
}
|
901
926
|
}
|
@@ -927,7 +952,10 @@ static void get_windows_version(void)
|
|
927
952
|
static int windows_init(struct libusb_context *ctx)
|
928
953
|
{
|
929
954
|
int i, r = LIBUSB_ERROR_OTHER;
|
955
|
+
DWORD_PTR affinity, dummy;
|
956
|
+
HANDLE event = NULL;
|
930
957
|
HANDLE semaphore;
|
958
|
+
LARGE_INTEGER li_frequency;
|
931
959
|
char sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID)
|
932
960
|
|
933
961
|
sprintf(sem_name, "libusb_init%08X", (unsigned int)GetCurrentProcessId()&0xFFFFFFFF);
|
@@ -965,7 +993,7 @@ static int windows_init(struct libusb_context *ctx)
|
|
965
993
|
// Load DLL imports
|
966
994
|
if (init_dlls() != LIBUSB_SUCCESS) {
|
967
995
|
usbi_err(ctx, "could not resolve DLL functions");
|
968
|
-
|
996
|
+
goto init_exit;
|
969
997
|
}
|
970
998
|
|
971
999
|
// Initialize the low level APIs (we don't care about errors at this stage)
|
@@ -973,38 +1001,53 @@ static int windows_init(struct libusb_context *ctx)
|
|
973
1001
|
usb_api_backend[i].init(SUB_API_NOTSET, ctx);
|
974
1002
|
}
|
975
1003
|
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
1004
|
+
if (QueryPerformanceFrequency(&li_frequency)) {
|
1005
|
+
// The hires frequency can go as high as 4 GHz, so we'll use a conversion
|
1006
|
+
// to picoseconds to compute the tv_nsecs part in clock_gettime
|
1007
|
+
hires_frequency = li_frequency.QuadPart;
|
1008
|
+
hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
|
1009
|
+
usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
|
1010
|
+
|
1011
|
+
// Because QueryPerformanceCounter might report different values when
|
1012
|
+
// running on different cores, we create a separate thread for the timer
|
1013
|
+
// calls, which we glue to the first available core always to prevent timing discrepancies.
|
1014
|
+
if (!GetProcessAffinityMask(GetCurrentProcess(), &affinity, &dummy) || (affinity == 0)) {
|
1015
|
+
usbi_err(ctx, "could not get process affinity: %s", windows_error_str(0));
|
984
1016
|
goto init_exit;
|
985
1017
|
}
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
goto init_exit;
|
991
|
-
}
|
992
|
-
timer_mutex = CreateMutex(NULL, FALSE, NULL);
|
993
|
-
if (timer_mutex == NULL) {
|
994
|
-
usbi_err(ctx, "could not create timer mutex - aborting");
|
995
|
-
goto init_exit;
|
996
|
-
}
|
997
|
-
timer_thread = (HANDLE)_beginthreadex(NULL, 0, windows_clock_gettime_threaded, NULL, 0, NULL);
|
998
|
-
if (timer_thread == NULL) {
|
999
|
-
usbi_err(ctx, "Unable to create timer thread - aborting");
|
1000
|
-
goto init_exit;
|
1001
|
-
}
|
1002
|
-
SetThreadAffinityMask(timer_thread, 0);
|
1018
|
+
// The process affinity mask is a bitmask where each set bit represents a core on
|
1019
|
+
// which this process is allowed to run, so we find the first set bit
|
1020
|
+
for (i = 0; !(affinity & (DWORD_PTR)(1 << i)); i++);
|
1021
|
+
affinity = (DWORD_PTR)(1 << i);
|
1003
1022
|
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1023
|
+
usbi_dbg("timer thread will run on core #%d", i);
|
1024
|
+
|
1025
|
+
r = LIBUSB_ERROR_NO_MEM;
|
1026
|
+
event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
1027
|
+
if (event == NULL) {
|
1028
|
+
usbi_err(ctx, "could not create event: %s", windows_error_str(0));
|
1029
|
+
goto init_exit;
|
1030
|
+
}
|
1031
|
+
timer_thread = (HANDLE)_beginthreadex(NULL, 0, windows_clock_gettime_threaded, (void *)event,
|
1032
|
+
0, (unsigned int *)&timer_thread_id);
|
1033
|
+
if (timer_thread == NULL) {
|
1034
|
+
usbi_err(ctx, "unable to create timer thread - aborting");
|
1035
|
+
goto init_exit;
|
1036
|
+
}
|
1037
|
+
if (!SetThreadAffinityMask(timer_thread, affinity)) {
|
1038
|
+
usbi_warn(ctx, "unable to set timer thread affinity, timer discrepancies may arise");
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
// Wait for timer thread to init before continuing.
|
1042
|
+
if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) {
|
1043
|
+
usbi_err(ctx, "failed to wait for timer thread to become ready - aborting");
|
1044
|
+
goto init_exit;
|
1045
|
+
}
|
1046
|
+
}
|
1047
|
+
else {
|
1048
|
+
usbi_dbg("no hires timer available on this platform");
|
1049
|
+
hires_frequency = 0;
|
1050
|
+
hires_ticks_to_ps = UINT64_C(0);
|
1008
1051
|
}
|
1009
1052
|
|
1010
1053
|
// Create a hash table to store session ids. Second parameter is better if prime
|
@@ -1016,35 +1059,27 @@ static int windows_init(struct libusb_context *ctx)
|
|
1016
1059
|
init_exit: // Holds semaphore here.
|
1017
1060
|
if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed?
|
1018
1061
|
if (timer_thread) {
|
1019
|
-
|
1020
|
-
if (
|
1062
|
+
// actually the signal to quit the thread.
|
1063
|
+
if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0) ||
|
1064
|
+
(WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) {
|
1021
1065
|
usbi_warn(ctx, "could not wait for timer thread to quit");
|
1022
|
-
TerminateThread(timer_thread, 1);
|
1023
|
-
|
1066
|
+
TerminateThread(timer_thread, 1);
|
1067
|
+
// shouldn't happen, but we're destroying
|
1068
|
+
// all objects it might have held anyway.
|
1024
1069
|
}
|
1025
1070
|
CloseHandle(timer_thread);
|
1026
1071
|
timer_thread = NULL;
|
1027
|
-
|
1028
|
-
for (i = 0; i < 2; i++) {
|
1029
|
-
if (timer_request[i]) {
|
1030
|
-
CloseHandle(timer_request[i]);
|
1031
|
-
timer_request[i] = NULL;
|
1032
|
-
}
|
1033
|
-
}
|
1034
|
-
if (timer_response) {
|
1035
|
-
CloseHandle(timer_response);
|
1036
|
-
timer_response = NULL;
|
1037
|
-
}
|
1038
|
-
if (timer_mutex) {
|
1039
|
-
CloseHandle(timer_mutex);
|
1040
|
-
timer_mutex = NULL;
|
1072
|
+
timer_thread_id = 0;
|
1041
1073
|
}
|
1042
1074
|
htab_destroy();
|
1075
|
+
usbi_mutex_destroy(&autoclaim_lock);
|
1043
1076
|
}
|
1044
1077
|
|
1045
1078
|
if (r != LIBUSB_SUCCESS)
|
1046
1079
|
--concurrent_usage; // Not expected to call libusb_exit if we failed.
|
1047
1080
|
|
1081
|
+
if (event)
|
1082
|
+
CloseHandle(event);
|
1048
1083
|
ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
|
1049
1084
|
CloseHandle(semaphore);
|
1050
1085
|
return r;
|
@@ -1124,7 +1159,7 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle
|
|
1124
1159
|
cd_buf_short.req.SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
|
1125
1160
|
cd_buf_short.req.SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
1126
1161
|
cd_buf_short.req.SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i;
|
1127
|
-
cd_buf_short.req.SetupPacket.wIndex =
|
1162
|
+
cd_buf_short.req.SetupPacket.wIndex = 0;
|
1128
1163
|
cd_buf_short.req.SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST));
|
1129
1164
|
|
1130
1165
|
// Dummy call to get the required data size. Initial failures are reported as info rather
|
@@ -1153,7 +1188,7 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle
|
|
1153
1188
|
cd_buf_actual->SetupPacket.bmRequest = LIBUSB_ENDPOINT_IN;
|
1154
1189
|
cd_buf_actual->SetupPacket.bRequest = USB_REQUEST_GET_DESCRIPTOR;
|
1155
1190
|
cd_buf_actual->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8) | i;
|
1156
|
-
cd_buf_actual->SetupPacket.wIndex =
|
1191
|
+
cd_buf_actual->SetupPacket.wIndex = 0;
|
1157
1192
|
cd_buf_actual->SetupPacket.wLength = (USHORT)(size - sizeof(USB_DESCRIPTOR_REQUEST));
|
1158
1193
|
|
1159
1194
|
if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, cd_buf_actual, size,
|
@@ -1199,6 +1234,7 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
|
|
1199
1234
|
struct windows_device_priv *priv, *parent_priv;
|
1200
1235
|
struct libusb_context *ctx;
|
1201
1236
|
struct libusb_device* tmp_dev;
|
1237
|
+
unsigned long tmp_id;
|
1202
1238
|
unsigned i;
|
1203
1239
|
|
1204
1240
|
if ((dev == NULL) || (parent_dev == NULL)) {
|
@@ -1216,8 +1252,10 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
|
|
1216
1252
|
// If that's the case, lookup the ancestors to set the bus number
|
1217
1253
|
if (parent_dev->bus_number == 0) {
|
1218
1254
|
for (i=2; ; i++) {
|
1219
|
-
|
1220
|
-
if (
|
1255
|
+
tmp_id = get_ancestor_session_id(devinst, i);
|
1256
|
+
if (tmp_id == 0) break;
|
1257
|
+
tmp_dev = usbi_get_device_by_session_id(ctx, tmp_id);
|
1258
|
+
if (tmp_dev == NULL) continue;
|
1221
1259
|
if (tmp_dev->bus_number != 0) {
|
1222
1260
|
usbi_dbg("got bus number from ancestor #%d", i);
|
1223
1261
|
parent_dev->bus_number = tmp_dev->bus_number;
|
@@ -1525,7 +1563,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
|
|
1525
1563
|
//#define ENUM_DEBUG
|
1526
1564
|
#ifdef ENUM_DEBUG
|
1527
1565
|
const char *passname[] = { "HCD", "HUB", "GEN", "DEV", "HID", "EXT" };
|
1528
|
-
usbi_dbg("
|
1566
|
+
usbi_dbg("#### PROCESSING %ss %s", passname[(pass<=HID_PASS)?pass:HID_PASS+1],
|
1529
1567
|
(pass!=GEN_PASS)?guid_to_string(guid[pass]):"");
|
1530
1568
|
#endif
|
1531
1569
|
for (i = 0; ; i++) {
|
@@ -1627,6 +1665,10 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
|
|
1627
1665
|
LOOP_BREAK(LIBUSB_ERROR_OVERFLOW);
|
1628
1666
|
}
|
1629
1667
|
if_guid = (GUID*) calloc(1, sizeof(GUID));
|
1668
|
+
if (if_guid == NULL) {
|
1669
|
+
usbi_err(ctx, "could not calloc for if_guid: not enough memory");
|
1670
|
+
LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
|
1671
|
+
}
|
1630
1672
|
pCLSIDFromString(guid_string_w, if_guid);
|
1631
1673
|
guid[nb_guids++] = if_guid;
|
1632
1674
|
usbi_dbg("extra GUID: %s", guid_to_string(if_guid));
|
@@ -1849,29 +1891,18 @@ static void windows_exit(void)
|
|
1849
1891
|
exit_polling();
|
1850
1892
|
|
1851
1893
|
if (timer_thread) {
|
1852
|
-
|
1853
|
-
if (
|
1894
|
+
// actually the signal to quit the thread.
|
1895
|
+
if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_EXIT, 0, 0) ||
|
1896
|
+
(WaitForSingleObject(timer_thread, INFINITE) != WAIT_OBJECT_0)) {
|
1854
1897
|
usbi_dbg("could not wait for timer thread to quit");
|
1855
1898
|
TerminateThread(timer_thread, 1);
|
1856
1899
|
}
|
1857
1900
|
CloseHandle(timer_thread);
|
1858
1901
|
timer_thread = NULL;
|
1859
|
-
|
1860
|
-
for (i = 0; i < 2; i++) {
|
1861
|
-
if (timer_request[i]) {
|
1862
|
-
CloseHandle(timer_request[i]);
|
1863
|
-
timer_request[i] = NULL;
|
1864
|
-
}
|
1865
|
-
}
|
1866
|
-
if (timer_response) {
|
1867
|
-
CloseHandle(timer_response);
|
1868
|
-
timer_response = NULL;
|
1869
|
-
}
|
1870
|
-
if (timer_mutex) {
|
1871
|
-
CloseHandle(timer_mutex);
|
1872
|
-
timer_mutex = NULL;
|
1902
|
+
timer_thread_id = 0;
|
1873
1903
|
}
|
1874
1904
|
htab_destroy();
|
1905
|
+
usbi_mutex_destroy(&autoclaim_lock);
|
1875
1906
|
}
|
1876
1907
|
|
1877
1908
|
ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1
|
@@ -1903,7 +1934,7 @@ static int windows_get_config_descriptor(struct libusb_device *dev, uint8_t conf
|
|
1903
1934
|
|
1904
1935
|
config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptor[config_index];
|
1905
1936
|
|
1906
|
-
size =
|
1937
|
+
size = MIN(config_header->wTotalLength, len);
|
1907
1938
|
memcpy(buffer, priv->config_descriptor[config_index], size);
|
1908
1939
|
*host_endian = 0;
|
1909
1940
|
|
@@ -1986,9 +2017,6 @@ static int windows_claim_interface(struct libusb_device_handle *dev_handle, int
|
|
1986
2017
|
int r = LIBUSB_SUCCESS;
|
1987
2018
|
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
1988
2019
|
|
1989
|
-
if (iface >= USB_MAXINTERFACES)
|
1990
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
1991
|
-
|
1992
2020
|
safe_free(priv->usb_interface[iface].endpoint);
|
1993
2021
|
priv->usb_interface[iface].nb_endpoints= 0;
|
1994
2022
|
|
@@ -2084,7 +2112,6 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer)
|
|
2084
2112
|
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd,
|
2085
2113
|
(short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT));
|
2086
2114
|
|
2087
|
-
itransfer->flags |= USBI_TRANSFER_UPDATED_FDS;
|
2088
2115
|
return LIBUSB_SUCCESS;
|
2089
2116
|
}
|
2090
2117
|
|
@@ -2104,7 +2131,6 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer)
|
|
2104
2131
|
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd,
|
2105
2132
|
(short)(IS_XFERIN(transfer) ? POLLIN : POLLOUT));
|
2106
2133
|
|
2107
|
-
itransfer->flags |= USBI_TRANSFER_UPDATED_FDS;
|
2108
2134
|
return LIBUSB_SUCCESS;
|
2109
2135
|
}
|
2110
2136
|
|
@@ -2123,7 +2149,6 @@ static int submit_control_transfer(struct usbi_transfer *itransfer)
|
|
2123
2149
|
|
2124
2150
|
usbi_add_pollfd(ctx, transfer_priv->pollable_fd.fd, POLLIN);
|
2125
2151
|
|
2126
|
-
itransfer->flags |= USBI_TRANSFER_UPDATED_FDS;
|
2127
2152
|
return LIBUSB_SUCCESS;
|
2128
2153
|
|
2129
2154
|
}
|
@@ -2251,7 +2276,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds,
|
|
2251
2276
|
{
|
2252
2277
|
struct windows_transfer_priv* transfer_priv = NULL;
|
2253
2278
|
POLL_NFDS_TYPE i = 0;
|
2254
|
-
bool found
|
2279
|
+
bool found;
|
2255
2280
|
struct usbi_transfer *transfer;
|
2256
2281
|
DWORD io_size, io_result;
|
2257
2282
|
|
@@ -2269,6 +2294,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds,
|
|
2269
2294
|
// Because a Windows OVERLAPPED is used for poll emulation,
|
2270
2295
|
// a pollable fd is created and stored with each transfer
|
2271
2296
|
usbi_mutex_lock(&ctx->flying_transfers_lock);
|
2297
|
+
found = false;
|
2272
2298
|
list_for_each_entry(transfer, &ctx->flying_transfers, list, struct usbi_transfer) {
|
2273
2299
|
transfer_priv = usbi_transfer_get_os_priv(transfer);
|
2274
2300
|
if (transfer_priv->pollable_fd.fd == fds[i].fd) {
|
@@ -2296,6 +2322,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds,
|
|
2296
2322
|
// newly allocated wfd that took the place of the one from the transfer.
|
2297
2323
|
windows_handle_callback(transfer, io_result, io_size);
|
2298
2324
|
} else {
|
2325
|
+
usbi_mutex_unlock(&ctx->open_devs_lock);
|
2299
2326
|
usbi_err(ctx, "could not find a matching transfer for fd %x", fds[i]);
|
2300
2327
|
return LIBUSB_ERROR_NOT_FOUND;
|
2301
2328
|
}
|
@@ -2310,66 +2337,42 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds,
|
|
2310
2337
|
*/
|
2311
2338
|
unsigned __stdcall windows_clock_gettime_threaded(void* param)
|
2312
2339
|
{
|
2313
|
-
|
2314
|
-
|
2315
|
-
|
2316
|
-
|
2317
|
-
//
|
2318
|
-
|
2319
|
-
|
2320
|
-
hires_frequency = 0;
|
2321
|
-
hires_ticks_to_ps = UINT64_C(0);
|
2322
|
-
} else {
|
2323
|
-
hires_frequency = li_frequency.QuadPart;
|
2324
|
-
// The hires frequency can go as high as 4 GHz, so we'll use a conversion
|
2325
|
-
// to picoseconds to compute the tv_nsecs part in clock_gettime
|
2326
|
-
hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency;
|
2327
|
-
usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency);
|
2328
|
-
}
|
2340
|
+
struct timer_request *request;
|
2341
|
+
LARGE_INTEGER hires_counter;
|
2342
|
+
MSG msg;
|
2343
|
+
|
2344
|
+
// The following call will create this thread's message queue
|
2345
|
+
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644946.aspx
|
2346
|
+
pPeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
|
2329
2347
|
|
2330
2348
|
// Signal windows_init() that we're ready to service requests
|
2331
|
-
if (
|
2332
|
-
usbi_dbg("
|
2349
|
+
if (!SetEvent((HANDLE)param)) {
|
2350
|
+
usbi_dbg("SetEvent failed for timer init event: %s", windows_error_str(0));
|
2333
2351
|
}
|
2352
|
+
param = NULL;
|
2334
2353
|
|
2335
2354
|
// Main loop - wait for requests
|
2336
2355
|
while (1) {
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2340
|
-
continue;
|
2341
|
-
}
|
2342
|
-
if (request_count[timer_index] == 0) {
|
2343
|
-
// Request already handled
|
2344
|
-
ResetEvent(timer_request[timer_index]);
|
2345
|
-
// There's still a possiblity that a thread sends a request between the
|
2346
|
-
// time we test request_count[] == 0 and we reset the event, in which case
|
2347
|
-
// the request would be ignored. The simple solution to that is to test
|
2348
|
-
// request_count again and process requests if non zero.
|
2349
|
-
if (request_count[timer_index] == 0)
|
2350
|
-
continue;
|
2356
|
+
if (pGetMessageA(&msg, NULL, WM_TIMER_REQUEST, WM_TIMER_EXIT) == -1) {
|
2357
|
+
usbi_err(NULL, "GetMessage failed for timer thread: %s", windows_error_str(0));
|
2358
|
+
return 1;
|
2351
2359
|
}
|
2352
|
-
|
2353
|
-
|
2354
|
-
|
2360
|
+
|
2361
|
+
switch (msg.message) {
|
2362
|
+
case WM_TIMER_REQUEST:
|
2355
2363
|
// Requests to this thread are for hires always
|
2356
|
-
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2362
|
-
|
2364
|
+
// Microsoft says that this function always succeeds on XP and later
|
2365
|
+
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904.aspx
|
2366
|
+
request = (struct timer_request *)msg.lParam;
|
2367
|
+
QueryPerformanceCounter(&hires_counter);
|
2368
|
+
request->tp->tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
|
2369
|
+
request->tp->tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency) / 1000) * hires_ticks_to_ps);
|
2370
|
+
if (!SetEvent(request->event)) {
|
2371
|
+
usbi_err(NULL, "SetEvent failed for timer request: %s", windows_error_str(0));
|
2363
2372
|
}
|
2364
|
-
|
2373
|
+
break;
|
2365
2374
|
|
2366
|
-
|
2367
|
-
if ( (nb_responses)
|
2368
|
-
&& (ReleaseSemaphore(timer_response, nb_responses, NULL) == 0) ) {
|
2369
|
-
usbi_dbg("unable to release timer semaphore: %s", windows_error_str(0));
|
2370
|
-
}
|
2371
|
-
continue;
|
2372
|
-
case 1: // time to quit
|
2375
|
+
case WM_TIMER_EXIT:
|
2373
2376
|
usbi_dbg("timer thread quitting");
|
2374
2377
|
return 0;
|
2375
2378
|
}
|
@@ -2378,29 +2381,41 @@ unsigned __stdcall windows_clock_gettime_threaded(void* param)
|
|
2378
2381
|
|
2379
2382
|
static int windows_clock_gettime(int clk_id, struct timespec *tp)
|
2380
2383
|
{
|
2384
|
+
struct timer_request request;
|
2381
2385
|
FILETIME filetime;
|
2382
2386
|
ULARGE_INTEGER rtime;
|
2383
2387
|
DWORD r;
|
2384
2388
|
switch(clk_id) {
|
2385
2389
|
case USBI_CLOCK_MONOTONIC:
|
2386
|
-
if (
|
2387
|
-
|
2388
|
-
|
2389
|
-
|
2390
|
-
|
2391
|
-
|
2392
|
-
|
2393
|
-
|
2394
|
-
|
2395
|
-
|
2396
|
-
|
2397
|
-
|
2390
|
+
if (timer_thread) {
|
2391
|
+
request.tp = tp;
|
2392
|
+
request.event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
2393
|
+
if (request.event == NULL) {
|
2394
|
+
return LIBUSB_ERROR_NO_MEM;
|
2395
|
+
}
|
2396
|
+
|
2397
|
+
if (!pPostThreadMessageA(timer_thread_id, WM_TIMER_REQUEST, 0, (LPARAM)&request)) {
|
2398
|
+
usbi_err(NULL, "PostThreadMessage failed for timer thread: %s", windows_error_str(0));
|
2399
|
+
CloseHandle(request.event);
|
2400
|
+
return LIBUSB_ERROR_OTHER;
|
2401
|
+
}
|
2402
|
+
|
2403
|
+
do {
|
2404
|
+
r = WaitForSingleObject(request.event, TIMER_REQUEST_RETRY_MS);
|
2405
|
+
if (r == WAIT_TIMEOUT) {
|
2398
2406
|
usbi_dbg("could not obtain a timer value within reasonable timeframe - too much load?");
|
2399
|
-
break; // Retry until successful
|
2400
|
-
default:
|
2401
|
-
usbi_dbg("WaitForSingleObject failed: %s", windows_error_str(0));
|
2402
|
-
return LIBUSB_ERROR_OTHER;
|
2403
2407
|
}
|
2408
|
+
else if (r == WAIT_FAILED) {
|
2409
|
+
usbi_err(NULL, "WaitForSingleObject failed: %s", windows_error_str(0));
|
2410
|
+
}
|
2411
|
+
} while (r == WAIT_TIMEOUT);
|
2412
|
+
CloseHandle(request.event);
|
2413
|
+
|
2414
|
+
if (r == WAIT_OBJECT_0) {
|
2415
|
+
return LIBUSB_SUCCESS;
|
2416
|
+
}
|
2417
|
+
else {
|
2418
|
+
return LIBUSB_ERROR_OTHER;
|
2404
2419
|
}
|
2405
2420
|
}
|
2406
2421
|
// Fall through and return real-time if monotonic was not detected @ timer init
|
@@ -2462,6 +2477,7 @@ const struct usbi_os_backend windows_backend = {
|
|
2462
2477
|
windows_clear_transfer_priv,
|
2463
2478
|
|
2464
2479
|
windows_handle_events,
|
2480
|
+
NULL, /* handle_transfer_completion() */
|
2465
2481
|
|
2466
2482
|
windows_clock_gettime,
|
2467
2483
|
#if defined(USBI_TIMERFD_AVAILABLE)
|
@@ -2470,7 +2486,6 @@ const struct usbi_os_backend windows_backend = {
|
|
2470
2486
|
sizeof(struct windows_device_priv),
|
2471
2487
|
sizeof(struct windows_device_handle_priv),
|
2472
2488
|
sizeof(struct windows_transfer_priv),
|
2473
|
-
0,
|
2474
2489
|
};
|
2475
2490
|
|
2476
2491
|
|
@@ -2668,7 +2683,7 @@ static int winusbx_init(int sub_api, struct libusb_context *ctx)
|
|
2668
2683
|
if (h == NULL) {
|
2669
2684
|
h = LoadLibraryA("WinUSB");
|
2670
2685
|
} if (h == NULL) {
|
2671
|
-
usbi_warn(ctx, "WinUSB DLL is not available either
|
2686
|
+
usbi_warn(ctx, "WinUSB DLL is not available either, "
|
2672
2687
|
"you will not be able to access devices outside of enumeration");
|
2673
2688
|
return LIBUSB_ERROR_NOT_FOUND;
|
2674
2689
|
}
|
@@ -2769,7 +2784,7 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
|
|
2769
2784
|
{
|
2770
2785
|
struct windows_device_handle_priv *handle_priv = _device_handle_priv(dev_handle);
|
2771
2786
|
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
2772
|
-
HANDLE
|
2787
|
+
HANDLE handle;
|
2773
2788
|
int i;
|
2774
2789
|
|
2775
2790
|
if (sub_api == SUB_API_NOTSET)
|
@@ -2777,13 +2792,39 @@ static void winusbx_close(int sub_api, struct libusb_device_handle *dev_handle)
|
|
2777
2792
|
if (!WinUSBX[sub_api].initialized)
|
2778
2793
|
return;
|
2779
2794
|
|
2780
|
-
|
2781
|
-
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2795
|
+
if (priv->apib->id == USB_API_COMPOSITE) {
|
2796
|
+
// If this is a composite device, just free and close all WinUSB-like
|
2797
|
+
// interfaces directly (each is independent and not associated with another)
|
2798
|
+
for (i = 0; i < USB_MAXINTERFACES; i++) {
|
2799
|
+
if (priv->usb_interface[i].apib->id == USB_API_WINUSBX) {
|
2800
|
+
handle = handle_priv->interface_handle[i].api_handle;
|
2801
|
+
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
|
2802
|
+
WinUSBX[sub_api].Free(handle);
|
2803
|
+
}
|
2804
|
+
handle = handle_priv->interface_handle[i].dev_handle;
|
2805
|
+
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
|
2806
|
+
CloseHandle(handle);
|
2807
|
+
}
|
2808
|
+
}
|
2809
|
+
}
|
2810
|
+
}
|
2811
|
+
else {
|
2812
|
+
// If this is a WinUSB device, free all interfaces above interface 0,
|
2813
|
+
// then free and close interface 0 last
|
2814
|
+
for (i = 1; i < USB_MAXINTERFACES; i++) {
|
2815
|
+
handle = handle_priv->interface_handle[i].api_handle;
|
2816
|
+
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
|
2817
|
+
WinUSBX[sub_api].Free(handle);
|
2785
2818
|
}
|
2786
2819
|
}
|
2820
|
+
handle = handle_priv->interface_handle[0].api_handle;
|
2821
|
+
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
|
2822
|
+
WinUSBX[sub_api].Free(handle);
|
2823
|
+
}
|
2824
|
+
handle = handle_priv->interface_handle[0].dev_handle;
|
2825
|
+
if ((handle != 0) && (handle != INVALID_HANDLE_VALUE)) {
|
2826
|
+
CloseHandle(handle);
|
2827
|
+
}
|
2787
2828
|
}
|
2788
2829
|
}
|
2789
2830
|
|
@@ -3579,7 +3620,7 @@ static int _hid_get_descriptor(struct hid_device_priv* dev, HANDLE hid_handle, i
|
|
3579
3620
|
return LIBUSB_ERROR_OTHER;
|
3580
3621
|
}
|
3581
3622
|
usbi_dbg("unsupported");
|
3582
|
-
return
|
3623
|
+
return LIBUSB_ERROR_NOT_SUPPORTED;
|
3583
3624
|
}
|
3584
3625
|
|
3585
3626
|
static int _hid_get_report(struct hid_device_priv* dev, HANDLE hid_handle, int id, void *data,
|
@@ -4086,7 +4127,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
|
|
4086
4127
|
r = LIBUSB_COMPLETED;
|
4087
4128
|
} else {
|
4088
4129
|
usbi_warn(ctx, "cannot set configuration other than the default one");
|
4089
|
-
r =
|
4130
|
+
r = LIBUSB_ERROR_NOT_SUPPORTED;
|
4090
4131
|
}
|
4091
4132
|
break;
|
4092
4133
|
case LIBUSB_REQUEST_GET_INTERFACE:
|
@@ -4102,7 +4143,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
|
|
4102
4143
|
break;
|
4103
4144
|
default:
|
4104
4145
|
usbi_warn(ctx, "unsupported HID control request");
|
4105
|
-
r =
|
4146
|
+
r = LIBUSB_ERROR_NOT_SUPPORTED;
|
4106
4147
|
break;
|
4107
4148
|
}
|
4108
4149
|
break;
|
@@ -4113,7 +4154,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
|
|
4113
4154
|
break;
|
4114
4155
|
default:
|
4115
4156
|
usbi_warn(ctx, "unsupported HID control request");
|
4116
|
-
r =
|
4157
|
+
r = LIBUSB_ERROR_NOT_SUPPORTED;
|
4117
4158
|
break;
|
4118
4159
|
}
|
4119
4160
|
|
@@ -4387,24 +4428,31 @@ static void composite_close(int sub_api, struct libusb_device_handle *dev_handle
|
|
4387
4428
|
{
|
4388
4429
|
struct windows_device_priv *priv = _device_priv(dev_handle->dev);
|
4389
4430
|
uint8_t i;
|
4390
|
-
|
4391
|
-
|
4392
|
-
for (i = 0; i<SUB_API_MAX; i++) {
|
4393
|
-
available[i] = false;
|
4394
|
-
}
|
4431
|
+
// SUB_API_MAX+1 as the SUB_API_MAX pos is used to indicate availability of HID
|
4432
|
+
bool available[SUB_API_MAX+1] = {0};
|
4395
4433
|
|
4396
4434
|
for (i=0; i<USB_MAXINTERFACES; i++) {
|
4397
|
-
|
4398
|
-
|
4399
|
-
|
4435
|
+
switch (priv->usb_interface[i].apib->id) {
|
4436
|
+
case USB_API_WINUSBX:
|
4437
|
+
if (priv->usb_interface[i].sub_api != SUB_API_NOTSET)
|
4438
|
+
available[priv->usb_interface[i].sub_api] = true;
|
4439
|
+
break;
|
4440
|
+
case USB_API_HID:
|
4441
|
+
available[SUB_API_MAX] = true;
|
4442
|
+
break;
|
4443
|
+
default:
|
4444
|
+
break;
|
4400
4445
|
}
|
4401
4446
|
}
|
4402
4447
|
|
4403
|
-
for (i=0; i<SUB_API_MAX; i++) {
|
4448
|
+
for (i=0; i<SUB_API_MAX; i++) { // WinUSB-like drivers
|
4404
4449
|
if (available[i]) {
|
4405
4450
|
usb_api_backend[USB_API_WINUSBX].close(i, dev_handle);
|
4406
4451
|
}
|
4407
4452
|
}
|
4453
|
+
if (available[SUB_API_MAX]) { // HID driver
|
4454
|
+
hid_close(SUB_API_NOTSET, dev_handle);
|
4455
|
+
}
|
4408
4456
|
}
|
4409
4457
|
|
4410
4458
|
static int composite_claim_interface(int sub_api, struct libusb_device_handle *dev_handle, int iface)
|
@@ -4433,19 +4481,57 @@ static int composite_submit_control_transfer(int sub_api, struct usbi_transfer *
|
|
4433
4481
|
struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
|
4434
4482
|
struct libusb_context *ctx = DEVICE_CTX(transfer->dev_handle->dev);
|
4435
4483
|
struct windows_device_priv *priv = _device_priv(transfer->dev_handle->dev);
|
4436
|
-
|
4484
|
+
struct libusb_config_descriptor *conf_desc;
|
4485
|
+
WINUSB_SETUP_PACKET *setup = (WINUSB_SETUP_PACKET *) transfer->buffer;
|
4486
|
+
int iface, pass, r;
|
4437
4487
|
|
4438
4488
|
// Interface shouldn't matter for control, but it does in practice, with Windows'
|
4439
|
-
// restrictions with regards to accessing HID keyboards and mice. Try
|
4489
|
+
// restrictions with regards to accessing HID keyboards and mice. Try to target
|
4490
|
+
// a specific interface first, if possible.
|
4491
|
+
switch (LIBUSB_REQ_RECIPIENT(setup->request_type)) {
|
4492
|
+
case LIBUSB_RECIPIENT_INTERFACE:
|
4493
|
+
iface = setup->index & 0xFF;
|
4494
|
+
break;
|
4495
|
+
case LIBUSB_RECIPIENT_ENDPOINT:
|
4496
|
+
r = libusb_get_config_descriptor(transfer->dev_handle->dev, (uint8_t)(priv->active_config-1), &conf_desc);
|
4497
|
+
if (r == LIBUSB_SUCCESS) {
|
4498
|
+
iface = get_interface_by_endpoint(conf_desc, (setup->index & 0xFF));
|
4499
|
+
libusb_free_config_descriptor(conf_desc);
|
4500
|
+
break;
|
4501
|
+
}
|
4502
|
+
// Fall through if not able to determine interface
|
4503
|
+
default:
|
4504
|
+
iface = -1;
|
4505
|
+
break;
|
4506
|
+
}
|
4507
|
+
|
4508
|
+
// Try and target a specific interface if the control setup indicates such
|
4509
|
+
if ((iface >= 0) && (iface < USB_MAXINTERFACES)) {
|
4510
|
+
usbi_dbg("attempting control transfer targeted to interface %d", iface);
|
4511
|
+
if (priv->usb_interface[iface].path != NULL) {
|
4512
|
+
r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
|
4513
|
+
if (r == LIBUSB_SUCCESS) {
|
4514
|
+
return r;
|
4515
|
+
}
|
4516
|
+
}
|
4517
|
+
}
|
4518
|
+
|
4519
|
+
// Either not targeted to a specific interface or no luck in doing so.
|
4520
|
+
// Try a 2 pass approach with all interfaces.
|
4440
4521
|
for (pass = 0; pass < 2; pass++) {
|
4441
|
-
for (
|
4442
|
-
if (priv->usb_interface[
|
4443
|
-
if ((pass == 0) && (priv->usb_interface[
|
4444
|
-
usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)",
|
4522
|
+
for (iface = 0; iface < USB_MAXINTERFACES; iface++) {
|
4523
|
+
if (priv->usb_interface[iface].path != NULL) {
|
4524
|
+
if ((pass == 0) && (priv->usb_interface[iface].restricted_functionality)) {
|
4525
|
+
usbi_dbg("trying to skip restricted interface #%d (HID keyboard or mouse?)", iface);
|
4445
4526
|
continue;
|
4446
4527
|
}
|
4447
|
-
usbi_dbg("using interface %d",
|
4448
|
-
|
4528
|
+
usbi_dbg("using interface %d", iface);
|
4529
|
+
r = priv->usb_interface[iface].apib->submit_control_transfer(priv->usb_interface[iface].sub_api, itransfer);
|
4530
|
+
// If not supported on this API, it may be supported on another, so don't give up yet!!
|
4531
|
+
if (r == LIBUSB_ERROR_NOT_SUPPORTED) {
|
4532
|
+
continue;
|
4533
|
+
}
|
4534
|
+
return r;
|
4449
4535
|
}
|
4450
4536
|
}
|
4451
4537
|
}
|