libusb 0.3.4 → 0.4.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 (136) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Gemfile +1 -0
  5. data/History.md +10 -0
  6. data/README.md +19 -6
  7. data/Rakefile +1 -1
  8. data/ext/extconf.rb +17 -1
  9. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/AUTHORS +18 -6
  10. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/COPYING +0 -0
  11. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ChangeLog +58 -1
  12. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/INSTALL +0 -0
  13. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.am +6 -1
  14. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.in +248 -174
  15. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/NEWS +2 -2
  16. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/PORTING +0 -0
  17. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/README +2 -1
  18. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/TODO +0 -0
  19. data/ext/libusbx-1.0.17/Xcode/common.xcconfig +40 -0
  20. data/ext/libusbx-1.0.17/Xcode/config.h +28 -0
  21. data/ext/libusbx-1.0.17/Xcode/debug.xcconfig +29 -0
  22. data/ext/libusbx-1.0.17/Xcode/libusbx.xcconfig +21 -0
  23. data/ext/libusbx-1.0.17/Xcode/libusbx.xcodeproj/project.pbxproj +864 -0
  24. data/ext/libusbx-1.0.17/Xcode/libusbx_debug.xcconfig +21 -0
  25. data/ext/libusbx-1.0.17/Xcode/libusbx_release.xcconfig +21 -0
  26. data/ext/libusbx-1.0.17/Xcode/release.xcconfig +29 -0
  27. data/ext/libusbx-1.0.17/aclocal.m4 +1112 -0
  28. data/ext/libusbx-1.0.17/android/README +114 -0
  29. data/ext/libusbx-1.0.17/android/config.h +90 -0
  30. data/ext/libusbx-1.0.17/android/jni/Android.mk +23 -0
  31. data/ext/libusbx-1.0.17/android/jni/Application.mk +19 -0
  32. data/ext/libusbx-1.0.17/android/jni/examples.mk +134 -0
  33. data/ext/libusbx-1.0.17/android/jni/libusb.mk +54 -0
  34. data/ext/libusbx-1.0.17/android/jni/tests.mk +56 -0
  35. data/ext/libusbx-1.0.17/compile +347 -0
  36. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.guess +164 -130
  37. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.h.in +37 -1
  38. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.sub +174 -89
  39. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure +723 -302
  40. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure.ac +71 -20
  41. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/depcomp +345 -185
  42. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.am +0 -0
  43. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.in +95 -32
  44. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/doxygen.cfg.in +1 -1
  45. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.am +5 -4
  46. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.in +208 -104
  47. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp.c +1 -1
  48. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp_threaded.c +1 -1
  49. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.c +188 -8
  50. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.h +18 -5
  51. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/fxload.c +90 -64
  52. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.c +0 -0
  53. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.h +0 -0
  54. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt1.c +0 -0
  55. data/ext/libusbx-1.0.17/examples/hotplugtest.c +97 -0
  56. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/listdevs.c +12 -4
  57. data/ext/libusbx-1.0.17/examples/sam3u_benchmark.c +193 -0
  58. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/xusb.c +106 -49
  59. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/install-sh +21 -14
  60. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb-1.0.pc.in +1 -1
  61. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/Makefile.am +29 -10
  62. data/ext/libusbx-1.0.17/libusb/Makefile.in +914 -0
  63. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/core.c +378 -87
  64. data/ext/libusbx-1.0.17/libusb/descriptor.c +1199 -0
  65. data/ext/libusbx-1.0.17/libusb/hotplug.c +322 -0
  66. data/ext/libusbx-1.0.17/libusb/hotplug.h +82 -0
  67. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/io.c +182 -62
  68. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.def +32 -0
  69. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.rc +2 -0
  70. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb.h +481 -32
  71. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusbi.h +135 -38
  72. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.c +591 -496
  73. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.h +39 -46
  74. data/ext/libusbx-1.0.17/libusb/os/linux_netlink.c +345 -0
  75. data/ext/libusbx-1.0.17/libusb/os/linux_udev.c +306 -0
  76. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.c +653 -617
  77. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.h +32 -0
  78. data/ext/{libusbx-1.0.14/libusb/os/openbsd_usb.c → libusbx-1.0.17/libusb/os/netbsd_usb.c} +70 -63
  79. data/ext/libusbx-1.0.17/libusb/os/openbsd_usb.c +823 -0
  80. data/ext/libusbx-1.0.17/libusb/os/poll_posix.c +51 -0
  81. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_posix.h +2 -1
  82. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.c +85 -106
  83. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.h +14 -3
  84. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.c +3 -1
  85. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.h +0 -0
  86. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.c +6 -5
  87. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.h +0 -0
  88. data/ext/libusbx-1.0.17/libusb/os/wince_usb.c +1026 -0
  89. data/ext/libusbx-1.0.17/libusb/os/wince_usb.h +131 -0
  90. data/ext/libusbx-1.0.17/libusb/os/windows_common.h +108 -0
  91. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.c +92 -57
  92. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.h +2 -63
  93. data/ext/libusbx-1.0.17/libusb/strerror.c +184 -0
  94. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/sync.c +24 -38
  95. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/version.h +1 -1
  96. data/ext/libusbx-1.0.17/libusb/version_nano.h +1 -0
  97. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ltmain.sh +60 -41
  98. data/ext/{libusbx-1.0.14/aclocal.m4 → libusbx-1.0.17/m4/libtool.m4} +229 -1723
  99. data/ext/libusbx-1.0.17/m4/ltoptions.m4 +384 -0
  100. data/ext/libusbx-1.0.17/m4/ltsugar.m4 +123 -0
  101. data/ext/libusbx-1.0.17/m4/ltversion.m4 +23 -0
  102. data/ext/libusbx-1.0.17/m4/lt~obsolete.m4 +98 -0
  103. data/ext/libusbx-1.0.17/missing +215 -0
  104. data/ext/libusbx-1.0.17/tests/Makefile.am +6 -0
  105. data/ext/libusbx-1.0.17/tests/Makefile.in +583 -0
  106. data/ext/libusbx-1.0.17/tests/libusbx_testlib.h +107 -0
  107. data/ext/libusbx-1.0.17/tests/stress.c +160 -0
  108. data/ext/libusbx-1.0.17/tests/testlib.c +276 -0
  109. data/lib/libusb.rb +4 -0
  110. data/lib/libusb/call.rb +43 -1
  111. data/lib/libusb/constants.rb +5 -0
  112. data/lib/libusb/context.rb +100 -0
  113. data/lib/libusb/dev_handle.rb +27 -0
  114. data/lib/libusb/device.rb +10 -4
  115. data/lib/libusb/version_gem.rb +1 -1
  116. data/test/test_libusb_capability.rb +2 -2
  117. data/test/test_libusb_compat.rb +2 -2
  118. data/test/test_libusb_compat_mass_storage.rb +2 -2
  119. data/test/test_libusb_descriptors.rb +4 -2
  120. data/test/test_libusb_event_machine.rb +2 -2
  121. data/test/test_libusb_gc.rb +2 -2
  122. data/test/test_libusb_hotplug.rb +115 -0
  123. data/test/test_libusb_iso_transfer.rb +3 -3
  124. data/test/test_libusb_mass_storage.rb +6 -16
  125. data/test/test_libusb_mass_storage2.rb +26 -3
  126. data/test/test_libusb_structs.rb +2 -2
  127. data/test/test_libusb_threads.rb +2 -2
  128. data/test/test_libusb_version.rb +2 -2
  129. metadata +127 -68
  130. metadata.gz.sig +0 -0
  131. data/ext/libusbx-1.0.14/THANKS +0 -7
  132. data/ext/libusbx-1.0.14/compile +0 -143
  133. data/ext/libusbx-1.0.14/libusb/Makefile.in +0 -721
  134. data/ext/libusbx-1.0.14/libusb/descriptor.c +0 -731
  135. data/ext/libusbx-1.0.14/libusb/version_nano.h +0 -1
  136. data/ext/libusbx-1.0.14/missing +0 -376
@@ -21,7 +21,9 @@
21
21
  #ifndef LIBUSBI_H
22
22
  #define LIBUSBI_H
23
23
 
24
- #include <config.h>
24
+ #include "config.h"
25
+
26
+ #include <stdlib.h>
25
27
 
26
28
  #include <stddef.h>
27
29
  #include <stdint.h>
@@ -31,7 +33,10 @@
31
33
  #include <poll.h>
32
34
  #endif
33
35
 
34
- #include <libusb.h>
36
+ #ifdef HAVE_MISSING_H
37
+ #include "missing.h"
38
+ #endif
39
+ #include "libusb.h"
35
40
  #include "version.h"
36
41
 
37
42
  /* Inside the libusbx code, mark all public functions as follows:
@@ -49,26 +54,39 @@
49
54
  #define USB_MAXINTERFACES 32
50
55
  #define USB_MAXCONFIG 8
51
56
 
57
+ /* Backend specific capabilities */
58
+ #define USBI_CAP_HAS_HID_ACCESS 0x00010000
59
+ #define USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER 0x00020000
60
+
61
+ /* Maximum number of bytes in a log line */
62
+ #define USBI_MAX_LOG_LEN 1024
63
+ /* Terminator for log lines */
64
+ #define USBI_LOG_LINE_END "\n"
65
+
52
66
  /* The following is used to silence warnings for unused variables */
53
- #define UNUSED(var) (void)(var)
67
+ #define UNUSED(var) do { (void)(var); } while(0)
68
+
69
+ #if !defined(ARRAYSIZE)
70
+ #define ARRAYSIZE(array) (sizeof(array)/sizeof(array[0]))
71
+ #endif
54
72
 
55
73
  struct list_head {
56
74
  struct list_head *prev, *next;
57
75
  };
58
76
 
59
77
  /* Get an entry from the list
60
- * ptr - the address of this list_head element in "type"
61
- * type - the data type that contains "member"
62
- * member - the list_head element in "type"
78
+ * ptr - the address of this list_head element in "type"
79
+ * type - the data type that contains "member"
80
+ * member - the list_head element in "type"
63
81
  */
64
82
  #define list_entry(ptr, type, member) \
65
- ((type *)((uintptr_t)(ptr) - (uintptr_t)(&((type *)0L)->member)))
83
+ ((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member)))
66
84
 
67
85
  /* Get each entry from a list
68
- * pos - A structure pointer has a "member" element
69
- * head - list head
70
- * member - the list_head element in "pos"
71
- * type - the type of the first parameter
86
+ * pos - A structure pointer has a "member" element
87
+ * head - list head
88
+ * member - the list_head element in "pos"
89
+ * type - the type of the first parameter
72
90
  */
73
91
  #define list_for_each_entry(pos, head, member, type) \
