libusb 0.3.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/Gemfile +1 -0
- data/History.md +10 -0
- data/README.md +19 -6
- data/Rakefile +1 -1
- data/ext/extconf.rb +17 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/AUTHORS +18 -6
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/COPYING +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ChangeLog +58 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/INSTALL +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.am +6 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.in +248 -174
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/NEWS +2 -2
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/PORTING +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/README +2 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/TODO +0 -0
- data/ext/libusbx-1.0.17/Xcode/common.xcconfig +40 -0
- data/ext/libusbx-1.0.17/Xcode/config.h +28 -0
- data/ext/libusbx-1.0.17/Xcode/debug.xcconfig +29 -0
- data/ext/libusbx-1.0.17/Xcode/libusbx.xcconfig +21 -0
- data/ext/libusbx-1.0.17/Xcode/libusbx.xcodeproj/project.pbxproj +864 -0
- data/ext/libusbx-1.0.17/Xcode/libusbx_debug.xcconfig +21 -0
- data/ext/libusbx-1.0.17/Xcode/libusbx_release.xcconfig +21 -0
- data/ext/libusbx-1.0.17/Xcode/release.xcconfig +29 -0
- data/ext/libusbx-1.0.17/aclocal.m4 +1112 -0
- data/ext/libusbx-1.0.17/android/README +114 -0
- data/ext/libusbx-1.0.17/android/config.h +90 -0
- data/ext/libusbx-1.0.17/android/jni/Android.mk +23 -0
- data/ext/libusbx-1.0.17/android/jni/Application.mk +19 -0
- data/ext/libusbx-1.0.17/android/jni/examples.mk +134 -0
- data/ext/libusbx-1.0.17/android/jni/libusb.mk +54 -0
- data/ext/libusbx-1.0.17/android/jni/tests.mk +56 -0
- data/ext/libusbx-1.0.17/compile +347 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.guess +164 -130
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.h.in +37 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.sub +174 -89
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure +723 -302
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure.ac +71 -20
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/depcomp +345 -185
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.am +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.in +95 -32
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/doxygen.cfg.in +1 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.am +5 -4
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.in +208 -104
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp.c +1 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp_threaded.c +1 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.c +188 -8
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.h +18 -5
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/fxload.c +90 -64
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.c +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.h +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt1.c +0 -0
- data/ext/libusbx-1.0.17/examples/hotplugtest.c +97 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/listdevs.c +12 -4
- data/ext/libusbx-1.0.17/examples/sam3u_benchmark.c +193 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/xusb.c +106 -49
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/install-sh +21 -14
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb-1.0.pc.in +1 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/Makefile.am +29 -10
- data/ext/libusbx-1.0.17/libusb/Makefile.in +914 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/core.c +378 -87
- data/ext/libusbx-1.0.17/libusb/descriptor.c +1199 -0
- data/ext/libusbx-1.0.17/libusb/hotplug.c +322 -0
- data/ext/libusbx-1.0.17/libusb/hotplug.h +82 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/io.c +182 -62
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.def +32 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.rc +2 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb.h +481 -32
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusbi.h +135 -38
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.c +591 -496
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.h +39 -46
- data/ext/libusbx-1.0.17/libusb/os/linux_netlink.c +345 -0
- data/ext/libusbx-1.0.17/libusb/os/linux_udev.c +306 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.c +653 -617
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.h +32 -0
- data/ext/{libusbx-1.0.14/libusb/os/openbsd_usb.c → libusbx-1.0.17/libusb/os/netbsd_usb.c} +70 -63
- data/ext/libusbx-1.0.17/libusb/os/openbsd_usb.c +823 -0
- data/ext/libusbx-1.0.17/libusb/os/poll_posix.c +51 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_posix.h +2 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.c +85 -106
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.h +14 -3
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.c +3 -1
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.h +0 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.c +6 -5
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.h +0 -0
- data/ext/libusbx-1.0.17/libusb/os/wince_usb.c +1026 -0
- data/ext/libusbx-1.0.17/libusb/os/wince_usb.h +131 -0
- data/ext/libusbx-1.0.17/libusb/os/windows_common.h +108 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.c +92 -57
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.h +2 -63
- data/ext/libusbx-1.0.17/libusb/strerror.c +184 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/sync.c +24 -38
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/version.h +1 -1
- data/ext/libusbx-1.0.17/libusb/version_nano.h +1 -0
- data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ltmain.sh +60 -41
- data/ext/{libusbx-1.0.14/aclocal.m4 → libusbx-1.0.17/m4/libtool.m4} +229 -1723
- data/ext/libusbx-1.0.17/m4/ltoptions.m4 +384 -0
- data/ext/libusbx-1.0.17/m4/ltsugar.m4 +123 -0
- data/ext/libusbx-1.0.17/m4/ltversion.m4 +23 -0
- data/ext/libusbx-1.0.17/m4/lt~obsolete.m4 +98 -0
- data/ext/libusbx-1.0.17/missing +215 -0
- data/ext/libusbx-1.0.17/tests/Makefile.am +6 -0
- data/ext/libusbx-1.0.17/tests/Makefile.in +583 -0
- data/ext/libusbx-1.0.17/tests/libusbx_testlib.h +107 -0
- data/ext/libusbx-1.0.17/tests/stress.c +160 -0
- data/ext/libusbx-1.0.17/tests/testlib.c +276 -0
- data/lib/libusb.rb +4 -0
- data/lib/libusb/call.rb +43 -1
- data/lib/libusb/constants.rb +5 -0
- data/lib/libusb/context.rb +100 -0
- data/lib/libusb/dev_handle.rb +27 -0
- data/lib/libusb/device.rb +10 -4
- data/lib/libusb/version_gem.rb +1 -1
- data/test/test_libusb_capability.rb +2 -2
- data/test/test_libusb_compat.rb +2 -2
- data/test/test_libusb_compat_mass_storage.rb +2 -2
- data/test/test_libusb_descriptors.rb +4 -2
- data/test/test_libusb_event_machine.rb +2 -2
- data/test/test_libusb_gc.rb +2 -2
- data/test/test_libusb_hotplug.rb +115 -0
- data/test/test_libusb_iso_transfer.rb +3 -3
- data/test/test_libusb_mass_storage.rb +6 -16
- data/test/test_libusb_mass_storage2.rb +26 -3
- data/test/test_libusb_structs.rb +2 -2
- data/test/test_libusb_threads.rb +2 -2
- data/test/test_libusb_version.rb +2 -2
- metadata +127 -68
- metadata.gz.sig +0 -0
- data/ext/libusbx-1.0.14/THANKS +0 -7
- data/ext/libusbx-1.0.14/compile +0 -143
- data/ext/libusbx-1.0.14/libusb/Makefile.in +0 -721
- data/ext/libusbx-1.0.14/libusb/descriptor.c +0 -731
- data/ext/libusbx-1.0.14/libusb/version_nano.h +0 -1
- 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
|
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
|
-
#
|
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
|
-
*
|
61
|
-
*
|
62
|
-
*
|
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)(
|
83
|
+
((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member)))
|
66
84
|
|
67
85
|
/* Get each entry from a list
|
68
|
-
*
|
69
|
-
*
|
70
|
-
*
|
71
|
-
*
|
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
|
213
|
+
/* Internal abstraction for thread synchronization */
|
196
214
|
#if defined(THREADS_POSIX)
|
197
|
-
#include
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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-
|
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
|
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; /*
|
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
|
-
|
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
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
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,
|
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
|
-
|
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 **
|
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
|
-
|
213
|
-
|
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
|
-
|
225
|
-
|
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
|
-
|
250
|
-
|
251
|
-
(*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
|
262
|
-
|
263
|
-
|
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
|
-
|
267
|
-
if (kresult)
|
268
|
-
return kresult;
|
257
|
+
usbi_mutex_lock(&active_contexts_lock);
|
269
258
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
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
|
-
(
|
265
|
+
IOObjectRelease(service);
|
276
266
|
}
|
277
267
|
|
278
|
-
|
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
|
290
|
-
struct
|
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
|
-
|
296
|
-
|
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
|
-
|
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
|
-
|
312
|
-
CFNumberGetValue(locationCF, kCFNumberLongType, &location);
|
313
|
-
|
314
|
-
CFRelease (locationCF);
|
286
|
+
usbi_mutex_lock(&active_contexts_lock);
|
315
287
|
|
316
|
-
|
317
|
-
|
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
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
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(&
|
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 *
|
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-
|
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)
|
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
|
-
|
380
|
-
|
381
|
-
|
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
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
504
|
+
struct darwin_cached_device *priv = DARWIN_CACHED_DEVICE(dev);
|
501
505
|
IOUSBConfigurationDescriptorPtr desc;
|
502
506
|
IOReturn kresult;
|
503
|
-
|
507
|
+
int ret;
|
504
508
|
|
505
|
-
if (!priv)
|
509
|
+
if (!priv || !priv->device)
|
506
510
|
return LIBUSB_ERROR_OTHER;
|
507
511
|
|
508
|
-
|
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
|
-
|
533
|
-
|
524
|
+
ret = darwin_to_libusb (kresult);
|
525
|
+
if (ret != LIBUSB_SUCCESS)
|
526
|
+
return ret;
|
534
527
|
|
535
|
-
return
|
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
|
540
|
-
|
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 (
|
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
|
-
|
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 (
|
574
|
+
if (dev->dev_descriptor.bNumConfigurations == 1)
|
582
575
|
/* to avoid problems with some devices get the configurations value from the configuration descriptor */
|
583
|
-
|
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, &
|
579
|
+
(*darwin_device)->GetConfiguration (darwin_device, &dev->active_config);
|
587
580
|
} else
|
588
581
|
/* not configured */
|
589
|
-
|
582
|
+
dev->active_config = 0;
|
590
583
|
|
591
|
-
usbi_dbg ("active config: %u, first config: %u",
|
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
|
597
|
-
|
598
|
-
|
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
|
-
|
611
|
-
|
612
|
-
|
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
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
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 (
|
637
|
-
|
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
|
-
|
644
|
+
usbi_dbg("descriptor appears to be invalid. resetting configuration before trying again...");
|
641
645
|
|
642
|
-
|
643
|
-
|
646
|
+
/* set the first configuration */
|
647
|
+
(*device)->SetConfiguration(device, 1);
|
644
648
|
|
645
|
-
|
646
|
-
|
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
|
-
|
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
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
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",
|
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",
|
697
|
-
|
698
|
-
return
|
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 (
|
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
|
-
|
721
|
-
return
|
712
|
+
idProduct, libusb_le16_to_cpu (dev->dev_descriptor.idProduct));
|
713
|
+
return LIBUSB_ERROR_NO_DEVICE;
|
722
714
|
}
|
723
715
|
|
724
|
-
|
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
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
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
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
|
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 (
|
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
|
-
|
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
|
-
|
756
|
-
|
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
|
-
|
760
|
-
|
761
|
-
|
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
|
-
|
765
|
-
|
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
|
-
|
770
|
-
|
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
|
-
|
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
|
-
|
777
|
-
dev->
|
778
|
-
|
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
|
-
|
890
|
+
dev->port_number, (void *) dev->parent_dev, priv->dev->sys_path);
|
811
891
|
} while (0);
|
812
892
|
|
813
|
-
if (
|
814
|
-
|
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
|
820
|
-
io_iterator_t
|
821
|
-
|
822
|
-
kern_return_t
|
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 ((
|
832
|
-
(void) process_new_device (ctx,
|
911
|
+
while ((service = IOIteratorNext (deviceIterator))) {
|
912
|
+
(void) process_new_device (ctx, service);
|
833
913
|
|
834
|
-
(
|
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
|
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
|
-
|
864
|
-
|
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
|
-
|
876
|
-
|
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
|
-
|
881
|
-
|
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
|
-
|
884
|
-
|
948
|
+
if (priv->is_open) {
|
949
|
+
(*(dpriv->device))->USBDeviceClose (dpriv->device);
|
885
950
|
}
|
886
951
|
|
887
|
-
priv->is_open =
|
888
|
-
|
889
|
-
CFRetain (libusb_darwin_acfl);
|
952
|
+
priv->is_open = 0;
|
890
953
|
|
891
|
-
|
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
|
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
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
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
|
-
|
943
|
-
|
944
|
-
|
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
|
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
|
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
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
1130
|
-
|
1196
|
+
CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
|
1197
|
+
(LPVOID)&cInterface->interface);
|
1131
1198
|
/* We no longer need the intermediate plug-in */
|
1132
|
-
IODestroyPlugInInterface
|
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
|
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
|
-
|
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
|
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
|
-
(
|
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
|
-
|
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
|
-
|
1463
|
+
transfer->length, darwin_async_io_callback, itransfer);
|
1349
1464
|
else
|
1350
1465
|
ret = (*(cInterface->interface))->WritePipeAsync(cInterface->interface, pipeRef, transfer->buffer,
|
1351
|
-
|
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
|
-
|
1358
|
-
|
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
|
-
|
1362
|
-
|
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
|
-
|
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
|
1378
|
-
uint8_t
|
1379
|
-
|
1380
|
-
|
1381
|
-
|
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
|
-
|
1431
|
-
|
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
|
-
|
1435
|
-
|
1557
|
+
transfer->num_iso_packets, tpriv->isoc_framelist, darwin_async_io_callback,
|
1558
|
+
itransfer);
|
1436
1559
|
|
1437
|
-
|
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
|
-
|
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
|
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
|
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
|
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
|
-
|
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
|
-
/*
|
1603
|
-
if ((
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
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
|
-
|
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
|
-
|
1665
|
-
|
1666
|
-
|
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
|
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",
|
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
|
-
|
1818
|
+
if (pollfd->revents & POLLERR) {
|
1819
|
+
/* this probably will never happen so ignore the error an move on. */
|
1726
1820
|
continue;
|
1727
|
-
|
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
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
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
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1776
|
-
|
1777
|
-
|
1778
|
-
|
1779
|
-
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
1795
|
-
|
1796
|
-
|
1797
|
-
|
1798
|
-
|
1799
|
-
|
1800
|
-
|
1801
|
-
|
1802
|
-
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
1806
|
-
|
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
|
};
|