libusb 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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
  };