74
92
  for (pos = list_entry((head)->next, type, member); \
@@ -192,32 +210,13 @@ static inline void usbi_dbg(const char *format, ...)
192
210
  #define IS_XFERIN(xfer) (0 != ((xfer)->endpoint & LIBUSB_ENDPOINT_IN))
193
211
  #define IS_XFEROUT(xfer) (!IS_XFERIN(xfer))
194
212
 
195
- /* Internal abstractions for thread synchronization and poll */
213
+ /* Internal abstraction for thread synchronization */
196
214
  #if defined(THREADS_POSIX)
197
- #include <os/threads_posix.h>
198
- #elif defined(OS_WINDOWS)
215
+ #include "os/threads_posix.h"
216
+ #elif defined(OS_WINDOWS) || defined(OS_WINCE)
199
217
  #include <os/threads_windows.h>
200
218
  #endif
201
219
 
202
- #if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD)
203
- #include <unistd.h>
204
- #include <os/poll_posix.h>
205
- #elif defined(OS_WINDOWS)
206
- #include <os/poll_windows.h>
207
- #endif
208
-
209
- #if defined(OS_WINDOWS) && !defined(__GCC__)
210
- #undef HAVE_GETTIMEOFDAY
211
- int usbi_gettimeofday(struct timeval *tp, void *tzp);
212
- #define LIBUSB_GETTIMEOFDAY_WIN32
213
- #define HAVE_USBI_GETTIMEOFDAY
214
- #else
215
- #ifdef HAVE_GETTIMEOFDAY
216
- #define usbi_gettimeofday(tv, tz) gettimeofday((tv), (tz))
217
- #define HAVE_USBI_GETTIMEOFDAY
218
- #endif
219
- #endif
220
-
221
220
  extern struct libusb_context *usbi_default_context;
222
221
 
223
222
  struct libusb_context {
@@ -236,6 +235,11 @@ struct libusb_context {
236
235
  struct list_head open_devs;
237
236
  usbi_mutex_t open_devs_lock;
238
237
 
238
+ /* A list of registered hotplug callbacks */
239
+ struct list_head hotplug_cbs;
240
+ usbi_mutex_t hotplug_cbs_lock;
241
+ int hotplug_pipe[2];
242
+
239
243
  /* this is a list of in-flight transfer handles, sorted by timeout
240
244
  * expiration. URBs to timeout the soonest are placed at the beginning of
241
245
  * the list, URBs that will time out later are placed after, and urbs with
@@ -273,6 +277,8 @@ struct libusb_context {
273
277
  * this timerfd is maintained to trigger on the next pending timeout */
274
278
  int timerfd;
275
279
  #endif
280
+
281
+ struct list_head list;
276
282
  };
277
283
 
278
284
  #ifdef USBI_TIMERFD_AVAILABLE
@@ -298,7 +304,17 @@ struct libusb_device {
298
304
 
299
305
  struct list_head list;
300
306
  unsigned long session_data;
301
- unsigned char os_priv[0];
307
+
308
+ struct libusb_device_descriptor device_descriptor;
309
+ int attached;
310
+
311
+ unsigned char os_priv
312
+ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
313
+ [] /* valid C99 code */
314
+ #else
315
+ [0] /* non-standard, but usually working code */
316
+ #endif
317
+ ;
302
318
  };
303
319
 
304
320
  struct libusb_device_handle {
@@ -308,7 +324,14 @@ struct libusb_device_handle {
308
324
 
309
325
  struct list_head list;
310
326
  struct libusb_device *dev;
311
- unsigned char os_priv[0];
327
+ int auto_detach_kernel_driver;
328
+ unsigned char os_priv
329
+ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
330
+ [] /* valid C99 code */
331
+ #else
332
+ [0] /* non-standard, but usually working code */
333
+ #endif
334
+ ;
312
335
  };
313
336
 
314
337
  enum {
@@ -402,12 +425,35 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
402
425
  enum libusb_transfer_status status);
403
426
  int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer);
404
427
 
405
- int usbi_parse_descriptor(unsigned char *source, const char *descriptor,
428
+ int usbi_parse_descriptor(const unsigned char *source, const char *descriptor,
406
429
  void *dest, int host_endian);
430
+ int usbi_device_cache_descriptor(libusb_device *dev);
407
431
  int usbi_get_config_index_by_value(struct libusb_device *dev,
408
432
  uint8_t bConfigurationValue, int *idx);
409
433
 
410
- /* polling */
434
+ void usbi_connect_device (struct libusb_device *dev);
435
+ void usbi_disconnect_device (struct libusb_device *dev);
436
+
437
+ /* Internal abstraction for poll (needs struct usbi_transfer on Windows) */
438
+ #if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD)
439
+ #include <unistd.h>
440
+ #include "os/poll_posix.h"
441
+ #elif defined(OS_WINDOWS) || defined(OS_WINCE)
442
+ #include "os/poll_windows.h"
443
+ #endif
444
+
445
+ #if (defined(OS_WINDOWS) || defined(OS_WINCE)) && !defined(__GNUC__)
446
+ #define snprintf _snprintf
447
+ #define vsnprintf _vsnprintf
448
+ int usbi_gettimeofday(struct timeval *tp, void *tzp);
449
+ #define LIBUSB_GETTIMEOFDAY_WIN32
450
+ #define HAVE_USBI_GETTIMEOFDAY
451
+ #else
452
+ #ifdef HAVE_GETTIMEOFDAY
453
+ #define usbi_gettimeofday(tv, tz) gettimeofday((tv), (tz))
454
+ #define HAVE_USBI_GETTIMEOFDAY
455
+ #endif
456
+ #endif
411
457
 
412
458
  struct usbi_pollfd {
413
459
  /* must come first */
@@ -430,7 +476,13 @@ void usbi_fd_notification(struct libusb_context *ctx);
430
476
  struct discovered_devs {
431
477
  size_t len;
432
478
  size_t capacity;
433
- struct libusb_device *devices[0];
479
+ struct libusb_device *devices
480
+ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
481
+ [] /* valid C99 code */
482
+ #else
483
+ [0] /* non-standard, but usually working code */
484
+ #endif
485
+ ;
434
486
  };
435
487
 
436
488
  struct discovered_devs *discovered_devs_append(
@@ -444,6 +496,9 @@ struct usbi_os_backend {
444
496
  /* A human-readable name for your backend, e.g. "Linux usbfs" */
445
497
  const char *name;
446
498
 
499
+ /* Binary mask for backend specific capabilities */
500
+ uint32_t caps;
501
+
447
502
  /* Perform initialization of your backend. You might use this function
448
503
  * to determine specific capabilities of the system, allocate required
449
504
  * data structures for later, etc.
@@ -509,11 +564,30 @@ struct usbi_os_backend {
509
564
  * This function is executed when the user wishes to retrieve a list
510
565
  * of USB devices connected to the system.
511
566
  *
567
+ * If the backend has hotplug support, this function is not used!
568
+ *
512
569
  * Return 0 on success, or a LIBUSB_ERROR code on failure.
513
570
  */
514
571
  int (*get_device_list)(struct libusb_context *ctx,
515
572
  struct discovered_devs **discdevs);
516
573
 
574
+ /* Apps which were written before hotplug support, may listen for
575
+ * hotplug events on their own and call libusb_get_device_list on
576
+ * device addition. In this case libusb_get_device_list will likely
577
+ * return a list without the new device in there, as the hotplug
578
+ * event thread will still be busy enumerating the device, which may
579
+ * take a while, or may not even have seen the event yet.
580
+ *
581
+ * To avoid this libusb_get_device_list will call this optional
582
+ * function for backends with hotplug support before copying
583
+ * ctx->usb_devs to the user. In this function the backend should
584
+ * ensure any pending hotplug events are fully processed before
585
+ * returning.
586
+ *
587
+ * Optional, should be implemented by backends with hotplug support.
588
+ */
589
+ void (*hotplug_poll)(void);
590
+
517
591
  /* Open a device for I/O and other USB operations. The device handle
518
592
  * is preallocated for you, you can retrieve the device in question
519
593
  * through handle->dev.
@@ -623,6 +697,22 @@ struct usbi_os_backend {
623
697
  uint8_t config_index, unsigned char *buffer, size_t len,
624
698
  int *host_endian);
625
699
 
700
+ /* Like get_config_descriptor but then by bConfigurationValue instead
701
+ * of by index.
702
+ *
703
+ * Optional, if not present the core will call get_config_descriptor
704
+ * for all configs until it finds the desired bConfigurationValue.
705
+ *
706
+ * Returns a pointer to the raw-descriptor in *buffer, this memory
707
+ * is valid as long as device is valid.
708
+ *
709
+ * Returns the length of the returned raw-descriptor on success,
710
+ * or a LIBUSB_ERROR code on failure.
711
+ */
712
+ int (*get_config_descriptor_by_value)(struct libusb_device *device,
713
+ uint8_t bConfigurationValue, unsigned char **buffer,
714
+ int *host_endian);
715
+
626
716
  /* Get the bConfigurationValue for the active configuration for a device.
627
717
  * Optional. This should only be implemented if you can retrieve it from
628
718
  * cache (don't generate I/O).
@@ -806,6 +896,8 @@ struct usbi_os_backend {
806
896
  *
807
897
  * This function must not block.
808
898
  *
899
+ * This function gets called with the flying_transfers_lock locked!
900
+ *
809
901
  * Return:
810
902
  * - 0 on success
811
903
  * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected
@@ -905,6 +997,11 @@ extern const struct usbi_os_backend * const usbi_backend;
905
997
  extern const struct usbi_os_backend linux_usbfs_backend;
906
998
  extern const struct usbi_os_backend darwin_backend;
907
999
  extern const struct usbi_os_backend openbsd_backend;
1000
+ extern const struct usbi_os_backend netbsd_backend;
908
1001
  extern const struct usbi_os_backend windows_backend;
1002
+ extern const struct usbi_os_backend wince_backend;
1003
+
1004
+ extern struct list_head active_contexts_list;
1005
+ extern usbi_mutex_static_t active_contexts_lock;
909
1006
 
910
1007
  #endif
@@ -1,6 +1,7 @@
1
+ /* -*- Mode: C; indent-tabs-mode:nil -*- */
1
2
  /*
2
3
  * darwin backend for libusbx 1.0
3
- * Copyright © 2008-2011 Nathan Hjelm <hjelmn@users.sourceforge.net>
4
+ * Copyright © 2008-2013 Nathan Hjelm <hjelmn@users.sourceforge.net>
4
5
  *
5
6
  * This library is free software; you can redistribute it and/or
6
7
  * modify it under the terms of the GNU Lesser General Public
@@ -17,19 +18,16 @@
17
18
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19
  */
19
20
 
20
- #include <config.h>
21
+ #include "config.h"
21
22
  #include <ctype.h>
22
- #include <dirent.h>
23
23
  #include <errno.h>
24
- #include <fcntl.h>
25
24
  #include <pthread.h>
26
25
  #include <stdio.h>
27
26
  #include <stdlib.h>
28
27
  #include <string.h>
29
- #include <sys/ioctl.h>
30
- #include <sys/stat.h>
31
28
  #include <sys/types.h>
32
29
  #include <unistd.h>
30
+ #include <fcntl.h>
33
31
  #include <libkern/OSAtomic.h>
34
32
 
35
33
  #include <mach/clock.h>
@@ -42,22 +40,23 @@
42
40
  #include <objc/objc-auto.h>
43
41
  #endif
44
42
 
45
- #include <IOKit/IOCFBundle.h>
46
- #include <IOKit/usb/IOUSBLib.h>
47
- #include <IOKit/IOCFPlugIn.h>
48
-
49
43
  #include "darwin_usb.h"
50
44
 
51
45
  /* async event thread */
52
- static pthread_mutex_t libusb_darwin_at_mutex;
53
- static pthread_cond_t libusb_darwin_at_cond;
46
+ static pthread_mutex_t libusb_darwin_at_mutex = PTHREAD_MUTEX_INITIALIZER;
47
+ static pthread_cond_t libusb_darwin_at_cond = PTHREAD_COND_INITIALIZER;
54
48
 
55
49
  static clock_serv_t clock_realtime;
56
50
  static clock_serv_t clock_monotonic;
57
51
 
58
- static CFRunLoopRef libusb_darwin_acfl = NULL; /* async cf loop */
52
+ static CFRunLoopRef libusb_darwin_acfl = NULL; /* event cf loop */
59
53
  static volatile int32_t initCount = 0;
60
54
 
55
+ static usbi_mutex_t darwin_cached_devices_lock = PTHREAD_MUTEX_INITIALIZER;
56
+ static struct list_head darwin_cached_devices = {&darwin_cached_devices, &darwin_cached_devices};
57
+
58
+ #define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev))
59
+
61
60
  /* async event thread */
62
61
  static pthread_t libusb_darwin_at;
63
62
 
@@ -67,7 +66,10 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int
67
66
  static int darwin_reset_device(struct libusb_device_handle *dev_handle);
68
67
  static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0);
69
68
 
70
- #ifdef ENABLE_LOGGING
69
+ static int darwin_scan_devices(struct libusb_context *ctx);
70
+ static int process_new_device (struct libusb_context *ctx, io_service_t service);
71
+
72
+ #if defined(ENABLE_LOGGING)
71
73
  static const char *darwin_error_str (int result) {
72
74
  switch (result) {
73
75
  case kIOReturnSuccess:
@@ -96,6 +98,10 @@ static const char *darwin_error_str (int result) {
96
98
  return "data overrun";
97
99
  case kIOReturnCannotWire:
98
100
  return "physical memory can not be wired down";
101
+ case kIOReturnNoResources:
102
+ return "out of resources";
103
+ case kIOUSBHighSpeedSplitError:
104
+ return "high speed split error";
99
105
  default:
100
106
  return "unknown error";
101
107
  }
@@ -127,6 +133,21 @@ static int darwin_to_libusb (int result) {
127
133
  }
128
134
  }
129
135
 
136
+ /* this function must be called with the darwin_cached_devices_lock held */
137
+ static void darwin_deref_cached_device(struct darwin_cached_device *cached_dev) {
138
+ cached_dev->refcount--;
139
+ /* free the device and remove it from the cache */
140
+ if (0 == cached_dev->refcount) {
141
+ list_del(&cached_dev->list);
142
+
143
+ (*(cached_dev->device))->Release(cached_dev->device);
144
+ free (cached_dev);
145
+ }
146
+ }
147
+
148
+ static void darwin_ref_cached_device(struct darwin_cached_device *cached_dev) {
149
+ cached_dev->refcount++;
150
+ }
130
151
 
131
152
  static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, uint8_t *pipep, uint8_t *ifcp) {
132
153
  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
@@ -143,12 +164,12 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
143
164
 
144
165
  if (dev_handle->claimed_interfaces & (1 << iface)) {
145
166
  for (i = 0 ; i < cInterface->num_endpoints ; i++) {
146
- if (cInterface->endpoint_addrs[i] == ep) {
147
- *pipep = i + 1;
148
- *ifcp = iface;
149
- usbi_dbg ("pipe %d on interface %d matches", *pipep, *ifcp);
150
- return 0;
151
- }
167
+ if (cInterface->endpoint_addrs[i] == ep) {
168
+ *pipep = i + 1;
169
+ *ifcp = iface;
170
+ usbi_dbg ("pipe %d on interface %d matches", *pipep, *ifcp);
171
+ return 0;
172
+ }
152
173
  }
153
174
  }
154
175
  }
@@ -159,7 +180,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui
159
180
  return -1;
160
181
  }
161
182
 
162
- static int usb_setup_device_iterator (io_iterator_t *deviceIterator, long location) {
183
+ static int usb_setup_device_iterator (io_iterator_t *deviceIterator, UInt32 location) {
163
184
  CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
164
185
 
165
186
  if (!matchingDict)
@@ -171,7 +192,9 @@ static int usb_setup_device_iterator (io_iterator_t *deviceIterator, long locati
171
192
  &kCFTypeDictionaryValueCallBacks);
172
193
 
173
194
  if (propertyMatchDict) {
174
- CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberLongType, &location);
195
+ /* there are no unsigned CFNumber types so treat the value as signed. the os seems to do this
196
+ internally (CFNumberType of locationID is 3) */
197
+ CFTypeRef locationCF = CFNumberCreate (NULL, kCFNumberSInt32Type, &location);
175
198
 
176
199
  CFDictionarySetValue (propertyMatchDict, CFSTR(kUSBDevicePropertyLocationID), locationCF);
177
200
  /* release our reference to the CFNumber (CFDictionarySetValue retains it) */
@@ -187,6 +210,7 @@ static int usb_setup_device_iterator (io_iterator_t *deviceIterator, long locati
187
210
  return IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, deviceIterator);
188
211
  }
189
212
 
213
+ /* Returns 1 on success, 0 on failure. */
190
214
  static int get_ioregistry_value_number (io_service_t service, CFStringRef property, CFNumberType type, void *p) {
191
215
  CFTypeRef cfNumber = IORegistryEntryCreateCFProperty (service, property, kCFAllocatorDefault, 0);
192
216
  int ret = 0;
@@ -202,134 +226,77 @@ static int get_ioregistry_value_number (io_service_t service, CFStringRef proper
202
226
  return ret;
203
227
  }
204
228
 
205
- static usb_device_t **usb_get_next_device (io_iterator_t deviceIterator, UInt32 *locationp, UInt8 *portp, UInt32 *parent_locationp) {
229
+ static usb_device_t **darwin_device_from_service (io_service_t service)
230
+ {
206
231
  io_cf_plugin_ref_t *plugInInterface = NULL;
207
232
  usb_device_t **device;
208
- io_service_t usbDevice, parent;
209
233
  kern_return_t result;
210
234
  SInt32 score;
211
235
 
212
- if (!IOIteratorIsValid (deviceIterator))
213
- return NULL;
214
-
215
-
216
- while ((usbDevice = IOIteratorNext(deviceIterator))) {
217
- result = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID,
218
- kIOCFPlugInInterfaceID, &plugInInterface,
219
- &score);
220
-
221
- /* we are done with the usb_device_t */
222
- (void)IOObjectRelease(usbDevice);
236
+ result = IOCreatePlugInInterfaceForService(service, kIOUSBDeviceUserClientTypeID,
237
+ kIOCFPlugInInterfaceID, &plugInInterface,
238
+ &score);
223
239
 
224
- if (portp) {
225
- *portp = 0;
226
- (void) get_ioregistry_value_number (usbDevice, CFSTR("PortNum"), kCFNumberSInt8Type, portp);
227
- }
228
-
229
- if (parent_locationp) {
230
- *parent_locationp = 0;
231
-
232
- result = IORegistryEntryGetParentEntry (usbDevice, kIOUSBPlane, &parent);
233
-
234
- if (kIOReturnSuccess == result) {
235
- (void) get_ioregistry_value_number (parent, CFSTR("locationID"), kCFNumberLongType, parent_locationp);
236
- }
237
- }
238
-
239
- if (kIOReturnSuccess == result && plugInInterface)
240
- break;
241
-
242
- usbi_dbg ("libusb/darwin.c usb_get_next_device: could not set up plugin for service: %s\n", darwin_error_str (result));
243
- }
244
-
245
- if (!usbDevice)
240
+ if (kIOReturnSuccess != result || !plugInInterface) {
241
+ usbi_dbg ("could not set up plugin for service: %s\n", darwin_error_str (result));
246
242
  return NULL;
243
+ }
247
244
 
248
245
  (void)(*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(DeviceInterfaceID),
249
- (LPVOID)&device);
250
-
251
- (*plugInInterface)->Stop(plugInInterface);
252
- IODestroyPlugInInterface (plugInInterface);
253
-
254
- /* get the location from the device */
255
- if (locationp)
256
- (*(device))->GetLocationID(device, locationp);
246
+ (LPVOID)&device);
247
+ /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
248
+ (*plugInInterface)->Release (plugInInterface);
257
249
 
258
250
  return device;
259
251
  }
260
252
 
261
- static kern_return_t darwin_get_device (uint32_t dev_location, usb_device_t ***darwin_device) {
262
- kern_return_t kresult;
263
- UInt32 location;
264
- io_iterator_t deviceIterator;
253
+ static void darwin_devices_attached (void *ptr, io_iterator_t add_devices) {
254
+ struct libusb_context *ctx;
255
+ io_service_t service;
265
256
 
266
- kresult = usb_setup_device_iterator (&deviceIterator, dev_location);
267
- if (kresult)
268
- return kresult;
257
+ usbi_mutex_lock(&active_contexts_lock);
269
258
 
270
- /* This port of libusb uses locations to keep track of devices. */
271
- while ((*darwin_device = usb_get_next_device (deviceIterator, &location, NULL, NULL)) != NULL) {
272
- if (location == dev_location)
273
- break;
259
+ while ((service = IOIteratorNext(add_devices))) {
260
+ /* add this device to each active context's device list */
261
+ list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
262
+ process_new_device (ctx, service);;
263
+ }
274
264
 
275
- (**darwin_device)->Release(*darwin_device);
265
+ IOObjectRelease(service);
276
266
  }
277
267
 
278
- IOObjectRelease (deviceIterator);
279
-
280
- if (!(*darwin_device))
281
- return kIOReturnNoDevice;
282
-
283
- return kIOReturnSuccess;
268
+ usbi_mutex_unlock(&active_contexts_lock);
284
269
  }
285
270
 
286
-
287
-
288
271
  static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) {
289
- struct libusb_context *ctx = (struct libusb_context *)ptr;
290
- struct libusb_device_handle *handle;
291
- struct darwin_device_priv *dpriv;
292
- struct darwin_device_handle_priv *priv;
272
+ struct libusb_device *dev = NULL;
273
+ struct libusb_context *ctx;
293
274
 
294
275
  io_service_t device;
295
- long location;
296
- bool locationValid;
297
- CFTypeRef locationCF;
298
- UInt32 message;
299
-
300
- usbi_dbg ("a device has been detached");
276
+ UInt64 session;
277
+ int ret;
301
278
 
302
279
  while ((device = IOIteratorNext (rem_devices)) != 0) {
303
280
  /* get the location from the i/o registry */
304
- locationCF = IORegistryEntryCreateCFProperty (device, CFSTR(kUSBDevicePropertyLocationID), kCFAllocatorDefault, 0);
305
-
281
+ ret = get_ioregistry_value_number (device, CFSTR("sessionID"), kCFNumberSInt64Type, &session);
306
282
  IOObjectRelease (device);
307
-
308
- if (!locationCF)
283
+ if (!ret)
309
284
  continue;
310
285
 
311
- locationValid = CFGetTypeID(locationCF) == CFNumberGetTypeID() &&
312
- CFNumberGetValue(locationCF, kCFNumberLongType, &location);
313
-
314
- CFRelease (locationCF);
286
+ usbi_mutex_lock(&active_contexts_lock);
315
287
 
316
- if (!locationValid)
317
- continue;
288
+ list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
289
+ usbi_dbg ("notifying context %p of device disconnect", ctx);
318
290
 
319
- usbi_mutex_lock(&ctx->open_devs_lock);
320
- list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) {
321
- dpriv = (struct darwin_device_priv *)handle->dev->os_priv;
322
-
323
- /* the device may have been opened several times. write to each handle's event descriptor */
324
- if (dpriv->location == location && handle->os_priv) {
325
- priv = (struct darwin_device_handle_priv *)handle->os_priv;
326
-
327
- message = MESSAGE_DEVICE_GONE;
328
- write (priv->fds[1], &message, sizeof (message));
291
+ dev = usbi_get_device_by_session_id(ctx, (unsigned long) session);
292
+ if (dev) {
293
+ /* signal the core that this device has been disconnected. the core will tear down this device
294
+ when the reference count reaches 0 */
295
+ usbi_disconnect_device(dev);
329
296
  }
330
297
  }
331
298
 
332
- usbi_mutex_unlock(&ctx->open_devs_lock);
299
+ usbi_mutex_unlock(&active_contexts_lock);
333
300
  }
334
301
  }
335
302
 
@@ -340,7 +307,7 @@ static void darwin_clear_iterator (io_iterator_t iter) {
340
307
  IOObjectRelease (device);
341
308
  }
342
309
 
343
- static void *event_thread_main (void *arg0) {
310
+ static void *darwin_event_thread_main (void *arg0) {
344
311
  IOReturn kresult;
345
312
  struct libusb_context *ctx = (struct libusb_context *)arg0;
346
313
  CFRunLoopRef runloop;
@@ -348,21 +315,20 @@ static void *event_thread_main (void *arg0) {
348
315
  /* Set this thread's name, so it can be seen in the debugger
349
316
  and crash reports. */
350
317
  #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
351
- pthread_setname_np ("org.libusb.device-detach");
352
- #endif
318
+ pthread_setname_np ("org.libusb.device-hotplug");
353
319
 
354
320
  /* Tell the Objective-C garbage collector about this thread.
355
321
  This is required because, unlike NSThreads, pthreads are
356
322
  not automatically registered. Although we don't use
357
323
  Objective-C, we use CoreFoundation, which does. */
358
- #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
359
324
  objc_registerThreadWithCollector();
360
325
  #endif
361
326
 
362
- /* hotplug (device removal) source */
327
+ /* hotplug (device arrival/removal) sources */
363
328
  CFRunLoopSourceRef libusb_notification_cfsource;
364
329
  io_notification_port_t libusb_notification_port;
365
330
  io_iterator_t libusb_rem_device_iterator;
331
+ io_iterator_t libusb_add_device_iterator;
366
332
 
367
333
  usbi_dbg ("creating hotplug event source");
368
334
 
@@ -376,9 +342,21 @@ static void *event_thread_main (void *arg0) {
376
342
 
377
343
  /* create notifications for removed devices */
378
344
  kresult = IOServiceAddMatchingNotification (libusb_notification_port, kIOTerminatedNotification,
379
- IOServiceMatching(kIOUSBDeviceClassName),
380
- (IOServiceMatchingCallback)darwin_devices_detached,
381
- (void *)ctx, &libusb_rem_device_iterator);
345
+ IOServiceMatching(kIOUSBDeviceClassName),
346
+ (IOServiceMatchingCallback)darwin_devices_detached,
347
+ (void *)ctx, &libusb_rem_device_iterator);
348
+
349
+ if (kresult != kIOReturnSuccess) {
350
+ usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult));
351
+
352
+ pthread_exit (NULL);
353
+ }
354
+
355
+ /* create notifications for attached devices */
356
+ kresult = IOServiceAddMatchingNotification(libusb_notification_port, kIOFirstMatchNotification,
357
+ IOServiceMatching(kIOUSBDeviceClassName),
358
+ (IOServiceMatchingCallback)darwin_devices_attached,
359
+ (void *)ctx, &libusb_add_device_iterator);
382
360
 
383
361
  if (kresult != kIOReturnSuccess) {
384
362
  usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult));
@@ -388,10 +366,11 @@ static void *event_thread_main (void *arg0) {
388
366
 
389
367
  /* arm notifiers */
390
368
  darwin_clear_iterator (libusb_rem_device_iterator);
369
+ darwin_clear_iterator (libusb_add_device_iterator);
391
370
 
392
- usbi_dbg ("thread ready to receive events");
371
+ usbi_dbg ("darwin event thread ready to receive events");
393
372
 
394
- /* signal the main thread that the async runloop has been created. */
373
+ /* signal the main thread that the hotplug runloop has been created. */
395
374
  pthread_mutex_lock (&libusb_darwin_at_mutex);
396
375
  libusb_darwin_acfl = runloop;
397
376
  pthread_cond_signal (&libusb_darwin_at_cond);
@@ -400,11 +379,17 @@ static void *event_thread_main (void *arg0) {
400
379
  /* run the runloop */
401
380
  CFRunLoopRun();
402
381
 
403
- usbi_dbg ("thread exiting");
382
+ usbi_dbg ("darwin event thread exiting");
383
+
384
+ /* remove the notification cfsource */
385
+ CFRunLoopRemoveSource(runloop, libusb_notification_cfsource, kCFRunLoopDefaultMode);
404
386
 
405
387
  /* delete notification port */
406
388
  IONotificationPortDestroy (libusb_notification_port);
389
+
390
+ /* delete iterators */
407
391
  IOObjectRelease (libusb_rem_device_iterator);
392
+ IOObjectRelease (libusb_add_device_iterator);
408
393
 
409
394
  CFRelease (runloop);
410
395
 
@@ -413,21 +398,40 @@ static void *event_thread_main (void *arg0) {
413
398
  pthread_exit (NULL);
414
399
  }
415
400
 
401
+ static void _darwin_finalize(void) {
402
+ struct darwin_cached_device *dev, *next;
403
+
404
+ usbi_mutex_lock(&darwin_cached_devices_lock);
405
+ list_for_each_entry_safe(dev, next, &darwin_cached_devices, list, struct darwin_cached_device) {
406
+ darwin_deref_cached_device(dev);
407
+ }
408
+ usbi_mutex_unlock(&darwin_cached_devices_lock);
409
+ }
410
+
416
411
  static int darwin_init(struct libusb_context *ctx) {
417
412
  host_name_port_t host_self;
413
+ static int initted = 0;
414
+ int rc;
415
+
416
+ rc = darwin_scan_devices (ctx);
417
+ if (LIBUSB_SUCCESS != rc) {
418
+ return rc;
419
+ }
418
420
 
419
421
  if (OSAtomicIncrement32Barrier(&initCount) == 1) {
420
422
  /* create the clocks that will be used */
421
423
 
424
+ if (!initted) {
425
+ initted = 1;
426
+ atexit(_darwin_finalize);
427
+ }
428
+
422
429
  host_self = mach_host_self();
423
430
  host_get_clock_service(host_self, CALENDAR_CLOCK, &clock_realtime);
424
431
  host_get_clock_service(host_self, SYSTEM_CLOCK, &clock_monotonic);
425
432
  mach_port_deallocate(mach_task_self(), host_self);
426
433
 
427
- pthread_mutex_init (&libusb_darwin_at_mutex, NULL);
428
- pthread_cond_init (&libusb_darwin_at_cond, NULL);
429
-
430
- pthread_create (&libusb_darwin_at, NULL, event_thread_main, (void *)ctx);
434
+ pthread_create (&libusb_darwin_at, NULL, darwin_event_thread_main, (void *)ctx);
431
435
 
432
436
  pthread_mutex_lock (&libusb_darwin_at_mutex);
433
437
  while (!libusb_darwin_acfl)
@@ -435,7 +439,7 @@ static int darwin_init(struct libusb_context *ctx) {
435
439
  pthread_mutex_unlock (&libusb_darwin_at_mutex);
436
440
  }
437
441
 
438
- return 0;
442
+ return rc;
439
443
  }
440
444
 
441
445
  static void darwin_exit (void) {
@@ -443,14 +447,14 @@ static void darwin_exit (void) {
443
447
  mach_port_deallocate(mach_task_self(), clock_realtime);
444
448
  mach_port_deallocate(mach_task_self(), clock_monotonic);
445
449
 
446
- /* stop the async runloop and wait for the thread to terminate. */
450
+ /* stop the event runloop and wait for the thread to terminate. */
447
451
  CFRunLoopStop (libusb_darwin_acfl);
448
452
  pthread_join (libusb_darwin_at, NULL);
449
453
  }
450
454
  }
451
455
 
452
456
  static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) {
453
- struct darwin_device_priv *priv = (struct darwin_device_priv *)dev->os_priv;
457
+ struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
454
458
 
455
459
  /* return cached copy */
456
460
  memmove (buffer, &(priv->dev_descriptor), DEVICE_DESC_LENGTH);
@@ -461,7 +465,7 @@ static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char
461
465
  }
462
466
 
463
467
  static int get_configuration_index (struct libusb_device *dev, int config_value) {
464
- struct darwin_device_priv *priv = (struct darwin_device_priv *)dev->os_priv;
468
+ struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
465
469
  UInt8 i, numConfig;
466
470
  IOUSBConfigurationDescriptorPtr desc;
467
471
  IOReturn kresult;
@@ -479,15 +483,15 @@ static int get_configuration_index (struct libusb_device *dev, int config_value)
479
483
  }
480
484
 
481
485
  /* configuration not found */
482
- return LIBUSB_ERROR_OTHER;
486
+ return LIBUSB_ERROR_NOT_FOUND;
483
487
  }
484
488
 
485
489
  static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsigned char *buffer, size_t len, int *host_endian) {
486
- struct darwin_device_priv *priv = (struct darwin_device_priv *)dev->os_priv;
490
+ struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
487
491
  int config_index;
488
492
 
489
493
  if (0 == priv->active_config)
490
- return LIBUSB_ERROR_INVALID_PARAM;
494
+ return LIBUSB_ERROR_NOT_FOUND;
491
495
 
492
496
  config_index = get_configuration_index (dev, priv->active_config);
493
497
  if (config_index < 0)
@@ -497,27 +501,15 @@ static int darwin_get_active_config_descriptor(struct libusb_device *dev, unsign
497
501
  }
498
502
 
499
503
  static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) {
500
- struct darwin_device_priv *priv = (struct darwin_device_priv *)dev->os_priv;
504
+ struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
501
505
  IOUSBConfigurationDescriptorPtr desc;
502
506
  IOReturn kresult;
503
- usb_device_t **device = NULL;
507
+ int ret;
504
508
 
505
- if (!priv)
509
+ if (!priv || !priv->device)
506
510
  return LIBUSB_ERROR_OTHER;
507
511
 
508
- if (!priv->device) {
509
- kresult = darwin_get_device (priv->location, &device);
510
- if (kresult || !device) {
511
- usbi_err (DEVICE_CTX (dev), "could not find device: %s", darwin_error_str (kresult));
512
-
513
- return darwin_to_libusb (kresult);
514
- }
515
-
516
- /* don't have to open the device to get a config descriptor */
517
- } else
518
- device = priv->device;
519
-
520
- kresult = (*device)->GetConfigurationDescriptorPtr (device, config_index, &desc);
512
+ kresult = (*priv->device)->GetConfigurationDescriptorPtr (priv->device, config_index, &desc);
521
513
  if (kresult == kIOReturnSuccess) {
522
514
  /* copy descriptor */
523
515
  if (libusb_le16_to_cpu(desc->wTotalLength) < len)
@@ -529,15 +521,16 @@ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t confi
529
521
  *host_endian = 0;
530
522
  }
531
523
 
532
- if (!priv->device)
533
- (*device)->Release (device);
524
+ ret = darwin_to_libusb (kresult);
525
+ if (ret != LIBUSB_SUCCESS)
526
+ return ret;
534
527
 
535
- return darwin_to_libusb (kresult);
528
+ return len;
536
529
  }
537
530
 
538
531
  /* check whether the os has configured the device */
539
- static int darwin_check_configuration (struct libusb_context *ctx, struct libusb_device *dev, usb_device_t **darwin_device) {
540
- struct darwin_device_priv *priv = (struct darwin_device_priv *)dev->os_priv;
532
+ static int darwin_check_configuration (struct libusb_context *ctx, struct darwin_cached_device *dev) {
533
+ usb_device_t **darwin_device = dev->device;
541
534
 
542
535
  IOUSBConfigurationDescriptorPtr configDesc;
543
536
  IOUSBFindInterfaceRequest request;
@@ -545,14 +538,14 @@ static int darwin_check_configuration (struct libusb_context *ctx, struct libusb
545
538
  io_iterator_t interface_iterator;
546
539
  io_service_t firstInterface;
547
540
 
548
- if (priv->dev_descriptor.bNumConfigurations < 1) {
541
+ if (dev->dev_descriptor.bNumConfigurations < 1) {
549
542
  usbi_err (ctx, "device has no configurations");
550
543
  return LIBUSB_ERROR_OTHER; /* no configurations at this speed so we can't use it */
551
544
  }
552
545
 
553
546
  /* find the first configuration */
554
547
  kresult = (*darwin_device)->GetConfigurationDescriptorPtr (darwin_device, 0, &configDesc);
555
- priv->first_config = (kIOReturnSuccess == kresult) ? configDesc->bConfigurationValue : 1;
548
+ dev->first_config = (kIOReturnSuccess == kresult) ? configDesc->bConfigurationValue : 1;
556
549
 
557
550
  /* check if the device is already configured. there is probably a better way than iterating over the
558
551
  to accomplish this (the trick is we need to avoid a call to GetConfigurations since buggy devices
@@ -578,72 +571,83 @@ static int darwin_check_configuration (struct libusb_context *ctx, struct libusb
578
571
  IOObjectRelease (firstInterface);
579
572
 
580
573
  /* device is configured */
581
- if (priv->dev_descriptor.bNumConfigurations == 1)
574
+ if (dev->dev_descriptor.bNumConfigurations == 1)
582
575
  /* to avoid problems with some devices get the configurations value from the configuration descriptor */
583
- priv->active_config = priv->first_config;
576
+ dev->active_config = dev->first_config;
584
577
  else
585
578
  /* devices with more than one configuration should work with GetConfiguration */
586
- (*darwin_device)->GetConfiguration (darwin_device, &priv->active_config);
579
+ (*darwin_device)->GetConfiguration (darwin_device, &dev->active_config);
587
580
  } else
588
581
  /* not configured */
589
- priv->active_config = 0;
582
+ dev->active_config = 0;
590
583
 
591
- usbi_dbg ("active config: %u, first config: %u", priv->active_config, priv->first_config);
584
+ usbi_dbg ("active config: %u, first config: %u", dev->active_config, dev->first_config);
592
585
 
593
586
  return 0;
594
587
  }
595
588
 
596
- static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct libusb_device *dev, usb_device_t **device) {
597
- struct darwin_device_priv *priv;
598
- int retries = 5, delay = 30000;
589
+ static int darwin_request_descriptor (usb_device_t **device, UInt8 desc, UInt8 desc_index, void *buffer, size_t buffer_size) {
590
+ IOUSBDevRequestTO req;
591
+
592
+ memset (buffer, 0, buffer_size);
593
+
594
+ /* Set up request for descriptor/ */
595
+ req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
596
+ req.bRequest = kUSBRqGetDescriptor;
597
+ req.wValue = desc << 8;
598
+ req.wIndex = desc_index;
599
+ req.wLength = buffer_size;
600
+ req.pData = buffer;
601
+ req.noDataTimeout = 20;
602
+ req.completionTimeout = 100;
603
+
604
+ return (*device)->DeviceRequestTO (device, &req);
605
+ }
606
+
607
+ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct darwin_cached_device *dev) {
608
+ usb_device_t **device = dev->device;
609
+ int retries = 1, delay = 30000;
599
610
  int unsuspended = 0, try_unsuspend = 1, try_reconfigure = 1;
600
611
  int is_open = 0;
601
612
  int ret = 0, ret2;
602
- IOUSBDevRequest req;
603
613
  UInt8 bDeviceClass;
604
614
  UInt16 idProduct, idVendor;
605
615
 
616
+ dev->can_enumerate = 0;
617
+
606
618
  (*device)->GetDeviceClass (device, &bDeviceClass);
607
619
  (*device)->GetDeviceProduct (device, &idProduct);
608
620
  (*device)->GetDeviceVendor (device, &idVendor);
609
621
 
610
- priv = (struct darwin_device_priv *)dev->os_priv;
611
-
612
- /* try to open the device (we can usually continue even if this fails) */
622
+ /* According to Apple's documentation the device must be open for DeviceRequest but we may not be able to open some
623
+ * devices and Apple's USB Prober doesn't bother to open the device before issuing a descriptor request. Still,
624
+ * to follow the spec as closely as possible, try opening the device */
613
625
  is_open = ((*device)->USBDeviceOpenSeize(device) == kIOReturnSuccess);
614
626
 
615
- /**** retrieve device descriptor ****/
616
627
  do {
617
- /* Set up request for device descriptor */
618
- memset (&(priv->dev_descriptor), 0, sizeof(IOUSBDeviceDescriptor));
619
- req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
620
- req.bRequest = kUSBRqGetDescriptor;
621
- req.wValue = kUSBDeviceDesc << 8;
622
- req.wIndex = 0;
623
- req.wLength = sizeof(priv->dev_descriptor);
624
- req.pData = &(priv->dev_descriptor);
625
-
626
- /* according to Apple's documentation the device must be open for DeviceRequest but we may not be able to open some
627
- * devices and Apple's USB Prober doesn't bother to open the device before issuing a descriptor request. Still,
628
- * to follow the spec as closely as possible, try opening the device */
629
-
630
- ret = (*(device))->DeviceRequest (device, &req);
631
-
632
- if (kIOReturnOverrun == ret && kUSBDeviceDesc == priv->dev_descriptor.bDescriptorType)
628
+ /**** retrieve device descriptor ****/
629
+ ret = darwin_request_descriptor (device, kUSBDeviceDesc, 0, &dev->dev_descriptor, sizeof(dev->dev_descriptor));
630
+
631
+ if (kIOReturnOverrun == ret && kUSBDeviceDesc == dev->dev_descriptor.bDescriptorType)
633
632
  /* received an overrun error but we still received a device descriptor */
634
633
  ret = kIOReturnSuccess;
635
634
 
636
- if (kIOReturnSuccess == ret && (0 == priv->dev_descriptor.bNumConfigurations ||
637
- 0 == priv->dev_descriptor.bcdUSB)) {
635
+ if (kIOUSBVendorIDAppleComputer == idVendor) {
636
+ /* NTH: don't bother retrying or unsuspending Apple devices */
637
+ break;
638
+ }
639
+
640
+ if (kIOReturnSuccess == ret && (0 == dev->dev_descriptor.bNumConfigurations ||
641
+ 0 == dev->dev_descriptor.bcdUSB)) {
638
642
  /* work around for incorrectly configured devices */
639
643
  if (try_reconfigure && is_open) {
640
- usbi_dbg("descriptor appears to be invalid. resetting configuration before trying again...");
644
+ usbi_dbg("descriptor appears to be invalid. resetting configuration before trying again...");
641
645
 
642
- /* set the first configuration */
643
- (*device)->SetConfiguration(device, 1);
646
+ /* set the first configuration */
647
+ (*device)->SetConfiguration(device, 1);
644
648
 
645
- /* don't try to reconfigure again */
646
- try_reconfigure = 0;
649
+ /* don't try to reconfigure again */
650
+ try_reconfigure = 0;
647
651
  }
648
652
 
649
653
  ret = kIOUSBPipeStalled;
@@ -652,25 +656,27 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct li
652
656
  if (kIOReturnSuccess != ret && is_open && try_unsuspend) {
653
657
  /* device may be suspended. unsuspend it and try again */
654
658
  #if DeviceVersion >= 320
655
- UInt32 info;
659
+ UInt32 info = 0;
656
660
 
657
661
  /* IOUSBFamily 320+ provides a way to detect device suspension but earlier versions do not */
658
662
  (void)(*device)->GetUSBDeviceInformation (device, &info);
659
663
 
660
- try_unsuspend = info & (1 << kUSBInformationDeviceIsSuspendedBit);
664
+ /* note that the device was suspended */
665
+ if (info & (1 << kUSBInformationDeviceIsSuspendedBit) || 0 == info)
666
+ try_unsuspend = 1;
661
667
  #endif
662
668
 
663
669
  if (try_unsuspend) {
664
- /* resume the device */
665
- ret2 = (*device)->USBDeviceSuspend (device, 0);
666
- if (kIOReturnSuccess != ret2) {
667
- /* prevent log spew from poorly behaving devices. this indicates the
668
- os actually had trouble communicating with the device */
669
- usbi_dbg("could not retrieve device descriptor. failed to unsuspend: %s",darwin_error_str(ret2));
670
- } else
671
- unsuspended = 1;
672
-
673
- try_unsuspend = 0;
670
+ /* try to unsuspend the device */
671
+ ret2 = (*device)->USBDeviceSuspend (device, 0);
672
+ if (kIOReturnSuccess != ret2) {
673
+ /* prevent log spew from poorly behaving devices. this indicates the
674
+ os actually had trouble communicating with the device */
675
+ usbi_dbg("could not retrieve device descriptor. failed to unsuspend: %s",darwin_error_str(ret2));
676
+ } else
677
+ unsuspended = 1;
678
+
679
+ try_unsuspend = 0;
674
680
  }
675
681
  }
676
682
 
@@ -691,147 +697,221 @@ static int darwin_cache_device_descriptor (struct libusb_context *ctx, struct li
691
697
  if (ret != kIOReturnSuccess) {
692
698
  /* a debug message was already printed out for this error */
693
699
  if (LIBUSB_CLASS_HUB == bDeviceClass)
694
- usbi_dbg ("could not retrieve device descriptor %.4x:%.4x: %s. skipping device", idVendor, idProduct, darwin_error_str (ret));
700
+ usbi_dbg ("could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
701
+ idVendor, idProduct, darwin_error_str (ret), ret);
695
702
  else
696
- usbi_warn (ctx, "could not retrieve device descriptor %.4x:%.4x: %s. skipping device", idVendor, idProduct, darwin_error_str (ret));
697
-
698
- return -1;
703
+ usbi_warn (ctx, "could not retrieve device descriptor %.4x:%.4x: %s (%x). skipping device",
704
+ idVendor, idProduct, darwin_error_str (ret), ret);
705
+ return darwin_to_libusb (ret);
699
706
  }
700
707
 
701
- usbi_dbg ("device descriptor:");
702
- usbi_dbg (" bDescriptorType: 0x%02x", priv->dev_descriptor.bDescriptorType);
703
- usbi_dbg (" bcdUSB: 0x%04x", priv->dev_descriptor.bcdUSB);
704
- usbi_dbg (" bDeviceClass: 0x%02x", priv->dev_descriptor.bDeviceClass);
705
- usbi_dbg (" bDeviceSubClass: 0x%02x", priv->dev_descriptor.bDeviceSubClass);
706
- usbi_dbg (" bDeviceProtocol: 0x%02x", priv->dev_descriptor.bDeviceProtocol);
707
- usbi_dbg (" bMaxPacketSize0: 0x%02x", priv->dev_descriptor.bMaxPacketSize0);
708
- usbi_dbg (" idVendor: 0x%04x", priv->dev_descriptor.idVendor);
709
- usbi_dbg (" idProduct: 0x%04x", priv->dev_descriptor.idProduct);
710
- usbi_dbg (" bcdDevice: 0x%04x", priv->dev_descriptor.bcdDevice);
711
- usbi_dbg (" iManufacturer: 0x%02x", priv->dev_descriptor.iManufacturer);
712
- usbi_dbg (" iProduct: 0x%02x", priv->dev_descriptor.iProduct);
713
- usbi_dbg (" iSerialNumber: 0x%02x", priv->dev_descriptor.iSerialNumber);
714
- usbi_dbg (" bNumConfigurations: 0x%02x", priv->dev_descriptor.bNumConfigurations);
715
-
716
708
  /* catch buggy hubs (which appear to be virtual). Apple's own USB prober has problems with these devices. */
717
- if (libusb_le16_to_cpu (priv->dev_descriptor.idProduct) != idProduct) {
709
+ if (libusb_le16_to_cpu (dev->dev_descriptor.idProduct) != idProduct) {
718
710
  /* not a valid device */
719
711
  usbi_warn (ctx, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device",
720
- idProduct, libusb_le16_to_cpu (priv->dev_descriptor.idProduct));
721
- return -1;
712
+ idProduct, libusb_le16_to_cpu (dev->dev_descriptor.idProduct));
713
+ return LIBUSB_ERROR_NO_DEVICE;
722
714
  }
723
715
 
724
- return 0;
716
+ usbi_dbg ("cached device descriptor:");
717
+ usbi_dbg (" bDescriptorType: 0x%02x", dev->dev_descriptor.bDescriptorType);
718
+ usbi_dbg (" bcdUSB: 0x%04x", dev->dev_descriptor.bcdUSB);
719
+ usbi_dbg (" bDeviceClass: 0x%02x", dev->dev_descriptor.bDeviceClass);
720
+ usbi_dbg (" bDeviceSubClass: 0x%02x", dev->dev_descriptor.bDeviceSubClass);
721
+ usbi_dbg (" bDeviceProtocol: 0x%02x", dev->dev_descriptor.bDeviceProtocol);
722
+ usbi_dbg (" bMaxPacketSize0: 0x%02x", dev->dev_descriptor.bMaxPacketSize0);
723
+ usbi_dbg (" idVendor: 0x%04x", dev->dev_descriptor.idVendor);
724
+ usbi_dbg (" idProduct: 0x%04x", dev->dev_descriptor.idProduct);
725
+ usbi_dbg (" bcdDevice: 0x%04x", dev->dev_descriptor.bcdDevice);
726
+ usbi_dbg (" iManufacturer: 0x%02x", dev->dev_descriptor.iManufacturer);
727
+ usbi_dbg (" iProduct: 0x%02x", dev->dev_descriptor.iProduct);
728
+ usbi_dbg (" iSerialNumber: 0x%02x", dev->dev_descriptor.iSerialNumber);
729
+ usbi_dbg (" bNumConfigurations: 0x%02x", dev->dev_descriptor.bNumConfigurations);
730
+
731
+ dev->can_enumerate = 1;
732
+
733
+ return LIBUSB_SUCCESS;
725
734
  }
726
735
 
727
- static int process_new_device (struct libusb_context *ctx, usb_device_t **device, UInt32 locationID,
728
- UInt32 parent_location, UInt8 port, struct discovered_devs **_discdevs,
729
- struct libusb_device **last_dev) {
730
- struct darwin_device_priv *priv;
731
- struct libusb_device *dev, *parent = NULL;
732
- struct discovered_devs *discdevs;
733
- UInt16 address;
734
- UInt8 devSpeed;
735
- int ret = 0, need_unref = 0;
736
+ static int darwin_get_cached_device(struct libusb_context *ctx, io_service_t service,
737
+ struct darwin_cached_device **cached_out) {
738
+ struct darwin_cached_device *new_device;
739
+ UInt64 sessionID = 0, parent_sessionID = 0;
740
+ int ret = LIBUSB_SUCCESS;
741
+ usb_device_t **device;
742
+ io_service_t parent;
743
+ kern_return_t result;
744
+ UInt8 port = 0;
736
745
 
746
+ /* get some info from the io registry */
747
+ (void) get_ioregistry_value_number (service, CFSTR("sessionID"), kCFNumberSInt64Type, &sessionID);
748
+ (void) get_ioregistry_value_number (service, CFSTR("PortNum"), kCFNumberSInt8Type, &port);
749
+
750
+ usbi_dbg("finding cached device for sessionID 0x\n" PRIx64, sessionID);
751
+
752
+ result = IORegistryEntryGetParentEntry (service, kIOUSBPlane, &parent);
753
+
754
+ if (kIOReturnSuccess == result) {
755
+ (void) get_ioregistry_value_number (parent, CFSTR("sessionID"), kCFNumberSInt64Type, &parent_sessionID);
756
+ IOObjectRelease(parent);
757
+ }
758
+
759
+ usbi_mutex_lock(&darwin_cached_devices_lock);
737
760
  do {
738
- dev = usbi_get_device_by_session_id(ctx, locationID);
739
- if (!dev) {
740
- usbi_dbg ("allocating new device for location 0x%08x", locationID);
741
- dev = usbi_alloc_device(ctx, locationID);
742
- need_unref = 1;
743
- } else
744
- usbi_dbg ("using existing device for location 0x%08x", locationID);
761
+ *cached_out = NULL;
762
+
763
+ list_for_each_entry(new_device, &darwin_cached_devices, list, struct darwin_cached_device) {
764
+ usbi_dbg("matching sessionID 0x%x against cached device with sessionID 0x%x", sessionID, new_device->session);
765
+ if (new_device->session == sessionID) {
766
+ usbi_dbg("using cached device for device");
767
+ *cached_out = new_device;
768
+ break;
769
+ }
770
+ }
745
771
 
746
- if (!dev) {
772
+ if (*cached_out)
773
+ break;
774
+
775
+ usbi_dbg("caching new device with sessionID 0x%x\n", sessionID);
776
+
777
+ device = darwin_device_from_service (service);
778
+ if (!device) {
779
+ ret = LIBUSB_ERROR_NO_DEVICE;
780
+ break;
781
+ }
782
+
783
+ new_device = calloc (1, sizeof (*new_device));
784
+ if (!new_device) {
747
785
  ret = LIBUSB_ERROR_NO_MEM;
748
786
  break;
749
787
  }
750
788
 
751
- priv = (struct darwin_device_priv *)dev->os_priv;
789
+ /* add this device to the cached device list */
790
+ list_add(&new_device->list, &darwin_cached_devices);
752
791
 
753
- (*device)->GetDeviceAddress (device, (USBDeviceAddress *)&address);
792
+ (*device)->GetDeviceAddress (device, (USBDeviceAddress *)&new_device->address);
754
793
 
755
- ret = darwin_cache_device_descriptor (ctx, dev, device);
756
- if (ret < 0)
794
+ /* keep a reference to this device */
795
+ darwin_ref_cached_device(new_device);
796
+
797
+ new_device->device = device;
798
+ new_device->session = sessionID;
799
+ (*device)->GetLocationID (device, &new_device->location);
800
+ new_device->port = port;
801
+ new_device->parent_session = parent_sessionID;
802
+
803
+ /* cache the device descriptor */
804
+ ret = darwin_cache_device_descriptor(ctx, new_device);
805
+ if (ret)
757
806
  break;
758
807
 
759
- /* check current active configuration (and cache the first configuration value-- which may be used by claim_interface) */
760
- ret = darwin_check_configuration (ctx, dev, device);
761
- if (ret < 0)
808
+ if (new_device->can_enumerate) {
809
+ snprintf(new_device->sys_path, 20, "%03i-%04x-%04x-%02x-%02x", new_device->address,
810
+ new_device->dev_descriptor.idVendor, new_device->dev_descriptor.idProduct,
811
+ new_device->dev_descriptor.bDeviceClass, new_device->dev_descriptor.bDeviceSubClass);
812
+ }
813
+ } while (0);
814
+
815
+ usbi_mutex_unlock(&darwin_cached_devices_lock);
816
+
817
+ /* keep track of devices regardless of if we successfully enumerate them to
818
+ prevent them from being enumerated multiple times */
819
+
820
+ *cached_out = new_device;
821
+
822
+ return ret;
823
+ }
824
+
825
+ static int process_new_device (struct libusb_context *ctx, io_service_t service) {
826
+ struct darwin_device_priv *priv;
827
+ struct libusb_device *dev = NULL;
828
+ struct darwin_cached_device *cached_device;
829
+ UInt8 devSpeed;
830
+ int ret = 0;
831
+
832
+ do {
833
+ ret = darwin_get_cached_device (ctx, service, &cached_device);
834
+
835
+ if (ret < 0 || !cached_device->can_enumerate) {
836
+ return ret;
837
+ }
838
+
839
+ /* check current active configuration (and cache the first configuration value--
840
+ which may be used by claim_interface) */
841
+ ret = darwin_check_configuration (ctx, cached_device);
842
+ if (ret)
762
843
  break;
763
844
 
764
- /* the device iterator provides devices in increasing order of location. given this property
765
- * we can use the last device to find the parent. */
766
- for (parent = *last_dev ; parent ; parent = parent->parent_dev) {
767
- struct darwin_device_priv *parent_priv = (struct darwin_device_priv *) parent->os_priv;
845
+ usbi_dbg ("allocating new device in context %p for with session 0x%08x",
846
+ ctx, cached_device->session);
768
847
 
769
- if (parent_priv->location == parent_location) {
770
- break;
771
- }
848
+ dev = usbi_alloc_device(ctx, (unsigned long) cached_device->session);
849
+ if (!dev) {
850
+ return LIBUSB_ERROR_NO_MEM;
772
851
  }
773
852
 
774
- dev->parent_dev = parent;
853
+ priv = (struct darwin_device_priv *)dev->os_priv;
854
+
855
+ priv->dev = cached_device;
856
+ darwin_ref_cached_device (priv->dev);
857
+
858
+ if (cached_device->parent_session > 0) {
859
+ dev->parent_dev = usbi_get_device_by_session_id (ctx, (unsigned long) cached_device->parent_session);
860
+ } else {
861
+ dev->parent_dev = NULL;
862
+ }
863
+ dev->port_number = cached_device->port;
864
+ dev->bus_number = cached_device->location >> 24;
865
+ dev->device_address = cached_device->address;
775
866
 
776
- dev->port_number = port;
777
- dev->bus_number = locationID >> 24;
778
- dev->device_address = address;
867
+ /* need to add a reference to the parent device */
868
+ if (dev->parent_dev) {
869
+ libusb_ref_device(dev->parent_dev);
870
+ }
779
871
 
780
- (*device)->GetDeviceSpeed (device, &devSpeed);
872
+ (*(priv->dev->device))->GetDeviceSpeed (priv->dev->device, &devSpeed);
781
873
 
782
874
  switch (devSpeed) {
783
875
  case kUSBDeviceSpeedLow: dev->speed = LIBUSB_SPEED_LOW; break;
784
876
  case kUSBDeviceSpeedFull: dev->speed = LIBUSB_SPEED_FULL; break;
785
877
  case kUSBDeviceSpeedHigh: dev->speed = LIBUSB_SPEED_HIGH; break;
878
+ #if DeviceVersion >= 500
879
+ case kUSBDeviceSpeedSuper: dev->speed = LIBUSB_SPEED_SUPER; break;
880
+ #endif
786
881
  default:
787
882
  usbi_warn (ctx, "Got unknown device speed %d", devSpeed);
788
883
  }
789
884
 
790
- /* save our location, we'll need this later */
791
- priv->location = locationID;
792
- snprintf(priv->sys_path, 20, "%03i-%04x-%04x-%02x-%02x", address, priv->dev_descriptor.idVendor, priv->dev_descriptor.idProduct,
793
- priv->dev_descriptor.bDeviceClass, priv->dev_descriptor.bDeviceSubClass);
794
-
795
885
  ret = usbi_sanitize_device (dev);
796
886
  if (ret < 0)
797
887
  break;
798
888
 
799
- /* append the device to the list of discovered devices */
800
- discdevs = discovered_devs_append(*_discdevs, dev);
801
- if (!discdevs) {
802
- ret = LIBUSB_ERROR_NO_MEM;
803
- break;
804
- }
805
-
806
- *_discdevs = discdevs;
807
- *last_dev = dev;
808
-
809
889
  usbi_dbg ("found device with address %d port = %d parent = %p at %p", dev->device_address,
810
- dev->port_number, priv->sys_path, (void *) parent);
890
+ dev->port_number, (void *) dev->parent_dev, priv->dev->sys_path);
811
891
  } while (0);
812
892
 
813
- if (need_unref)
814
- libusb_unref_device(dev);
893
+ if (0 == ret) {
894
+ usbi_connect_device (dev);
895
+ } else {
896
+ libusb_unref_device (dev);
897
+ }
815
898
 
816
899
  return ret;
817
900
  }
818
901
 
819
- static int darwin_get_device_list(struct libusb_context *ctx, struct discovered_devs **_discdevs) {
820
- io_iterator_t deviceIterator;
821
- usb_device_t **device;
822
- kern_return_t kresult;
823
- UInt32 location, parent_location;
824
- UInt8 port;
825
- struct libusb_device *last_dev = NULL;
902
+ static int darwin_scan_devices(struct libusb_context *ctx) {
903
+ io_iterator_t deviceIterator;
904
+ io_service_t service;
905
+ kern_return_t kresult;
826
906
 
827
907
  kresult = usb_setup_device_iterator (&deviceIterator, 0);
828
908
  if (kresult != kIOReturnSuccess)
829
909
  return darwin_to_libusb (kresult);
830
910
 
831
- while ((device = usb_get_next_device (deviceIterator, &location, &port, &parent_location)) != NULL) {
832
- (void) process_new_device (ctx, device, location, parent_location, port, _discdevs, &last_dev);
911
+ while ((service = IOIteratorNext (deviceIterator))) {
912
+ (void) process_new_device (ctx, service);
833
913
 
834
- (*(device))->Release(device);
914
+ IOObjectRelease(service);
835
915
  }
836
916
 
837
917
  IOObjectRelease(deviceIterator);
@@ -841,56 +921,43 @@ static int darwin_get_device_list(struct libusb_context *ctx, struct discovered_
841
921
 
842
922
  static int darwin_open (struct libusb_device_handle *dev_handle) {
843
923
  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
844
- struct darwin_device_priv *dpriv = (struct darwin_device_priv *)dev_handle->dev->os_priv;
845
- usb_device_t **darwin_device;
924
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
846
925
  IOReturn kresult;
847
926
 
848
927
  if (0 == dpriv->open_count) {
849
- kresult = darwin_get_device (dpriv->location, &darwin_device);
850
- if (kresult) {
851
- usbi_err (HANDLE_CTX (dev_handle), "could not find device: %s", darwin_error_str (kresult));
852
- return darwin_to_libusb (kresult);
853
- }
854
-
855
- dpriv->device = darwin_device;
856
-
857
928
  /* try to open the device */
858
929
  kresult = (*(dpriv->device))->USBDeviceOpenSeize (dpriv->device);
859
-
860
930
  if (kresult != kIOReturnSuccess) {
861
931
  usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult));
862
932
 
863
- switch (kresult) {
864
- case kIOReturnExclusiveAccess:
865
- /* it is possible to perform some actions on a device that is not open so do not return an error */
866
- priv->is_open = 0;
867
-
868
- break;
869
- default:
870
- (*(dpriv->device))->Release (dpriv->device);
871
- dpriv->device = NULL;
872
- return darwin_to_libusb (kresult);
933
+ if (kIOReturnExclusiveAccess != kresult) {
934
+ return darwin_to_libusb (kresult);
873
935
  }
936
+
937
+ /* it is possible to perform some actions on a device that is not open so do not return an error */
938
+ priv->is_open = 0;
874
939
  } else {
875
- /* create async event source */
876
- kresult = (*(dpriv->device))->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource);
877
- if (kresult != kIOReturnSuccess) {
878
- usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult));
940
+ priv->is_open = 1;
941
+ }
879
942
 
880
- (*(dpriv->device))->USBDeviceClose (dpriv->device);
881
- (*(dpriv->device))->Release (dpriv->device);
943
+ /* create async event source */
944
+ kresult = (*(dpriv->device))->CreateDeviceAsyncEventSource (dpriv->device, &priv->cfSource);
945
+ if (kresult != kIOReturnSuccess) {
946
+ usbi_err (HANDLE_CTX (dev_handle), "CreateDeviceAsyncEventSource: %s", darwin_error_str(kresult));
882
947
 
883
- dpriv->device = NULL;
884
- return darwin_to_libusb (kresult);
948
+ if (priv->is_open) {
949
+ (*(dpriv->device))->USBDeviceClose (dpriv->device);
885
950
  }
886
951
 
887
- priv->is_open = 1;
888
-
889
- CFRetain (libusb_darwin_acfl);
952
+ priv->is_open = 0;
890
953
 
891
- /* add the cfSource to the aync run loop */
892
- CFRunLoopAddSource(libusb_darwin_acfl, priv->cfSource, kCFRunLoopCommonModes);
954
+ return darwin_to_libusb (kresult);
893
955
  }
956
+
957
+ CFRetain (libusb_darwin_acfl);
958
+
959
+ /* add the cfSource to the aync run loop */
960
+ CFRunLoopAddSource(libusb_darwin_acfl, priv->cfSource, kCFRunLoopCommonModes);
894
961
  }
895
962
 
896
963
  /* device opened successfully */
@@ -911,7 +978,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) {
911
978
 
912
979
  static void darwin_close (struct libusb_device_handle *dev_handle) {
913
980
  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
914
- struct darwin_device_priv *dpriv = (struct darwin_device_priv *)dev_handle->dev->os_priv;
981
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
915
982
  IOReturn kresult;
916
983
  int i;
917
984
 
@@ -929,30 +996,23 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
929
996
  libusb_release_interface (dev_handle, i);
930
997
 
931
998
  if (0 == dpriv->open_count) {
932
- if (priv->is_open) {
933
- /* delete the device's async event source */
934
- if (priv->cfSource) {
935
- CFRunLoopRemoveSource (libusb_darwin_acfl, priv->cfSource, kCFRunLoopDefaultMode);
936
- CFRelease (priv->cfSource);
937
- }
999
+ /* delete the device's async event source */
1000
+ if (priv->cfSource) {
1001
+ CFRunLoopRemoveSource (libusb_darwin_acfl, priv->cfSource, kCFRunLoopDefaultMode);
1002
+ CFRelease (priv->cfSource);
1003
+ priv->cfSource = NULL;
1004
+ CFRelease (libusb_darwin_acfl);
1005
+ }
938
1006
 
1007
+ if (priv->is_open) {
939
1008
  /* close the device */
940
1009
  kresult = (*(dpriv->device))->USBDeviceClose(dpriv->device);
941
1010
  if (kresult) {
942
- /* Log the fact that we had a problem closing the file, however failing a
943
- * close isn't really an error, so return success anyway */
944
- usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult));
1011
+ /* Log the fact that we had a problem closing the file, however failing a
1012
+ * close isn't really an error, so return success anyway */
1013
+ usbi_warn (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult));
945
1014
  }
946
1015
  }
947
-
948
- kresult = (*(dpriv->device))->Release(dpriv->device);
949
- if (kresult) {
950
- /* Log the fact that we had a problem closing the file, however failing a
951
- * close isn't really an error, so return success anyway */
952
- usbi_warn (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult));
953
- }
954
-
955
- dpriv->device = NULL;
956
1016
  }
957
1017
 
958
1018
  /* file descriptors are maintained per-instance */
@@ -964,7 +1024,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) {
964
1024
  }
965
1025
 
966
1026
  static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int *config) {
967
- struct darwin_device_priv *dpriv = (struct darwin_device_priv *)dev_handle->dev->os_priv;
1027
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
968
1028
 
969
1029
  *config = (int) dpriv->active_config;
970
1030
 
@@ -972,7 +1032,7 @@ static int darwin_get_configuration(struct libusb_device_handle *dev_handle, int
972
1032
  }
973
1033
 
974
1034
  static int darwin_set_configuration(struct libusb_device_handle *dev_handle, int config) {
975
- struct darwin_device_priv *dpriv = (struct darwin_device_priv *)dev_handle->dev->os_priv;
1035
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
976
1036
  IOReturn kresult;
977
1037
  int i;
978
1038
 
@@ -998,9 +1058,10 @@ static int darwin_set_configuration(struct libusb_device_handle *dev_handle, int
998
1058
 
999
1059
  static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_service_t *usbInterfacep) {
1000
1060
  IOUSBFindInterfaceRequest request;
1001
- uint8_t current_interface;
1002
1061
  kern_return_t kresult;
1003
1062
  io_iterator_t interface_iterator;
1063
+ UInt8 bInterfaceNumber;
1064
+ int ret;
1004
1065
 
1005
1066
  *usbInterfacep = IO_OBJECT_NULL;
1006
1067
 
@@ -1014,10 +1075,16 @@ static int darwin_get_interface (usb_device_t **darwin_device, uint8_t ifc, io_s
1014
1075
  if (kresult)
1015
1076
  return kresult;
1016
1077
 
1017
- for ( current_interface = 0 ; current_interface <= ifc ; current_interface++ ) {
1018
- *usbInterfacep = IOIteratorNext(interface_iterator);
1019
- if (current_interface != ifc)
1020
- (void) IOObjectRelease (*usbInterfacep);
1078
+ while ((*usbInterfacep = IOIteratorNext(interface_iterator))) {
1079
+ /* find the interface number */
1080
+ ret = get_ioregistry_value_number (*usbInterfacep, CFSTR("bInterfaceNumber"), kCFNumberSInt8Type,
1081
+ &bInterfaceNumber);
1082
+
1083
+ if (ret && bInterfaceNumber == ifc) {
1084
+ break;
1085
+ }
1086
+
1087
+ (void) IOObjectRelease (*usbInterfacep);
1021
1088
  }
1022
1089
 
1023
1090
  /* done with the interface iterator */
@@ -1051,7 +1118,7 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) {
1051
1118
  /* iterate through pipe references */
1052
1119
  for (i = 1 ; i <= numep ; i++) {
1053
1120
  kresult = (*(cInterface->interface))->GetPipeProperties(cInterface->interface, i, &direction, &number, &dont_care1,
1054
- &dont_care2, &dont_care3);
1121
+ &dont_care2, &dont_care3);
1055
1122
 
1056
1123
  if (kresult != kIOReturnSuccess) {
1057
1124
  usbi_err (HANDLE_CTX (dev_handle), "error getting pipe information for pipe %d: %s", i, darwin_error_str(kresult));
@@ -1070,7 +1137,7 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) {
1070
1137
  }
1071
1138
 
1072
1139
  static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int iface) {
1073
- struct darwin_device_priv *dpriv = (struct darwin_device_priv *)dev_handle->dev->os_priv;
1140
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1074
1141
  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)dev_handle->os_priv;
1075
1142
  io_service_t usbInterface = IO_OBJECT_NULL;
1076
1143
  IOReturn kresult;
@@ -1109,7 +1176,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
1109
1176
 
1110
1177
  /* get an interface to the device's interface */
1111
1178
  kresult = IOCreatePlugInInterfaceForService (usbInterface, kIOUSBInterfaceUserClientTypeID,
1112
- kIOCFPlugInInterfaceID, &plugInInterface, &score);
1179
+ kIOCFPlugInInterfaceID, &plugInInterface, &score);
1113
1180
 
1114
1181
  /* ignore release error */
1115
1182
  (void)IOObjectRelease (usbInterface);
@@ -1126,10 +1193,11 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i
1126
1193
 
1127
1194
  /* Do the actual claim */
1128
1195
  kresult = (*plugInInterface)->QueryInterface(plugInInterface,
1129
- CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
1130
- (LPVOID)&cInterface->interface);
1196
+ CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
1197
+ (LPVOID)&cInterface->interface);
1131
1198
  /* We no longer need the intermediate plug-in */
1132
- IODestroyPlugInInterface (plugInInterface);
1199
+ /* Use release instead of IODestroyPlugInInterface to avoid stopping IOServices associated with this device */
1200
+ (*plugInInterface)->Release (plugInInterface);
1133
1201
  if (kresult || !cInterface->interface) {
1134
1202
  usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult));
1135
1203
  return darwin_to_libusb (kresult);
@@ -1248,12 +1316,8 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c
1248
1316
 
1249
1317
  cInterface = &priv->interfaces[iface];
1250
1318
 
1251
- #if (InterfaceVersion < 190)
1252
- kresult = (*(cInterface->interface))->ClearPipeStall(cInterface->interface, pipeRef);
1253
- #else
1254
1319
  /* newer versions of darwin support clearing additional bits on the device's endpoint */
1255
1320
  kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
1256
- #endif
1257
1321
  if (kresult)
1258
1322
  usbi_warn (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult));
1259
1323
 
@@ -1261,18 +1325,59 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c
1261
1325
  }
1262
1326
 
1263
1327
  static int darwin_reset_device(struct libusb_device_handle *dev_handle) {
1264
- struct darwin_device_priv *dpriv = (struct darwin_device_priv *)dev_handle->dev->os_priv;
1328
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1329
+ IOUSBDeviceDescriptor descriptor;
1330
+ IOUSBConfigurationDescriptorPtr cached_configuration;
1331
+ IOUSBConfigurationDescriptor configuration;
1332
+ bool reenumerate = false;
1265
1333
  IOReturn kresult;
1334
+ int i;
1266
1335
 
1267
1336
  kresult = (*(dpriv->device))->ResetDevice (dpriv->device);
1268
- if (kresult)
1337
+ if (kresult) {
1269
1338
  usbi_err (HANDLE_CTX (dev_handle), "ResetDevice: %s", darwin_error_str (kresult));
1339
+ return darwin_to_libusb (kresult);
1340
+ }
1270
1341
 
1271
- return darwin_to_libusb (kresult);
1342
+ do {
1343
+ usbi_dbg ("darwin/reset_device: checking if device descriptor changed");
1344
+
1345
+ /* ignore return code. if we can't get a descriptor it might be worthwhile re-enumerating anway */
1346
+ (void) darwin_request_descriptor (dpriv->device, kUSBDeviceDesc, 0, &descriptor, sizeof (descriptor));
1347
+
1348
+ /* check if the device descriptor has changed */
1349
+ if (0 != memcmp (&dpriv->dev_descriptor, &descriptor, sizeof (descriptor))) {
1350
+ reenumerate = true;
1351
+ break;
1352
+ }
1353
+
1354
+ /* check if any configuration descriptor has changed */
1355
+ for (i = 0 ; i < descriptor.bNumConfigurations ; ++i) {
1356
+ usbi_dbg ("darwin/reset_device: checking if configuration descriptor %d changed", i);
1357
+
1358
+ (void) darwin_request_descriptor (dpriv->device, kUSBConfDesc, i, &configuration, sizeof (configuration));
1359
+ (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, i, &cached_configuration);
1360
+
1361
+ if (!cached_configuration || 0 != memcmp (cached_configuration, &configuration, sizeof (configuration))) {
1362
+ reenumerate = true;
1363
+ break;
1364
+ }
1365
+ }
1366
+ } while (0);
1367
+
1368
+ if (reenumerate) {
1369
+ usbi_dbg ("darwin/reset_device: device requires reenumeration");
1370
+ (void) (*(dpriv->device))->USBDeviceReEnumerate (dpriv->device, 0);
1371
+ return LIBUSB_ERROR_NOT_FOUND;
1372
+ }
1373
+
1374
+ usbi_dbg ("darwin/reset_device: device reset complete");
1375
+
1376
+ return LIBUSB_SUCCESS;
1272
1377
  }
1273
1378
 
1274
1379
  static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, int interface) {
1275
- struct darwin_device_priv *dpriv = (struct darwin_device_priv *)dev_handle->dev->os_priv;
1380
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(dev_handle->dev);
1276
1381
  io_service_t usbInterface;
1277
1382
  CFTypeRef driver;
1278
1383
  IOReturn kresult;
@@ -1311,7 +1416,15 @@ static int darwin_detach_kernel_driver (struct libusb_device_handle *dev_handle,
1311
1416
  }
1312
1417
 
1313
1418
  static void darwin_destroy_device(struct libusb_device *dev) {
1314
- (void)dev;
1419
+ struct darwin_device_priv *dpriv = (struct darwin_device_priv *) dev->os_priv;
1420
+
1421
+ if (dpriv->dev) {
1422
+ /* need to hold the lock in case this is the last reference to the device */
1423
+ usbi_mutex_lock(&darwin_cached_devices_lock);
1424
+ darwin_deref_cached_device (dpriv->dev);
1425
+ dpriv->dev = NULL;
1426
+ usbi_mutex_unlock(&darwin_cached_devices_lock);
1427
+ }
1315
1428
  }
1316
1429
 
1317
1430
  static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
@@ -1326,9 +1439,6 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
1326
1439
 
1327
1440
  struct darwin_interface *cInterface;
1328
1441
 
1329
- if (IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET)
1330
- return LIBUSB_ERROR_NOT_SUPPORTED;
1331
-
1332
1442
  if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) {
1333
1443
  usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface");
1334
1444
 
@@ -1338,33 +1448,38 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) {
1338
1448
  cInterface = &priv->interfaces[iface];
1339
1449
 
1340
1450
  (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
1341
- &transferType, &maxPacketSize, &interval);
1451
+ &transferType, &maxPacketSize, &interval);
1452
+
1453
+ if (0 != (transfer->length % maxPacketSize)) {
1454
+ /* do not need a zero packet */
1455
+ transfer->flags &= ~LIBUSB_TRANSFER_ADD_ZERO_PACKET;
1456
+ }
1342
1457
 
1343
1458
  /* submit the request */
1344
1459
  /* timeouts are unavailable on interrupt endpoints */
1345
1460
  if (transferType == kUSBInterrupt) {
1346
1461
  if (IS_XFERIN(transfer))
1347
1462
  ret = (*(cInterface->interface))->ReadPipeAsync(cInterface->interface, pipeRef, transfer->buffer,
1348
- transfer->length, darwin_async_io_callback, itransfer);
1463
+ transfer->length, darwin_async_io_callback, itransfer);
1349
1464
  else
1350
1465
  ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer,
1351
- transfer->length, darwin_async_io_callback, itransfer);
1466
+ transfer->length, darwin_async_io_callback, itransfer);
1352
1467
  } else {
1353
1468
  itransfer->flags |= USBI_TRANSFER_OS_HANDLES_TIMEOUT;
1354
1469
 
1355
1470
  if (IS_XFERIN(transfer))
1356
1471
  ret = (*(cInterface->interface))->ReadPipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
1357
- transfer->length, transfer->timeout, transfer->timeout,
1358
- darwin_async_io_callback, (void *)itransfer);
1472
+ transfer->length, transfer->timeout, transfer->timeout,
1473
+ darwin_async_io_callback, (void *)itransfer);
1359
1474
  else
1360
1475
  ret = (*(cInterface->interface))->WritePipeAsyncTO(cInterface->interface, pipeRef, transfer->buffer,
1361
- transfer->length, transfer->timeout, transfer->timeout,
1362
- darwin_async_io_callback, (void *)itransfer);
1476
+ transfer->length, transfer->timeout, transfer->timeout,
1477
+ darwin_async_io_callback, (void *)itransfer);
1363
1478
  }
1364
1479
 
1365
1480
  if (ret)
1366
1481
  usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", IS_XFERIN(transfer) ? "In" : "Out",
1367
- darwin_error_str(ret), ret);
1482
+ darwin_error_str(ret), ret);
1368
1483
 
