libusb 0.4.1 → 0.5.0

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.
Files changed (126) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +2 -0
  3. data.tar.gz.sig +0 -0
  4. data/.travis.yml +3 -3
  5. data/History.md +8 -0
  6. data/README.md +1 -0
  7. data/Rakefile +14 -14
  8. data/ext/{libusb-1.0.18 → libusb-1.0.19}/AUTHORS +6 -0
  9. data/ext/{libusb-1.0.18 → libusb-1.0.19}/COPYING +0 -0
  10. data/ext/{libusb-1.0.18 → libusb-1.0.19}/ChangeLog +9 -2
  11. data/ext/{libusb-1.0.18 → libusb-1.0.19}/INSTALL +0 -0
  12. data/ext/{libusb-1.0.18 → libusb-1.0.19}/Makefile.am +0 -0
  13. data/ext/{libusb-1.0.18 → libusb-1.0.19}/Makefile.in +188 -156
  14. data/ext/{libusb-1.0.18 → libusb-1.0.19}/NEWS +0 -0
  15. data/ext/{libusb-1.0.18 → libusb-1.0.19}/PORTING +0 -0
  16. data/ext/{libusb-1.0.18 → libusb-1.0.19}/README +0 -0
  17. data/ext/{libusb-1.0.18 → libusb-1.0.19}/TODO +0 -0
  18. data/ext/{libusb-1.0.18 → libusb-1.0.19}/Xcode/common.xcconfig +10 -1
  19. data/ext/{libusb-1.0.18 → libusb-1.0.19}/Xcode/config.h +0 -0
  20. data/ext/{libusb-1.0.18 → libusb-1.0.19}/Xcode/debug.xcconfig +0 -0
  21. data/ext/{libusb-1.0.18 → libusb-1.0.19}/Xcode/libusb.xcconfig +1 -1
  22. data/ext/{libusb-1.0.18 → libusb-1.0.19}/Xcode/libusb.xcodeproj/project.pbxproj +0 -0
  23. data/ext/{libusb-1.0.18 → libusb-1.0.19}/Xcode/libusb_debug.xcconfig +0 -0
  24. data/ext/{libusb-1.0.18 → libusb-1.0.19}/Xcode/libusb_release.xcconfig +0 -0
  25. data/ext/{libusb-1.0.18 → libusb-1.0.19}/Xcode/release.xcconfig +1 -0
  26. data/ext/libusb-1.0.19/aclocal.m4 +1190 -0
  27. data/ext/{libusb-1.0.18 → libusb-1.0.19}/android/README +0 -0
  28. data/ext/{libusb-1.0.18 → libusb-1.0.19}/android/config.h +0 -0
  29. data/ext/{libusb-1.0.18 → libusb-1.0.19}/android/jni/Android.mk +0 -0
  30. data/ext/{libusb-1.0.18 → libusb-1.0.19}/android/jni/Application.mk +0 -0
  31. data/ext/{libusb-1.0.18 → libusb-1.0.19}/android/jni/examples.mk +0 -0
  32. data/ext/{libusb-1.0.18 → libusb-1.0.19}/android/jni/libusb.mk +0 -0
  33. data/ext/{libusb-1.0.18 → libusb-1.0.19}/android/jni/tests.mk +0 -0
  34. data/ext/{libusb-1.0.18 → libusb-1.0.19}/compile +7 -3
  35. data/ext/{libusb-1.0.18 → libusb-1.0.19}/config.guess +116 -78
  36. data/ext/{libusb-1.0.18 → libusb-1.0.19}/config.h.in +0 -3
  37. data/ext/{libusb-1.0.18 → libusb-1.0.19}/config.sub +66 -46
  38. data/ext/{libusb-1.0.18 → libusb-1.0.19}/configure +265 -208
  39. data/ext/{libusb-1.0.18 → libusb-1.0.19}/configure.ac +0 -0
  40. data/ext/{libusb-1.0.18 → libusb-1.0.19}/depcomp +269 -186
  41. data/ext/{libusb-1.0.18 → libusb-1.0.19}/doc/Makefile.am +0 -0
  42. data/ext/{libusb-1.0.18 → libusb-1.0.19}/doc/Makefile.in +72 -35
  43. data/ext/{libusb-1.0.18 → libusb-1.0.19}/doc/doxygen.cfg.in +1 -1
  44. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/Makefile.am +0 -0
  45. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/Makefile.in +134 -70
  46. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/dpfp.c +0 -0
  47. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/dpfp_threaded.c +0 -0
  48. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/ezusb.c +9 -5
  49. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/ezusb.h +0 -0
  50. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/fxload.c +1 -1
  51. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/getopt/getopt.c +0 -0
  52. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/getopt/getopt.h +0 -0
  53. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/getopt/getopt1.c +0 -0
  54. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/hotplugtest.c +0 -0
  55. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/listdevs.c +0 -0
  56. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/sam3u_benchmark.c +0 -0
  57. data/ext/{libusb-1.0.18 → libusb-1.0.19}/examples/xusb.c +22 -2
  58. data/ext/{libusb-1.0.18 → libusb-1.0.19}/install-sh +7 -7
  59. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb-1.0.pc.in +0 -0
  60. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/Makefile.am +0 -0
  61. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/Makefile.in +133 -93
  62. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/core.c +86 -15
  63. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/descriptor.c +0 -0
  64. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/hotplug.c +6 -1
  65. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/hotplug.h +0 -0
  66. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/io.c +54 -17
  67. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/libusb-1.0.def +8 -0
  68. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/libusb-1.0.rc +0 -0
  69. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/libusb.h +42 -2
  70. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/libusbi.h +10 -1
  71. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/darwin_usb.c +156 -53
  72. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/darwin_usb.h +1 -1
  73. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/linux_netlink.c +26 -2
  74. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/linux_udev.c +2 -1
  75. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/linux_usbfs.c +93 -6
  76. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/linux_usbfs.h +12 -1
  77. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/netbsd_usb.c +6 -0
  78. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/openbsd_usb.c +6 -0
  79. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/poll_posix.c +0 -0
  80. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/poll_posix.h +0 -0
  81. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/poll_windows.c +0 -0
  82. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/poll_windows.h +12 -6
  83. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/threads_posix.c +0 -0
  84. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/threads_posix.h +0 -0
  85. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/threads_windows.c +0 -0
  86. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/threads_windows.h +0 -0
  87. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/wince_usb.c +8 -1
  88. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/wince_usb.h +0 -0
  89. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/windows_common.h +0 -0
  90. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/windows_usb.c +175 -42
  91. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/os/windows_usb.h +35 -0
  92. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/strerror.c +17 -2
  93. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/sync.c +0 -0
  94. data/ext/{libusb-1.0.18 → libusb-1.0.19}/libusb/version.h +1 -1
  95. data/ext/libusb-1.0.19/libusb/version_nano.h +1 -0
  96. data/ext/{libusb-1.0.18 → libusb-1.0.19}/ltmain.sh +3 -3
  97. data/ext/{libusb-1.0.18/aclocal.m4 → libusb-1.0.19/m4/libtool.m4} +36 -1734
  98. data/ext/libusb-1.0.19/m4/ltoptions.m4 +384 -0
  99. data/ext/libusb-1.0.19/m4/ltsugar.m4 +123 -0
  100. data/ext/libusb-1.0.19/m4/ltversion.m4 +23 -0
  101. data/ext/libusb-1.0.19/m4/lt~obsolete.m4 +98 -0
  102. data/ext/libusb-1.0.19/missing +215 -0
  103. data/ext/{libusb-1.0.18 → libusb-1.0.19}/tests/Makefile.am +0 -0
  104. data/ext/{libusb-1.0.18 → libusb-1.0.19}/tests/Makefile.in +128 -70
  105. data/ext/{libusb-1.0.18 → libusb-1.0.19}/tests/libusb_testlib.h +0 -0
  106. data/ext/{libusb-1.0.18 → libusb-1.0.19}/tests/stress.c +0 -0
  107. data/ext/{libusb-1.0.18 → libusb-1.0.19}/tests/testlib.c +0 -0
  108. data/lib/libusb.rb +3 -1
  109. data/lib/libusb/bos.rb +306 -0
  110. data/lib/libusb/call.rb +84 -0
  111. data/lib/libusb/constants.rb +4 -0
  112. data/lib/libusb/dev_handle.rb +77 -0
  113. data/lib/libusb/endpoint.rb +20 -0
  114. data/lib/libusb/ss_companion.rb +69 -0
  115. data/lib/libusb/transfer.rb +34 -0
  116. data/lib/libusb/version_gem.rb +1 -1
  117. data/libusb.gemspec +1 -0
  118. data/test/test_libusb_bos.rb +118 -0
  119. data/test/test_libusb_bulk_stream_transfer.rb +50 -0
  120. data/test/test_libusb_descriptors.rb +29 -0
  121. data/test/test_libusb_hotplug.rb +1 -1
  122. data/test/test_libusb_threads.rb +1 -1
  123. metadata +146 -124
  124. metadata.gz.sig +0 -0
  125. data/ext/libusb-1.0.18/libusb/version_nano.h +0 -1
  126. data/ext/libusb-1.0.18/missing +0 -331
