libusb 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
}
|