1369
1484
  return darwin_to_libusb (ret);
1370
1485
  }
@@ -1374,11 +1489,12 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
1374
1489
  struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
1375
1490
  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv;
1376
1491
 
1377
- IOReturn kresult;
1378
- uint8_t pipeRef, iface;
1379
- UInt64 frame;
1380
- AbsoluteTime atTime;
1381
- int i;
1492
+ IOReturn kresult;
1493
+ uint8_t direction, number, interval, pipeRef, iface, transferType;
1494
+ uint16_t maxPacketSize;
1495
+ UInt64 frame;
1496
+ AbsoluteTime atTime;
1497
+ int i;
1382
1498
 
1383
1499
  struct darwin_interface *cInterface;
1384
1500
 
@@ -1408,6 +1524,10 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
1408
1524
 
1409
1525
  cInterface = &priv->interfaces[iface];
1410
1526
 
1527
+ /* determine the properties of this endpoint and the speed of the device */
1528
+ (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
1529
+ &transferType, &maxPacketSize, &interval);
1530
+
1411
1531
  /* Last but not least we need the bus frame number */
1412
1532
  kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime);
1413
1533
  if (kresult) {
@@ -1418,6 +1538,9 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
1418
1538
  return darwin_to_libusb (kresult);
1419
1539
  }