@@ -137,7 +137,7 @@ struct darwin_device_handle_priv {
137
137
  uint8_t num_endpoints;
138
138
  CFRunLoopSourceRef cfSource;
139
139
  uint64_t frames[256];
140
- uint8_t endpoint_addrs[USB_MAXENDPOINTS];
140
+ uint8_t endpoint_addrs[USB_MAXENDPOINTS];
141
141
  } interfaces[USB_MAXINTERFACES];
142
142
  };
143
143
 
@@ -224,8 +224,32 @@ static int linux_netlink_parse(char *buffer, size_t len, int *detached, const ch
224
224
 
225
225
  tmp = netlink_message_parse(buffer, len, "BUSNUM");
226
226
  if (NULL == tmp) {
227
- /* no bus number (likely a usb interface). ignore*/
228
- return -1;
227
+ /* no bus number. try "DEVICE" */
228
+ tmp = netlink_message_parse(buffer, len, "DEVICE");
229
+ if (NULL == tmp) {
230
+ /* not usb. ignore */
231
+ return -1;
232
+ }
233
+
234
+ /* Parse a device path such as /dev/bus/usb/003/004 */
235
+ char *pLastSlash = (char*)strrchr(tmp,'/');
236
+ if(NULL == pLastSlash) {
237
+ return -1;
238
+ }
239
+
240
+ *devaddr = strtoul(pLastSlash + 1, NULL, 10);
241
+ if (errno) {
242
+ errno = 0;
243
+ return -1;
244
+ }
245
+
246
+ *busnum = strtoul(pLastSlash - 3, NULL, 10);
247
+ if (errno) {
248
+ errno = 0;
249
+ return -1;
250
+ }
251
+
252
+ return 0;
229
253
  }
230
254
 
231
255
  *busnum = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff);
@@ -61,7 +61,7 @@ int linux_udev_start_event_monitor(void)
61
61
  udev_ctx = udev_new();
62
62
  if (!udev_ctx) {
63
63
  usbi_err(NULL, "could not create udev context");
64
- return LIBUSB_ERROR_OTHER;
64
+ goto err;
65
65
  }
66
66
 
67
67
  udev_monitor = udev_monitor_new_from_netlink(udev_ctx, "udev");
@@ -119,6 +119,7 @@ err_free_monitor:
119
119
  udev_monitor_fd = -1;
120
120
  err_free_ctx:
121
121
  udev_unref(udev_ctx);
122
+ err:
122
123
  udev_ctx = NULL;
123
124
  return LIBUSB_ERROR_OTHER;
124
125
  }