1420
1540
 
1541
+ (*(cInterface->interface))->GetPipeProperties (cInterface->interface, pipeRef, &direction, &number,
1542
+ &transferType, &maxPacketSize, &interval);
1543
+
1421
1544
  /* schedule for a frame a little in the future */
1422
1545
  frame += 4;
1423
1546
 
@@ -1427,18 +1550,23 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
1427
1550
  /* submit the request */
1428
1551
  if (IS_XFERIN(transfer))
1429
1552
  kresult = (*(cInterface->interface))->ReadIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame,
1430
- transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
1431
- itransfer);
1553
+ transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
1554
+ itransfer);
1432
1555
  else
1433
1556
  kresult = (*(cInterface->interface))->WriteIsochPipeAsync(cInterface->interface, pipeRef, transfer->buffer, frame,
1434
- transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
1435
- itransfer);
1557
+ transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
1558
+ itransfer);
1436
1559
 
1437
- cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets / 8;
1560
+ if (LIBUSB_SPEED_FULL == transfer->dev_handle->dev->speed)
1561
+ /* Full speed */
1562
+ cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1));
1563
+ else
1564
+ /* High/super speed */
1565
+ cInterface->frames[transfer->endpoint] = frame + transfer->num_iso_packets * (1 << (interval - 1)) / 8;
1438
1566
 
1439
1567
  if (kresult != kIOReturnSuccess) {
1440
1568
  usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", IS_XFERIN(transfer) ? "In" : "Out",
1441
- darwin_error_str(kresult));
1569
+ darwin_error_str(kresult));
1442
1570
  free (tpriv->isoc_framelist);
1443
1571
  tpriv->isoc_framelist = NULL;
1444
1572
  }
@@ -1449,7 +1577,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) {
1449
1577
  static int submit_control_transfer(struct usbi_transfer *itransfer) {
1450
1578
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1451
1579
  struct libusb_control_setup *setup = (struct libusb_control_setup *) transfer->buffer;
1452
- struct darwin_device_priv *dpriv = (struct darwin_device_priv *)transfer->dev_handle->dev->os_priv;
1580
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev);
1453
1581
  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv;
1454
1582
  struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer);
1455
1583
 
@@ -1515,7 +1643,7 @@ static int darwin_submit_transfer(struct usbi_transfer *itransfer) {
1515
1643
 
1516
1644
  static int cancel_control_transfer(struct usbi_transfer *itransfer) {
1517
1645
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1518
- struct darwin_device_priv *dpriv = (struct darwin_device_priv *)transfer->dev_handle->dev->os_priv;
1646
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev);
1519
1647
  IOReturn kresult;
1520
1648
 
1521
1649
  usbi_warn (ITRANSFER_CTX (itransfer), "aborting all transactions control pipe");
@@ -1530,7 +1658,7 @@ static int cancel_control_transfer(struct usbi_transfer *itransfer) {
1530
1658
 
1531
1659
  static int darwin_abort_transfers (struct usbi_transfer *itransfer) {
1532
1660
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1533
- struct darwin_device_priv *dpriv = (struct darwin_device_priv *)transfer->dev_handle->dev->os_priv;
1661
+ struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(transfer->dev_handle->dev);
1534
1662
  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv;
1535
1663
  struct darwin_interface *cInterface;
1536
1664
  uint8_t pipeRef, iface;
@@ -1554,13 +1682,8 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) {
1554
1682
 
1555
1683
  usbi_dbg ("calling clear pipe stall to clear the data toggle bit");
1556
1684
 
1557
- /* clear the data toggle bit */
1558
- #if (InterfaceVersion < 190)
1559
- kresult = (*(cInterface->interface))->ClearPipeStall(cInterface->interface, pipeRef);
1560
- #else
1561
1685
  /* newer versions of darwin support clearing additional bits on the device's endpoint */
1562
1686
  kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef);
1563
- #endif
1564
1687
 
1565
1688
  return darwin_to_libusb (kresult);
1566
1689
  }
@@ -1595,22 +1718,24 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0)
1595
1718
  struct usbi_transfer *itransfer = (struct usbi_transfer *)refcon;