@@ -119,7 +119,7 @@ static int sysfs_can_relate_devices = -1;
119
119
  static int sysfs_has_descriptors = -1;
120
120
 
121
121
  /* how many times have we initted (and not exited) ? */
122
- static volatile int init_count = 0;
122
+ static int init_count = 0;
123
123
 
124
124
  /* Serialize hotplug start/stop */
125
125
  usbi_mutex_static_t linux_hotplug_startstop_lock = USBI_MUTEX_INITIALIZER;
@@ -184,6 +184,7 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
184
184
  struct libusb_context *ctx = DEVICE_CTX(dev);
185
185
  char path[PATH_MAX];
186
186
  int fd;
187
+ int delay = 10000;
187
188
 
188
189
  if (usbdev_names)
189
190
  snprintf(path, PATH_MAX, "%s/usbdev%d.%d",
@@ -196,6 +197,18 @@ static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
196
197
  if (fd != -1)
197
198
  return fd; /* Success */
198
199
 
200
+ if (errno == ENOENT) {
201
+ if (!silent)
202
+ usbi_err(ctx, "File doesn't exist, wait %d ms and try again\n", delay/1000);
203
+
204
+ /* Wait 10ms for USB device path creation.*/
205
+ usleep(delay);
206
+
207
+ fd = open(path, mode);
208
+ if (fd != -1)
209
+ return fd; /* Success */
210
+ }
211
+
199
212
  if (!silent) {
200
213
  usbi_err(ctx, "libusb couldn't open USB device %s: %s",
201
214
  path, strerror(errno));
@@ -1482,6 +1495,56 @@ out:
1482
1495
  return ret;
1483
1496
  }
1484
1497
 
1498
+ static int do_streams_ioctl(struct libusb_device_handle *handle, long req,
1499
+ uint32_t num_streams, unsigned char *endpoints, int num_endpoints)
1500
+ {
1501
+ int r, fd = _device_handle_priv(handle)->fd;
1502
+ struct usbfs_streams *streams;
1503
+
1504
+ if (num_endpoints > 30) /* Max 15 in + 15 out eps */
1505
+ return LIBUSB_ERROR_INVALID_PARAM;
1506
+
1507
+ streams = malloc(sizeof(struct usbfs_streams) + num_endpoints);
1508
+ if (!streams)
1509
+ return LIBUSB_ERROR_NO_MEM;
1510
+
1511
+ streams->num_streams = num_streams;
1512
+ streams->num_eps = num_endpoints;
1513
+ memcpy(streams->eps, endpoints, num_endpoints);
1514
+
1515
+ r = ioctl(fd, req, streams);
1516
+
1517
+ free(streams);
1518
+
1519
+ if (r < 0) {
1520
+ if (errno == ENOTTY)
1521
+ return LIBUSB_ERROR_NOT_SUPPORTED;
1522
+ else if (errno == EINVAL)
1523
+ return LIBUSB_ERROR_INVALID_PARAM;
1524
+ else if (errno == ENODEV)
1525
+ return LIBUSB_ERROR_NO_DEVICE;
1526
+
1527
+ usbi_err(HANDLE_CTX(handle),
1528
+ "streams-ioctl failed error %d errno %d", r, errno);
1529
+ return LIBUSB_ERROR_OTHER;
1530
+ }
1531
+ return r;
1532
+ }
1533
+
1534
+ static int op_alloc_streams(struct libusb_device_handle *handle,
1535
+ uint32_t num_streams, unsigned char *endpoints, int num_endpoints)
1536
+ {
1537
+ return do_streams_ioctl(handle, IOCTL_USBFS_ALLOC_STREAMS,
1538
+ num_streams, endpoints, num_endpoints);
1539
+ }
1540
+
1541
+ static int op_free_streams(struct libusb_device_handle *handle,
1542
+ unsigned char *endpoints, int num_endpoints)
1543
+ {
1544
+ return do_streams_ioctl(handle, IOCTL_USBFS_FREE_STREAMS, 0,
1545
+ endpoints, num_endpoints);
1546
+ }
1547
+
1485
1548
  static int op_kernel_driver_active(struct libusb_device_handle *handle,
1486
1549
  int interface)
1487
1550
  {
@@ -1689,8 +1752,7 @@ static void free_iso_urbs(struct linux_transfer_priv *tpriv)
1689
1752
  tpriv->iso_urbs = NULL;
1690
1753
  }
1691
1754
 
1692
- static int submit_bulk_transfer(struct usbi_transfer *itransfer,
1693
- unsigned char urb_type)
1755
+ static int submit_bulk_transfer(struct usbi_transfer *itransfer)
1694
1756
  {
1695
1757
  struct libusb_transfer *transfer =
1696
1758
  USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
@@ -1778,7 +1840,19 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer,
1778
1840
  for (i = 0; i < num_urbs; i++) {
1779
1841
  struct usbfs_urb *urb = &urbs[i];
1780
1842
  urb->usercontext = itransfer;
1781
- urb->type = urb_type;
1843
+ switch (transfer->type) {
1844
+ case LIBUSB_TRANSFER_TYPE_BULK:
1845
+ urb->type = USBFS_URB_TYPE_BULK;
1846
+ urb->stream_id = 0;
1847
+ break;
1848
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
1849
+ urb->type = USBFS_URB_TYPE_BULK;
1850
+ urb->stream_id = itransfer->stream_id;
1851
+ break;
1852
+ case LIBUSB_TRANSFER_TYPE_INTERRUPT:
1853
+ urb->type = USBFS_URB_TYPE_INTERRUPT;
1854
+ break;
1855
+ }
1782
1856
  urb->endpoint = transfer->endpoint;
1783
1857
  urb->buffer = transfer->buffer + (i * bulk_buffer_len);
1784
1858
  /* don't set the short not ok flag for the last URB */
@@ -2061,9 +2135,10 @@ static int op_submit_transfer(struct usbi_transfer *itransfer)
2061
2135
  case LIBUSB_TRANSFER_TYPE_CONTROL:
2062
2136
  return submit_control_transfer(itransfer);
2063
2137
  case LIBUSB_TRANSFER_TYPE_BULK:
2064
- return submit_bulk_transfer(itransfer, USBFS_URB_TYPE_BULK);
2138
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2139
+ return submit_bulk_transfer(itransfer);
2065
2140
  case LIBUSB_TRANSFER_TYPE_INTERRUPT:
2066
- return submit_bulk_transfer(itransfer, USBFS_URB_TYPE_INTERRUPT);
2141
+ return submit_bulk_transfer(itransfer);
2067
2142
  case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
2068
2143
  return submit_iso_transfer(itransfer);
2069
2144
  default:
@@ -2081,6 +2156,7 @@ static int op_cancel_transfer(struct usbi_transfer *itransfer)
2081
2156
 
2082
2157
  switch (transfer->type) {
2083
2158
  case LIBUSB_TRANSFER_TYPE_BULK:
2159
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2084
2160
  if (tpriv->reap_action == ERROR)
2085
2161
  break;
2086
2162
  /* else, fall through */
@@ -2111,6 +2187,7 @@ static void op_clear_transfer_priv(struct usbi_transfer *itransfer)
2111
2187
  switch (transfer->type) {
2112
2188
  case LIBUSB_TRANSFER_TYPE_CONTROL:
2113
2189
  case LIBUSB_TRANSFER_TYPE_BULK:
2190
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2114
2191
  case LIBUSB_TRANSFER_TYPE_INTERRUPT:
2115
2192
  usbi_mutex_lock(&itransfer->lock);
2116
2193
  if (tpriv->urbs)
@@ -2479,6 +2556,7 @@ static int reap_for_handle(struct libusb_device_handle *handle)
2479
2556
  case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
2480
2557
  return handle_iso_completion(itransfer, urb);
2481
2558
  case LIBUSB_TRANSFER_TYPE_BULK:
2559
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2482
2560
  case LIBUSB_TRANSFER_TYPE_INTERRUPT:
2483
2561
  return handle_bulk_completion(itransfer, urb);
2484
2562
  case LIBUSB_TRANSFER_TYPE_CONTROL:
@@ -2512,6 +2590,12 @@ static int op_handle_events(struct libusb_context *ctx,
2512
2590
  break;
2513
2591
  }
2514
2592
 
2593
+ if (!hpriv || hpriv->fd != pollfd->fd) {
2594
+ usbi_err(ctx, "cannot find handle for fd %d\n",
2595
+ pollfd->fd);
2596
+ continue;
2597
+ }
2598
+
2515
2599
  if (pollfd->revents & POLLERR) {
2516
2600
  usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->fd);
2517
2601
  usbi_handle_disconnect(handle);
@@ -2583,6 +2667,9 @@ const struct usbi_os_backend linux_usbfs_backend = {
2583
2667
  .clear_halt = op_clear_halt,
2584
2668
  .reset_device = op_reset_device,
2585
2669
 
2670
+ .alloc_streams = op_alloc_streams,
2671
+ .free_streams = op_free_streams,
2672
+
2586
2673
  .kernel_driver_active = op_kernel_driver_active,
2587
2674
  .detach_kernel_driver = op_detach_kernel_driver,
2588
2675
  .attach_kernel_driver = op_attach_kernel_driver,
@@ -94,7 +94,10 @@ struct usbfs_urb {
94
94
  int buffer_length;
95
95
  int actual_length;
96
96
  int start_frame;
97
- int number_of_packets;
97
+ union {
98
+ int number_of_packets; /* Only used for isoc urbs */
99
+ unsigned int stream_id; /* Only used with bulk streams */
100
+ };
98
101
  int error_count;
99
102
  unsigned int signr;
100
103
  void *usercontext;
@@ -132,6 +135,12 @@ struct usbfs_disconnect_claim {
132
135
  char driver[USBFS_MAXDRIVERNAME + 1];
133
136
  };
134
137
 
138
+ struct usbfs_streams {
139
+ unsigned int num_streams; /* Not used by USBDEVFS_FREE_STREAMS */
140
+ unsigned int num_eps;
141
+ unsigned char eps[0];
142
+ };
143
+
135
144
  #define IOCTL_USBFS_CONTROL _IOWR('U', 0, struct usbfs_ctrltransfer)
136
145
  #define IOCTL_USBFS_BULK _IOWR('U', 2, struct usbfs_bulktransfer)
137
146
  #define IOCTL_USBFS_RESETEP _IOR('U', 3, unsigned int)
@@ -155,6 +164,8 @@ struct usbfs_disconnect_claim {
155
164
  #define IOCTL_USBFS_RELEASE_PORT _IOR('U', 25, unsigned int)
156
165
  #define IOCTL_USBFS_GET_CAPABILITIES _IOR('U', 26, __u32)
157
166
  #define IOCTL_USBFS_DISCONNECT_CLAIM _IOR('U', 27, struct usbfs_disconnect_claim)
167
+ #define IOCTL_USBFS_ALLOC_STREAMS _IOR('U', 28, struct usbfs_streams)
168
+ #define IOCTL_USBFS_FREE_STREAMS _IOR('U', 29, struct usbfs_streams)
158
169
 
159
170
  extern usbi_mutex_static_t linux_hotplug_lock;
160
171
 
@@ -112,6 +112,9 @@ const struct usbi_os_backend netbsd_backend = {
112
112
  netbsd_clear_halt,
113
113
  netbsd_reset_device,
114
114
 
115
+ NULL, /* alloc_streams */
116
+ NULL, /* free_streams */
117
+
115
118
  NULL, /* kernel_driver_active() */
116
119
  NULL, /* detach_kernel_driver() */
117
120
  NULL, /* attach_kernel_driver() */
@@ -458,6 +461,9 @@ netbsd_submit_transfer(struct usbi_transfer *itransfer)
458
461
  }
459
462
  err = _sync_gen_transfer(itransfer);
460
463
  break;
464
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
465
+ err = LIBUSB_ERROR_NOT_SUPPORTED;
466
+ break;
461
467
  }
462
468
 
463
469
  if (err)
@@ -115,6 +115,9 @@ const struct usbi_os_backend openbsd_backend = {
115
115
  obsd_clear_halt,
116
116
  obsd_reset_device,
117
117
 
118
+ NULL, /* alloc_streams */
119
+ NULL, /* free_streams */
120
+
118
121
  NULL, /* kernel_driver_active() */
119
122
  NULL, /* detach_kernel_driver() */
120
123
  NULL, /* attach_kernel_driver() */
@@ -504,6 +507,9 @@ obsd_submit_transfer(struct usbi_transfer *itransfer)
504
507
  }
505
508
  err = _sync_gen_transfer(itransfer);
506
509
  break;
510
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
511
+ err = LIBUSB_ERROR_NOT_SUPPORTED;
512
+ break;
507
513
  }
508
514
 
509
515
  if (err)
@@ -40,14 +40,20 @@
40
40
 
41
41
  #define DUMMY_HANDLE ((HANDLE)(LONG_PTR)-2)
42
42
 
43
+ /* Windows versions */
43
44
  enum windows_version {
44
- WINDOWS_UNSUPPORTED,
45
- WINDOWS_CE,
46
- WINDOWS_XP,
47
- WINDOWS_2003, // also includes XP 64
48
- WINDOWS_VISTA_AND_LATER,
45
+ WINDOWS_CE = -2,
46
+ WINDOWS_UNDEFINED = -1,
47
+ WINDOWS_UNSUPPORTED = 0,
48
+ WINDOWS_XP = 0x51,
49
+ WINDOWS_2003 = 0x52, // Also XP x64
50
+ WINDOWS_VISTA = 0x60,
51
+ WINDOWS_7 = 0x61,
52
+ WINDOWS_8 = 0x62,
53
+ WINDOWS_8_1_OR_LATER = 0x63,
54
+ WINDOWS_MAX
49
55
  };
50
- extern enum windows_version windows_version;
56
+ extern int windows_version;
51
57
 
52
58
  #define MAX_FDS 256
53
59
 
@@ -38,7 +38,7 @@ unsigned __stdcall wince_clock_gettime_threaded(void* param);
38
38
  uint64_t hires_frequency, hires_ticks_to_ps;
39
39
  int errno;
40
40
  const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
41
- enum windows_version windows_version = WINDOWS_CE;
41
+ int windows_version = WINDOWS_CE;
42
42
  static int concurrent_usage = -1;
43
43
  // Timer thread
44
44
  // NB: index 0 is for monotonic and 1 is for the thread exit event
@@ -689,6 +689,8 @@ static int wince_submit_transfer(
689
689
  return wince_submit_control_or_bulk_transfer(itransfer);
690
690
  case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
691
691
  return wince_submit_iso_transfer(itransfer);
692
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
693
+ return LIBUSB_ERROR_NOT_SUPPORTED;
692
694
  default:
693
695
  usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
694
696
  return LIBUSB_ERROR_INVALID_PARAM;
@@ -801,6 +803,8 @@ static void wince_handle_callback (struct usbi_transfer *itransfer, uint32_t io_
801
803
  case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
802
804
  wince_transfer_callback (itransfer, io_result, io_size);
803
805
  break;
806
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
807
+ return LIBUSB_ERROR_NOT_SUPPORTED;
804
808
  default:
805
809
  usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
806
810
  }
@@ -1005,6 +1009,9 @@ const struct usbi_os_backend wince_backend = {
1005
1009
  wince_clear_halt,
1006
1010
  wince_reset_device,
1007
1011
 
1012
+ NULL, /* alloc_streams */
1013
+ NULL, /* free_streams */
1014
+
1008
1015
  wince_kernel_driver_active,
1009
1016
  wince_detach_kernel_driver,
1010
1017
  wince_attach_kernel_driver,
@@ -100,7 +100,8 @@ static int composite_copy_transfer_data(int sub_api, struct usbi_transfer *itran
100
100
  // Global variables
101
101
  uint64_t hires_frequency, hires_ticks_to_ps;
102
102
  const uint64_t epoch_time = UINT64_C(116444736000000000); // 1970.01.01 00:00:000 in MS Filetime
103
- enum windows_version windows_version = WINDOWS_UNSUPPORTED;
103
+ int windows_version = WINDOWS_UNDEFINED;
104
+ static char windows_version_str[128] = "Windows Undefined";
104
105
  // Concurrency
105
106
  static int concurrent_usage = -1;
106
107
  usbi_mutex_t autoclaim_lock;
@@ -209,7 +210,7 @@ static char* sanitize_path(const char* path)
209
210
  size = safe_strlen(path)+1;
210
211
  root_size = sizeof(root_prefix)-1;
211
212
 
212
- // Microsoft indiscriminatly uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes.
213
+ // Microsoft indiscriminately uses '\\?\', '\\.\', '##?#" or "##.#" for root prefixes.
213
214
  if (!((size > 3) && (((path[0] == '\\') && (path[1] == '\\') && (path[3] == '\\')) ||
214
215
  ((path[0] == '#') && (path[1] == '#') && (path[3] == '#'))))) {
215
216
  add_root = root_size;
@@ -221,7 +222,7 @@ static char* sanitize_path(const char* path)
221
222
 
222
223
  safe_strcpy(&ret_path[add_root], size-add_root, path);
223
224
 
224
- // Ensure consistancy with root prefix
225
+ // Ensure consistency with root prefix
225
226
  for (j=0; j<root_size; j++)
226
227
  ret_path[j] = root_prefix[j];
227
228
 
@@ -804,6 +805,118 @@ static void auto_release(struct usbi_transfer *itransfer)
804
805
  usbi_mutex_unlock(&autoclaim_lock);
805
806
  }
806
807
 
808
+ /* Windows version dtection */
809
+ static BOOL is_x64(void)
810
+ {
811
+ BOOL ret = FALSE;
812
+ // Detect if we're running a 32 or 64 bit system
813
+ if (sizeof(uintptr_t) < 8) {
814
+ DLL_LOAD_PREFIXED(Kernel32.dll, p, IsWow64Process, FALSE);
815
+ if (pIsWow64Process != NULL) {
816
+ (*pIsWow64Process)(GetCurrentProcess(), &ret);
817
+ }
818
+ } else {
819
+ ret = TRUE;
820
+ }
821
+ return ret;
822
+ }
823
+
824
+ static void get_windows_version(void)
825
+ {
826
+ OSVERSIONINFOEXA vi, vi2;
827
+ const char* w = 0;
828
+ const char* w64 = "32 bit";
829
+ char* vptr;
830
+ size_t vlen;
831
+ unsigned major, minor;
832
+ ULONGLONG major_equal, minor_equal;
833
+ BOOL ws;
834
+
835
+ memset(&vi, 0, sizeof(vi));
836
+ vi.dwOSVersionInfoSize = sizeof(vi);
837
+ if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
838
+ memset(&vi, 0, sizeof(vi));
839
+ vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
840
+ if (!GetVersionExA((OSVERSIONINFOA *)&vi))
841
+ return;
842
+ }
843
+
844
+ if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
845
+
846
+ if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) {
847
+ // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
848
+ // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx
849
+
850
+ major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
851
+ for (major = vi.dwMajorVersion; major <= 9; major++) {
852
+ memset(&vi2, 0, sizeof(vi2));
853
+ vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMajorVersion = major;
854
+ if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
855
+ continue;
856
+ if (vi.dwMajorVersion < major) {
857
+ vi.dwMajorVersion = major; vi.dwMinorVersion = 0;
858
+ }
859
+
860
+ minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
861
+ for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
862
+ memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2);
863
+ vi2.dwMinorVersion = minor;
864
+ if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
865
+ continue;
866
+ vi.dwMinorVersion = minor;
867
+ break;
868
+ }
869
+
870
+ break;
871
+ }
872
+ }
873
+
874
+ if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) {
875
+ ws = (vi.wProductType <= VER_NT_WORKSTATION);
876
+ windows_version = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
877
+ switch (windows_version) {
878
+ case 0x50: w = "2000";
879
+ break;
880
+ case 0x51: w = "XP";
881
+ break;
882
+ case 0x52: w = ("2003");
883
+ break;
884
+ case 0x60: w = (ws?"Vista":"2008");
885
+ break;
886
+ case 0x61: w = (ws?"7":"2008_R2");
887
+ break;
888
+ case 0x62: w = (ws?"8":"2012");
889
+ break;
890
+ case 0x63: w = (ws?"8.1":"2012_R2");
891
+ break;
892
+ case 0x64: w = (ws?"8.2":"2012_R3");
893
+ break;
894
+ default:
895
+ if (windows_version < 0x50)
896
+ windows_version = WINDOWS_UNSUPPORTED;
897
+ else
898
+ w = "9 or later";
899
+ break;
900
+ }
901
+ }
902
+ }
903
+
904
+ if (is_x64())
905
+ w64 = "64-bit";
906
+
907
+ vptr = &windows_version_str[sizeof("Windows ") - 1];
908
+ vlen = sizeof(windows_version_str) - sizeof("Windows ") - 1;
909
+ if (!w)
910
+ safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId==VER_PLATFORM_WIN32_NT?"NT":"??"),
911
+ (unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64);
912
+ else if (vi.wServicePackMinor)
913
+ safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64);
914
+ else if (vi.wServicePackMajor)
915
+ safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64);
916
+ else
917
+ safe_sprintf(vptr, vlen, "%s %s", w, w64);
918
+ }
919
+
807
920
  /*
808
921
  * init: libusb backend init function
809
922
  *
@@ -814,7 +927,6 @@ static void auto_release(struct usbi_transfer *itransfer)
814
927
  static int windows_init(struct libusb_context *ctx)
815
928
  {
816
929
  int i, r = LIBUSB_ERROR_OTHER;
817
- OSVERSIONINFO os_version;
818
930
  HANDLE semaphore;
819
931
  char sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID)
820
932
 
@@ -836,19 +948,8 @@ static int windows_init(struct libusb_context *ctx)
836
948
  // NB: concurrent usage supposes that init calls are equally balanced with
837
949
  // exit calls. If init is called more than exit, we will not exit properly
838
950
  if ( ++concurrent_usage == 0 ) { // First init?
839
- // Detect OS version
840
- memset(&os_version, 0, sizeof(OSVERSIONINFO));
841
- os_version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
842
- windows_version = WINDOWS_UNSUPPORTED;
843
- if ((GetVersionEx(&os_version) != 0) && (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT)) {
844
- if ((os_version.dwMajorVersion == 5) && (os_version.dwMinorVersion == 1)) {
845
- windows_version = WINDOWS_XP;
846
- } else if ((os_version.dwMajorVersion == 5) && (os_version.dwMinorVersion == 2)) {
847
- windows_version = WINDOWS_2003; // also includes XP 64
848
- } else if (os_version.dwMajorVersion >= 6) {
849
- windows_version = WINDOWS_VISTA_AND_LATER;
850
- }
851
- }
951
+ get_windows_version();
952
+ usbi_dbg(windows_version_str);
852
953
  if (windows_version == WINDOWS_UNSUPPORTED) {
853
954
  usbi_err(ctx, "This version of Windows is NOT supported");
854
955
  r = LIBUSB_ERROR_NOT_SUPPORTED;
@@ -1028,6 +1129,7 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle
1028
1129
 
1029
1130
  // Dummy call to get the required data size. Initial failures are reported as info rather
1030
1131
  // than error as they can occur for non-penalizing situations, such as with some hubs.
1132
+ // coverity[tainted_data_argument]
1031
1133
  if (!DeviceIoControl(hub_handle, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, &cd_buf_short, size,
1032
1134
  &cd_buf_short, size, &ret_size, NULL)) {
1033
1135
  usbi_info(ctx, "could not access configuration descriptor (dummy) for '%s': %s", device_id, windows_error_str(0));
@@ -1078,7 +1180,7 @@ static int cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handle
1078
1180
  // Cache the descriptor
1079
1181
  priv->config_descriptor[i] = (unsigned char*) malloc(cd_data->wTotalLength);
1080
1182
  if (priv->config_descriptor[i] == NULL)
1081
- return LIBUSB_ERROR_NO_MEM;
1183
+ LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1082
1184
  memcpy(priv->config_descriptor[i], cd_data, cd_data->wTotalLength);
1083
1185
  }
1084
1186
  return LIBUSB_SUCCESS;
@@ -1093,14 +1195,16 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
1093
1195
  HANDLE handle;
1094
1196
  DWORD size;
1095
1197
  USB_NODE_CONNECTION_INFORMATION_EX conn_info;
1198
+ USB_NODE_CONNECTION_INFORMATION_EX_V2 conn_info_v2;
1096
1199
  struct windows_device_priv *priv, *parent_priv;
1097
- struct libusb_context *ctx = DEVICE_CTX(dev);
1200
+ struct libusb_context *ctx;
1098
1201
  struct libusb_device* tmp_dev;
1099
1202
  unsigned i;
1100
1203
 
1101
1204
  if ((dev == NULL) || (parent_dev == NULL)) {
1102
1205
  return LIBUSB_ERROR_NOT_FOUND;
1103
1206
  }
1207
+ ctx = DEVICE_CTX(dev);
1104
1208
  priv = _device_priv(dev);
1105
1209
  parent_priv = _device_priv(parent_dev);
1106
1210
  if (parent_priv->apib->id != USB_API_HUB) {
@@ -1148,6 +1252,7 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
1148
1252
  }
1149
1253
  size = sizeof(conn_info);
1150
1254
  conn_info.ConnectionIndex = (ULONG)port_number;
1255
+ // coverity[tainted_data_argument]
1151
1256
  if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX, &conn_info, size,
1152
1257
  &conn_info, size, &size, NULL)) {
1153
1258
  usbi_warn(ctx, "could not get node connection information for device '%s': %s",
@@ -1169,6 +1274,23 @@ static int init_device(struct libusb_device* dev, struct libusb_device* parent_d
1169
1274
  dev->num_configurations = 0;
1170
1275
  priv->dev_descriptor.bNumConfigurations = 0;
1171
1276
  }
1277
+
1278
+ // In their great wisdom, Microsoft decided to BREAK the USB speed report between Windows 7 and Windows 8
1279
+ if (windows_version >= WINDOWS_8) {
1280
+ memset(&conn_info_v2, 0, sizeof(conn_info_v2));
1281
+ size = sizeof(conn_info_v2);
1282
+ conn_info_v2.ConnectionIndex = (ULONG)port_number;
1283
+ conn_info_v2.Length = size;
1284
+ conn_info_v2.SupportedUsbProtocols.Usb300 = 1;
1285
+ if (!DeviceIoControl(handle, IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX_V2,
1286
+ &conn_info_v2, size, &conn_info_v2, size, &size, NULL)) {
1287
+ usbi_warn(ctx, "could not get node connection information (V2) for device '%s': %s",
1288
+ device_id, windows_error_str(0));
1289
+ } else if (conn_info_v2.Flags.DeviceIsOperatingAtSuperSpeedOrHigher) {
1290
+ conn_info.Speed = 3;
1291
+ }
1292
+ }
1293
+
1172
1294
  safe_closehandle(handle);
1173
1295
 
1174
1296
  if (conn_info.DeviceAddress > UINT8_MAX) {
@@ -1246,7 +1368,7 @@ static void get_api_type(struct libusb_context *ctx, HDEVINFO *dev_info,
1246
1368
  for (k=0; k<3; k++) {
1247
1369
  j = get_sub_api(lookup[k].list, i);
1248
1370
  if (j >= 0) {
1249
- usbi_dbg("matched %s name against %s API",
1371
+ usbi_dbg("matched %s name against %s",
1250
1372
  lookup[k].designation, (i!=USB_API_WINUSBX)?usb_api_backend[i].designation:sub_api_name[j]);
1251
1373
  *api = i;
1252
1374
  *sub_api = j;
@@ -1553,7 +1675,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
1553
1675
  parent_priv = _device_priv(parent_dev);
1554
1676
  // virtual USB devices are also listed during GEN - don't process these yet
1555
1677
  if ( (pass == GEN_PASS) && (parent_priv->apib->id != USB_API_HUB) ) {
1556
- libusb_unref_device(parent_dev);
1678
+ libusb_unref_device(parent_dev);
1557
1679
  continue;
1558
1680
  }
1559
1681
  break;
@@ -1580,16 +1702,16 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
1580
1702
  usbi_dbg("found existing device for session [%X] (%d.%d)",
1581
1703
  session_id, dev->bus_number, dev->device_address);
1582
1704
  }
1583
- // Keep track of devices that need unref
1584
- unref_list[unref_cur++] = dev;
1585
- if (unref_cur >= unref_size) {
1586
- unref_size += 64;
1587
- unref_list = usbi_reallocf(unref_list, unref_size*sizeof(libusb_device*));
1588
- if (unref_list == NULL) {
1589
- usbi_err(ctx, "could not realloc list for unref - aborting.");
1590
- LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1591
- }
1592
- }
1705
+ // Keep track of devices that need unref
1706
+ unref_list[unref_cur++] = dev;
1707
+ if (unref_cur >= unref_size) {
1708
+ unref_size += 64;
1709
+ unref_list = usbi_reallocf(unref_list, unref_size*sizeof(libusb_device*));
1710
+ if (unref_list == NULL) {
1711
+ usbi_err(ctx, "could not realloc list for unref - aborting.");
1712
+ LOOP_BREAK(LIBUSB_ERROR_NO_MEM);
1713
+ }
1714
+ }
1593
1715
  priv = _device_priv(dev);
1594
1716
  }
1595
1717
 
@@ -1675,7 +1797,7 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
1675
1797
  break;
1676
1798
  }
1677
1799
  }
1678
- libusb_unref_device(parent_dev);
1800
+ libusb_unref_device(parent_dev);
1679
1801
  break;
1680
1802
  }
1681
1803
  }
@@ -1687,10 +1809,12 @@ static int windows_get_device_list(struct libusb_context *ctx, struct discovered
1687
1809
  }
1688
1810
 
1689
1811
  // Unref newly allocated devs
1690
- for (i=0; i<unref_cur; i++) {
1691
- safe_unref_device(unref_list[i]);
1812
+ if (unref_list != NULL) {
1813
+ for (i=0; i<unref_cur; i++) {
1814
+ safe_unref_device(unref_list[i]);
1815
+ }
1816
+ free(unref_list);
1692
1817
  }
1693
- safe_free(unref_list);
1694
1818
 
1695
1819
  return r;
1696
1820
  }
@@ -2019,6 +2143,8 @@ static int windows_submit_transfer(struct usbi_transfer *itransfer)
2019
2143
  return submit_bulk_transfer(itransfer);
2020
2144
  case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
2021
2145
  return submit_iso_transfer(itransfer);
2146
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2147
+ return LIBUSB_ERROR_NOT_SUPPORTED;
2022
2148
  default:
2023
2149
  usbi_err(TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type);
2024
2150
  return LIBUSB_ERROR_INVALID_PARAM;
@@ -2052,6 +2178,8 @@ static int windows_cancel_transfer(struct usbi_transfer *itransfer)
2052
2178
  case LIBUSB_TRANSFER_TYPE_INTERRUPT:
2053
2179
  case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
2054
2180
  return windows_abort_transfers(itransfer);
2181
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2182
+ return LIBUSB_ERROR_NOT_SUPPORTED;
2055
2183
  default:
2056
2184
  usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
2057
2185
  return LIBUSB_ERROR_INVALID_PARAM;
@@ -2111,6 +2239,9 @@ static void windows_handle_callback (struct usbi_transfer *itransfer, uint32_t i
2111
2239
  case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
2112
2240
  windows_transfer_callback (itransfer, io_result, io_size);
2113
2241
  break;
2242
+ case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2243
+ usbi_warn(ITRANSFER_CTX(itransfer), "bulk stream transfers are not yet supported on this platform");
2244
+ break;
2114
2245
  default:
2115
2246
  usbi_err(ITRANSFER_CTX(itransfer), "unknown endpoint type %d", transfer->type);
2116
2247
  }
@@ -2222,7 +2353,7 @@ unsigned __stdcall windows_clock_gettime_threaded(void* param)
2222
2353
  case 0:
2223
2354
  WaitForSingleObject(timer_mutex, INFINITE);
2224
2355
  // Requests to this thread are for hires always
2225
- if (QueryPerformanceCounter(&hires_counter) != 0) {
2356
+ if ((QueryPerformanceCounter(&hires_counter) != 0) && (hires_frequency != 0)) {
2226
2357
  timer_tp.tv_sec = (long)(hires_counter.QuadPart / hires_frequency);
2227
2358
  timer_tp.tv_nsec = (long)(((hires_counter.QuadPart % hires_frequency)/1000) * hires_ticks_to_ps);
2228
2359
  } else {
@@ -2317,6 +2448,9 @@ const struct usbi_os_backend windows_backend = {
2317
2448
  windows_clear_halt,
2318
2449
  windows_reset_device,
2319
2450
 
2451
+ NULL, /* alloc_streams */
2452
+ NULL, /* free_streams */
2453
+
2320
2454
  windows_kernel_driver_active,