1596
1719
  struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1597
1720
  struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv;
1598
- UInt32 message, size;
1721
+ struct darwin_msg_async_io_complete message = {.itransfer = itransfer, .result = result,
1722
+ .size = (UInt32) (uintptr_t) arg0};
1599
1723
 
1600
1724
  usbi_dbg ("an async io operation has completed");
1601
1725
 
1602
- /* The size should never be larger than 4 GB - Also see libusb bug #117 */
1603
- if ((intptr_t) arg0 > UINT32_MAX)
1604
- usbi_err (ITRANSFER_CTX (itransfer),
1605
- "async size truncation detected - please report this error");
1606
- size = (UInt32) (intptr_t) arg0;
1726
+ /* if requested write a zero packet */
1727
+ if (kIOReturnSuccess == result && IS_XFEROUT(transfer) && transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET) {
1728
+ struct darwin_interface *cInterface;
1729
+ uint8_t iface, pipeRef;
1730
+
1731
+ (void) ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface);
1732
+ cInterface = &priv->interfaces[iface];
1733
+
1734
+ (*(cInterface->interface))->WritePipe (cInterface->interface, pipeRef, transfer->buffer, 0);
1735
+ }
1607
1736
 
1608
1737
  /* send a completion message to the device's file descriptor */
1609
- message = MESSAGE_ASYNC_IO_COMPLETE;
1610
1738
  write (priv->fds[1], &message, sizeof (message));
1611
- write (priv->fds[1], &itransfer, sizeof (itransfer));
1612
- write (priv->fds[1], &result, sizeof (IOReturn));
1613
- write (priv->fds[1], &size, sizeof (size));
1614
1739
  }
1615
1740
 
1616
1741
  static int darwin_transfer_status (struct usbi_transfer *itransfer, kern_return_t result) {
@@ -1654,16 +1779,16 @@ static void darwin_handle_callback (struct usbi_transfer *itransfer, kern_return
1654
1779
  }
1655
1780
 
1656
1781
  usbi_dbg ("handling %s completion with kernel status %d",
1657
- isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", result);
1782
+ isControl ? "control" : isBulk ? "bulk" : isIsoc ? "isoc" : "interrupt", result);
1658
1783
 
1659
1784
  if (kIOReturnSuccess == result || kIOReturnUnderrun == result) {
1660
1785
  if (isIsoc && tpriv->isoc_framelist) {
1661
1786
  /* copy isochronous results back */
1662
1787
 
1663
1788
  for (i = 0; i < transfer->num_iso_packets ; i++) {
1664
- struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
1665
- lib_desc->status = darwin_to_libusb (tpriv->isoc_framelist[i].frStatus);
1666
- lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount;
1789
+ struct libusb_iso_packet_descriptor *lib_desc = &transfer->iso_packet_desc[i];
1790
+ lib_desc->status = darwin_to_libusb (tpriv->isoc_framelist[i].frStatus);
1791
+ lib_desc->actual_length = tpriv->isoc_framelist[i].frActCount;
1667
1792
  }
1668
1793
  } else if (!isIsoc)
1669
1794
  itransfer->transferred += io_size;
@@ -1674,66 +1799,35 @@ static void darwin_handle_callback (struct usbi_transfer *itransfer, kern_return
1674
1799
  }
1675
1800
 
1676
1801
  static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready) {
1677
- struct usbi_transfer *itransfer;
1678
- UInt32 io_size;
1679
- IOReturn kresult;
1802
+ struct darwin_msg_async_io_complete message;
1680
1803
  POLL_NFDS_TYPE i = 0;
1681
1804
  ssize_t ret;
1682
- UInt32 message;
1683
1805
 
1684
1806
  usbi_mutex_lock(&ctx->open_devs_lock);
1807
+
1685
1808
  for (i = 0; i < nfds && num_ready > 0; i++) {
1686
1809
  struct pollfd *pollfd = &fds[i];
1687
- struct libusb_device_handle *handle;
1688
- struct darwin_device_handle_priv *hpriv = NULL;
1689
1810
 
1690
- usbi_dbg ("checking fd %i with revents = %x", fds[i], pollfd->revents);
1811
+ usbi_dbg ("checking fd %i with revents = %x", pollfd->fd, pollfd->revents);
1691
1812
 
1692
1813
  if (!pollfd->revents)
1693
1814
  continue;
1694
1815
 
1695
1816
  num_ready--;
1696
- list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) {
1697
- hpriv = (struct darwin_device_handle_priv *)handle->os_priv;
1698
- if (hpriv->fds[0] == pollfd->fd)
1699
- break;
1700
- }
1701
- if (!hpriv)
1702
- continue;
1703
-
1704
- if (!(pollfd->revents & POLLERR)) {
1705
- ret = read (hpriv->fds[0], &message, sizeof (message));
1706
- if (ret < (ssize_t)sizeof (message))
1707
- continue;
1708
- } else
1709
- /* could not poll the device-- response is to delete the device (this seems a little heavy-handed) */
1710
- message = MESSAGE_DEVICE_GONE;
1711
-
1712
- switch (message) {
1713
- case MESSAGE_DEVICE_GONE:
1714
- /* remove the device's async port from the runloop */
1715
- if (hpriv->cfSource) {
1716
- if (libusb_darwin_acfl)
1717
- CFRunLoopRemoveSource (libusb_darwin_acfl, hpriv->cfSource, kCFRunLoopDefaultMode);
1718
- CFRelease (hpriv->cfSource);
1719
- hpriv->cfSource = NULL;
1720
- }
1721
-
1722
- usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->fds[0]);
1723
- usbi_handle_disconnect(handle);
1724
1817
 
1725
- /* done with this device */
1818
+ if (pollfd->revents & POLLERR) {
1819
+ /* this probably will never happen so ignore the error an move on. */
1726
1820
  continue;
1727
- case MESSAGE_ASYNC_IO_COMPLETE:
1728
- read (hpriv->fds[0], &itransfer, sizeof (itransfer));
1729
- read (hpriv->fds[0], &kresult, sizeof (IOReturn));
1730
- read (hpriv->fds[0], &io_size, sizeof (UInt32));
1821
+ }
1731
1822
 
1732
- darwin_handle_callback (itransfer, kresult, io_size);
1733
- break;
1734
- default:
1735
- usbi_warn (ctx, "unknown message received from device pipe");
1823
+ /* there is only one type of message */
1824
+ ret = read (pollfd->fd, &message, sizeof (message));
1825
+ if (ret < (ssize_t) sizeof (message)) {
1826
+ usbi_dbg ("WARNING: short read on async io completion pipe\n");
1827
+ continue;
1736
1828
  }
1829
+
1830
+ darwin_handle_callback (message.itransfer, message.result, message.size);
1737
1831
  }
1738
1832
 
1739
1833
  usbi_mutex_unlock(&ctx->open_devs_lock);
@@ -1767,41 +1861,42 @@ static int darwin_clock_gettime(int clk_id, struct timespec *tp) {
1767
1861
  }
1768
1862
 
1769
1863
  const struct usbi_os_backend darwin_backend = {
1770
- .name = "Darwin",
1771
- .init = darwin_init,
1772
- .exit = darwin_exit,
1773
- .get_device_list = darwin_get_device_list,
1774
- .get_device_descriptor = darwin_get_device_descriptor,
1775
- .get_active_config_descriptor = darwin_get_active_config_descriptor,
1776
- .get_config_descriptor = darwin_get_config_descriptor,
1777
-
1778
- .open = darwin_open,
1779
- .close = darwin_close,
1780
- .get_configuration = darwin_get_configuration,
1781
- .set_configuration = darwin_set_configuration,
1782
- .claim_interface = darwin_claim_interface,
1783
- .release_interface = darwin_release_interface,
1784
-
1785
- .set_interface_altsetting = darwin_set_interface_altsetting,
1786
- .clear_halt = darwin_clear_halt,
1787
- .reset_device = darwin_reset_device,
1788
-
1789
- .kernel_driver_active = darwin_kernel_driver_active,
1790
- .detach_kernel_driver = darwin_detach_kernel_driver,
1791
- .attach_kernel_driver = darwin_attach_kernel_driver,
1792
-
1793
- .destroy_device = darwin_destroy_device,
1794
-
1795
- .submit_transfer = darwin_submit_transfer,
1796
- .cancel_transfer = darwin_cancel_transfer,
1797
- .clear_transfer_priv = darwin_clear_transfer_priv,
1798
-
1799
- .handle_events = op_handle_events,
1800
-
1801
- .clock_gettime = darwin_clock_gettime,
1802
-
1803
- .device_priv_size = sizeof(struct darwin_device_priv),
1804
- .device_handle_priv_size = sizeof(struct darwin_device_handle_priv),
1805
- .transfer_priv_size = sizeof(struct darwin_transfer_priv),
1806
- .add_iso_packet_size = 0,
1864
+ .name = "Darwin",
1865
+ .caps = 0,
1866
+ .init = darwin_init,
1867
+ .exit = darwin_exit,
1868
+ .get_device_list = NULL, /* not needed */
1869
+ .get_device_descriptor = darwin_get_device_descriptor,
1870
+ .get_active_config_descriptor = darwin_get_active_config_descriptor,
1871
+ .get_config_descriptor = darwin_get_config_descriptor,
1872
+
1873
+ .open = darwin_open,
1874
+ .close = darwin_close,
1875
+ .get_configuration = darwin_get_configuration,
1876
+ .set_configuration = darwin_set_configuration,
1877
+ .claim_interface = darwin_claim_interface,
1878
+ .release_interface = darwin_release_interface,
1879
+
1880
+ .set_interface_altsetting = darwin_set_interface_altsetting,
1881
+ .clear_halt = darwin_clear_halt,
1882
+ .reset_device = darwin_reset_device,
1883
+
1884
+ .kernel_driver_active = darwin_kernel_driver_active,
1885
+ .detach_kernel_driver = darwin_detach_kernel_driver,
1886
+ .attach_kernel_driver = darwin_attach_kernel_driver,
1887
+
1888
+ .destroy_device = darwin_destroy_device,
1889
+
1890
+ .submit_transfer = darwin_submit_transfer,
1891
+ .cancel_transfer = darwin_cancel_transfer,
1892
+ .clear_transfer_priv = darwin_clear_transfer_priv,
1893
+
1894
+ .handle_events = op_handle_events,
1895
+
1896
+ .clock_gettime = darwin_clock_gettime,
1897
+
1898
+ .device_priv_size = sizeof(struct darwin_device_priv),
1899
+ .device_handle_priv_size = sizeof(struct darwin_device_handle_priv),
1900
+ .transfer_priv_size = sizeof(struct darwin_transfer_priv),
1901
+ .add_iso_packet_size = 0,
1807
1902
  };