2321
2455
  windows_detach_kernel_driver,
2322
2456
  windows_attach_kernel_driver,
@@ -2395,7 +2529,7 @@ static int common_configure_endpoints(int sub_api, struct libusb_device_handle *
2395
2529
  return LIBUSB_SUCCESS;
2396
2530
  }
2397
2531
  // These names must be uppercase
2398
- const char* hub_driver_names[] = {"USBHUB", "USBHUB3", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB"};
2532
+ const char* hub_driver_names[] = {"USBHUB", "USBHUB3", "USB3HUB", "NUSB3HUB", "RUSB3HUB", "FLXHCIH", "TIHUB3", "ETRONHUB3", "VIAHUB3", "ASMTHUB3", "IUSB3HUB", "VUSB3HUB", "AMDHUB30"};
2399
2533
  const char* composite_driver_names[] = {"USBCCGP"};
2400
2534
  const char* winusbx_driver_names[] = WINUSBX_DRV_NAMES;
2401
2535
  const char* hid_driver_names[] = {"HIDUSB", "MOUHID", "KBDHID"};
@@ -2755,11 +2889,10 @@ static int winusbx_claim_interface(int sub_api, struct libusb_device_handle *dev
2755
2889
  usbi_err(ctx, "could not open device %s: %s", filter_path, windows_error_str(0));
2756
2890
  } else {
2757
2891
  WinUSBX[sub_api].Free(winusb_handle);
2758
- if (!WinUSBX[sub_api].Initialize(file_handle, &winusb_handle)) {
2759
- continue;
2760
- }
2761
- found_filter = true;
2762
- break;
2892
+ if (WinUSBX[sub_api].Initialize(file_handle, &winusb_handle))
2893
+ found_filter = true;
2894
+ else
2895
+ usbi_err(ctx, "could not initialize filter driver for %s", filter_path);
2763
2896
  }
2764
2897
  }
2765
2898
  }