libusb 0.3.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Gemfile +1 -0
  5. data/History.md +10 -0
  6. data/README.md +19 -6
  7. data/Rakefile +1 -1
  8. data/ext/extconf.rb +17 -1
  9. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/AUTHORS +18 -6
  10. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/COPYING +0 -0
  11. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ChangeLog +58 -1
  12. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/INSTALL +0 -0
  13. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.am +6 -1
  14. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.in +248 -174
  15. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/NEWS +2 -2
  16. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/PORTING +0 -0
  17. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/README +2 -1
  18. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/TODO +0 -0
  19. data/ext/libusbx-1.0.17/Xcode/common.xcconfig +40 -0
  20. data/ext/libusbx-1.0.17/Xcode/config.h +28 -0
  21. data/ext/libusbx-1.0.17/Xcode/debug.xcconfig +29 -0
  22. data/ext/libusbx-1.0.17/Xcode/libusbx.xcconfig +21 -0
  23. data/ext/libusbx-1.0.17/Xcode/libusbx.xcodeproj/project.pbxproj +864 -0
  24. data/ext/libusbx-1.0.17/Xcode/libusbx_debug.xcconfig +21 -0
  25. data/ext/libusbx-1.0.17/Xcode/libusbx_release.xcconfig +21 -0
  26. data/ext/libusbx-1.0.17/Xcode/release.xcconfig +29 -0
  27. data/ext/libusbx-1.0.17/aclocal.m4 +1112 -0
  28. data/ext/libusbx-1.0.17/android/README +114 -0
  29. data/ext/libusbx-1.0.17/android/config.h +90 -0
  30. data/ext/libusbx-1.0.17/android/jni/Android.mk +23 -0
  31. data/ext/libusbx-1.0.17/android/jni/Application.mk +19 -0
  32. data/ext/libusbx-1.0.17/android/jni/examples.mk +134 -0
  33. data/ext/libusbx-1.0.17/android/jni/libusb.mk +54 -0
  34. data/ext/libusbx-1.0.17/android/jni/tests.mk +56 -0
  35. data/ext/libusbx-1.0.17/compile +347 -0
  36. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.guess +164 -130
  37. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.h.in +37 -1
  38. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.sub +174 -89
  39. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure +723 -302
  40. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure.ac +71 -20
  41. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/depcomp +345 -185
  42. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.am +0 -0
  43. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.in +95 -32
  44. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/doxygen.cfg.in +1 -1
  45. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.am +5 -4
  46. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.in +208 -104
  47. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp.c +1 -1
  48. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp_threaded.c +1 -1
  49. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.c +188 -8
  50. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.h +18 -5
  51. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/fxload.c +90 -64
  52. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.c +0 -0
  53. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.h +0 -0
  54. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt1.c +0 -0
  55. data/ext/libusbx-1.0.17/examples/hotplugtest.c +97 -0
  56. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/listdevs.c +12 -4
  57. data/ext/libusbx-1.0.17/examples/sam3u_benchmark.c +193 -0
  58. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/xusb.c +106 -49
  59. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/install-sh +21 -14
  60. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb-1.0.pc.in +1 -1
  61. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/Makefile.am +29 -10
  62. data/ext/libusbx-1.0.17/libusb/Makefile.in +914 -0
  63. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/core.c +378 -87
  64. data/ext/libusbx-1.0.17/libusb/descriptor.c +1199 -0
  65. data/ext/libusbx-1.0.17/libusb/hotplug.c +322 -0
  66. data/ext/libusbx-1.0.17/libusb/hotplug.h +82 -0
  67. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/io.c +182 -62
  68. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.def +32 -0
  69. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.rc +2 -0
  70. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb.h +481 -32
  71. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusbi.h +135 -38
  72. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.c +591 -496
  73. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.h +39 -46
  74. data/ext/libusbx-1.0.17/libusb/os/linux_netlink.c +345 -0
  75. data/ext/libusbx-1.0.17/libusb/os/linux_udev.c +306 -0
  76. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.c +653 -617
  77. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.h +32 -0
  78. data/ext/{libusbx-1.0.14/libusb/os/openbsd_usb.c → libusbx-1.0.17/libusb/os/netbsd_usb.c} +70 -63
  79. data/ext/libusbx-1.0.17/libusb/os/openbsd_usb.c +823 -0
  80. data/ext/libusbx-1.0.17/libusb/os/poll_posix.c +51 -0
  81. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_posix.h +2 -1
  82. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.c +85 -106
  83. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.h +14 -3
  84. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.c +3 -1
  85. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.h +0 -0
  86. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.c +6 -5
  87. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.h +0 -0
  88. data/ext/libusbx-1.0.17/libusb/os/wince_usb.c +1026 -0
  89. data/ext/libusbx-1.0.17/libusb/os/wince_usb.h +131 -0
  90. data/ext/libusbx-1.0.17/libusb/os/windows_common.h +108 -0
  91. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.c +92 -57
  92. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.h +2 -63
  93. data/ext/libusbx-1.0.17/libusb/strerror.c +184 -0
  94. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/sync.c +24 -38
  95. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/version.h +1 -1
  96. data/ext/libusbx-1.0.17/libusb/version_nano.h +1 -0
  97. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ltmain.sh +60 -41
  98. data/ext/{libusbx-1.0.14/aclocal.m4 → libusbx-1.0.17/m4/libtool.m4} +229 -1723
  99. data/ext/libusbx-1.0.17/m4/ltoptions.m4 +384 -0
  100. data/ext/libusbx-1.0.17/m4/ltsugar.m4 +123 -0
  101. data/ext/libusbx-1.0.17/m4/ltversion.m4 +23 -0
  102. data/ext/libusbx-1.0.17/m4/lt~obsolete.m4 +98 -0
  103. data/ext/libusbx-1.0.17/missing +215 -0
  104. data/ext/libusbx-1.0.17/tests/Makefile.am +6 -0
  105. data/ext/libusbx-1.0.17/tests/Makefile.in +583 -0
  106. data/ext/libusbx-1.0.17/tests/libusbx_testlib.h +107 -0
  107. data/ext/libusbx-1.0.17/tests/stress.c +160 -0
  108. data/ext/libusbx-1.0.17/tests/testlib.c +276 -0
  109. data/lib/libusb.rb +4 -0
  110. data/lib/libusb/call.rb +43 -1
  111. data/lib/libusb/constants.rb +5 -0
  112. data/lib/libusb/context.rb +100 -0
  113. data/lib/libusb/dev_handle.rb +27 -0
  114. data/lib/libusb/device.rb +10 -4
  115. data/lib/libusb/version_gem.rb +1 -1
  116. data/test/test_libusb_capability.rb +2 -2
  117. data/test/test_libusb_compat.rb +2 -2
  118. data/test/test_libusb_compat_mass_storage.rb +2 -2
  119. data/test/test_libusb_descriptors.rb +4 -2
  120. data/test/test_libusb_event_machine.rb +2 -2
  121. data/test/test_libusb_gc.rb +2 -2
  122. data/test/test_libusb_hotplug.rb +115 -0
  123. data/test/test_libusb_iso_transfer.rb +3 -3
  124. data/test/test_libusb_mass_storage.rb +6 -16
  125. data/test/test_libusb_mass_storage2.rb +26 -3
  126. data/test/test_libusb_structs.rb +2 -2
  127. data/test/test_libusb_threads.rb +2 -2
  128. data/test/test_libusb_version.rb +2 -2
  129. metadata +127 -68
  130. metadata.gz.sig +0 -0
  131. data/ext/libusbx-1.0.14/THANKS +0 -7
  132. data/ext/libusbx-1.0.14/compile +0 -143
  133. data/ext/libusbx-1.0.14/libusb/Makefile.in +0 -721
  134. data/ext/libusbx-1.0.14/libusb/descriptor.c +0 -731
  135. data/ext/libusbx-1.0.14/libusb/version_nano.h +0 -1
  136. data/ext/libusbx-1.0.14/missing +0 -376
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * darwin backend for libusbx 1.0
3
- * Copyright © 2008-2009 Nathan Hjelm <hjelmn@users.sourceforge.net>
3
+ * Copyright © 2008-2013 Nathan Hjelm <hjelmn@users.sourceforge.net>
4
4
  *
5
5
  * This library is free software; you can redistribute it and/or
6
6
  * modify it under the terms of the GNU Lesser General Public
@@ -28,7 +28,19 @@
28
28
  #include <IOKit/IOCFPlugIn.h>
29
29
 
30
30
  /* IOUSBInterfaceInferface */
31
- #if defined (kIOUSBInterfaceInterfaceID300)
31
+ #if defined (kIOUSBInterfaceInterfaceID550)
32
+
33
+ #define usb_interface_t IOUSBInterfaceInterface550
34
+ #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550
35
+ #define InterfaceVersion 550
36
+
37
+ #elif defined (kIOUSBInterfaceInterfaceID500)
38
+
39
+ #define usb_interface_t IOUSBInterfaceInterface500
40
+ #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500
41
+ #define InterfaceVersion 500
42
+
43
+ #elif defined (kIOUSBInterfaceInterfaceID300)
32
44
 
33
45
  #define usb_interface_t IOUSBInterfaceInterface300
34
46
  #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300
@@ -46,24 +58,6 @@
46
58
  #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220
47
59
  #define InterfaceVersion 220
48
60
 
49
- #elif defined (kIOUSBInterfaceInterfaceID197)
50
-
51
- #define usb_interface_t IOUSBInterfaceInterface197
52
- #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID197
53
- #define InterfaceVersion 197
54
-
55
- #elif defined (kIOUSBInterfaceInterfaceID190)
56
-
57
- #define usb_interface_t IOUSBInterfaceInterface190
58
- #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID190
59
- #define InterfaceVersion 190
60
-
61
- #elif defined (kIOUSBInterfaceInterfaceID182)
62
-
63
- #define usb_interface_t IOUSBInterfaceInterface182
64
- #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID182
65
- #define InterfaceVersion 182
66
-
67
61
  #else
68
62
 
69
63
  #error "IOUSBFamily is too old. Please upgrade your OS"
@@ -71,7 +65,13 @@
71
65
  #endif
72
66
 
73
67
  /* IOUSBDeviceInterface */
74
- #if defined (kIOUSBDeviceInterfaceID320)
68
+ #if defined (kIOUSBDeviceInterfaceID500)
69
+
70
+ #define usb_device_t IOUSBDeviceInterface500
71
+ #define DeviceInterfaceID kIOUSBDeviceInterfaceID500
72
+ #define DeviceVersion 500
73
+
74
+ #elif defined (kIOUSBDeviceInterfaceID320)
75
75
 
76
76
  #define usb_device_t IOUSBDeviceInterface320
77
77
  #define DeviceInterfaceID kIOUSBDeviceInterfaceID320
@@ -89,24 +89,11 @@
89
89
  #define DeviceInterfaceID kIOUSBDeviceInterfaceID245
90
90
  #define DeviceVersion 245
91
91
 
92
- #elif defined (kIOUSBDeviceInterfaceID197)
93
-
92
+ #elif defined (kIOUSBDeviceInterfaceID220)
94
93
  #define usb_device_t IOUSBDeviceInterface197
95
94
  #define DeviceInterfaceID kIOUSBDeviceInterfaceID197
96
95
  #define DeviceVersion 197
97
96
 
98
- #elif defined (kIOUSBDeviceInterfaceID187)
99
-
100
- #define usb_device_t IOUSBDeviceInterface187
101
- #define DeviceInterfaceID kIOUSBDeviceInterfaceID187
102
- #define DeviceVersion 187
103
-
104
- #elif defined (kIOUSBDeviceInterfaceID182)
105
-
106
- #define usb_device_t IOUSBDeviceInterface182
107
- #define DeviceInterfaceID kIOUSBDeviceInterfaceID182
108
- #define DeviceVersion 182
109
-
110
97
  #else
111
98
 
112
99
  #error "IOUSBFamily is too old. Please upgrade your OS"
@@ -121,13 +108,23 @@ typedef IOCFPlugInInterface *io_cf_plugin_ref_t;
121
108
  typedef IONotificationPortRef io_notification_port_t;
122
109
 
123
110
  /* private structures */
124
- struct darwin_device_priv {
111
+ struct darwin_cached_device {
112
+ struct list_head list;
125
113
  IOUSBDeviceDescriptor dev_descriptor;
126
114
  UInt32 location;
115
+ UInt64 parent_session;
116
+ UInt64 session;
117
+ UInt16 address;
127
118
  char sys_path[21];
128
119
  usb_device_t **device;
129
120
  int open_count;
130
- UInt8 first_config, active_config;
121
+ UInt8 first_config, active_config, port;
122
+ int can_enumerate;
123
+ int refcount;
124
+ };
125
+
126
+ struct darwin_device_priv {
127
+ struct darwin_cached_device *dev;
131
128
  };
132
129
 
133
130
  struct darwin_device_handle_priv {
@@ -150,20 +147,16 @@ struct darwin_transfer_priv {
150
147
  int num_iso_packets;
151
148
 
152
149
  /* Control */
153
- #if !defined (LIBUSB_NO_TIMEOUT_DEVICE)
154
150
  IOUSBDevRequestTO req;
155
- #else
156
- IOUSBDevRequest req;
157
- #endif
158
151
 
159
152
  /* Bulk */
160
153
  };
161
154
 
162
- enum {
163
- MESSAGE_DEVICE_GONE,
164
- MESSAGE_ASYNC_IO_COMPLETE
155
+ /* structure for signaling io completion */
156
+ struct darwin_msg_async_io_complete {
157
+ struct usbi_transfer *itransfer;
158
+ IOReturn result;
159
+ UInt32 size;
165
160
  };
166
161
 
167
-
168
-
169
162
  #endif
@@ -0,0 +1,345 @@
1
+ /* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */
2
+ /*
3
+ * Linux usbfs backend for libusb
4
+ * Copyright (C) 2007-2009 Daniel Drake <dsd@gentoo.org>
5
+ * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
6
+ * Copyright (c) 2013 Nathan Hjelm <hjelmn@mac.com>
7
+ *
8
+ * This library is free software; you can redistribute it and/or
9
+ * modify it under the terms of the GNU Lesser General Public
10
+ * License as published by the Free Software Foundation; either
11
+ * version 2.1 of the License, or (at your option) any later version.
12
+ *
13
+ * This library is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
+ * Lesser General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU Lesser General Public
19
+ * License along with this library; if not, write to the Free Software
20
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
+ */
22
+
23
+ #include "config.h"
24
+ #include "libusb.h"
25
+ #include "libusbi.h"
26
+ #include "linux_usbfs.h"
27
+
28
+ #include <ctype.h>
29
+ #include <dirent.h>
30
+ #include <errno.h>
31
+ #include <fcntl.h>
32
+ #include <poll.h>
33
+ #include <stdio.h>
34
+ #include <stdlib.h>
35
+ #include <string.h>
36
+ #include <sys/types.h>
37
+
38
+ #ifdef HAVE_ASM_TYPES_H
39
+ #include <asm/types.h>
40
+ #endif
41
+
42
+ #ifdef HAVE_SYS_SOCKET_H
43
+ #include <sys/socket.h>
44
+ #endif
45
+
46
+ #include <arpa/inet.h>
47
+
48
+ #ifdef HAVE_LINUX_NETLINK_H
49
+ #include <linux/netlink.h>
50
+ #endif
51
+
52
+ #ifdef HAVE_LINUX_FILTER_H
53
+ #include <linux/filter.h>
54
+ #endif
55
+
56
+ #define KERNEL 1
57
+
58
+ static int linux_netlink_socket = -1;
59
+ static int netlink_control_pipe[2] = { -1, -1 };
60
+ static pthread_t libusb_linux_event_thread;
61
+
62
+ static void *linux_netlink_event_thread_main(void *arg);
63
+
64
+ struct sockaddr_nl snl = { .nl_family=AF_NETLINK, .nl_groups=KERNEL };
65
+
66
+ static int set_fd_cloexec_nb (int fd)
67
+ {
68
+ int flags;
69
+
70
+ #if defined(FD_CLOEXEC)
71
+ flags = fcntl (linux_netlink_socket, F_GETFD);
72
+ if (0 > flags) {
73
+ return -1;
74
+ }
75
+
76
+ if (!(flags & FD_CLOEXEC)) {
77
+ fcntl (linux_netlink_socket, F_SETFD, flags | FD_CLOEXEC);
78
+ }
79
+ #endif
80
+
81
+ flags = fcntl (linux_netlink_socket, F_GETFL);
82
+ if (0 > flags) {
83
+ return -1;
84
+ }
85
+
86
+ if (!(flags & O_NONBLOCK)) {
87
+ fcntl (linux_netlink_socket, F_SETFL, flags | O_NONBLOCK);
88
+ }
89
+
90
+ return 0;
91
+ }
92
+
93
+ int linux_netlink_start_event_monitor(void)
94
+ {
95
+ int socktype = SOCK_RAW;
96
+ int ret;
97
+
98
+ snl.nl_groups = KERNEL;
99
+
100
+ #if defined(SOCK_CLOEXEC)
101
+ socktype |= SOCK_CLOEXEC;
102
+ #endif
103
+ #if defined(SOCK_NONBLOCK)
104
+ socktype |= SOCK_NONBLOCK;
105
+ #endif
106
+
107
+ linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
108
+ if (-1 == linux_netlink_socket && EINVAL == errno) {
109
+ linux_netlink_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
110
+ }
111
+
112
+ if (-1 == linux_netlink_socket) {
113
+ return LIBUSB_ERROR_OTHER;
114
+ }
115
+
116
+ ret = set_fd_cloexec_nb (linux_netlink_socket);
117
+ if (0 != ret) {
118
+ close (linux_netlink_socket);
119
+ linux_netlink_socket = -1;
120
+ return LIBUSB_ERROR_OTHER;
121
+ }
122
+
123
+ ret = bind(linux_netlink_socket, (struct sockaddr *) &snl, sizeof(snl));
124
+ if (0 != ret) {
125
+ close(linux_netlink_socket);
126
+ return LIBUSB_ERROR_OTHER;
127
+ }
128
+
129
+ /* TODO -- add authentication */
130
+ /* setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); */
131
+
132
+ ret = usbi_pipe(netlink_control_pipe);
133
+ if (ret) {
134
+ usbi_err(NULL, "could not create netlink control pipe");
135
+ close(linux_netlink_socket);
136
+ return LIBUSB_ERROR_OTHER;
137
+ }
138
+
139
+ ret = pthread_create(&libusb_linux_event_thread, NULL, linux_netlink_event_thread_main, NULL);
140
+ if (0 != ret) {
141
+ close(netlink_control_pipe[0]);
142
+ close(netlink_control_pipe[1]);
143
+ close(linux_netlink_socket);
144
+ return LIBUSB_ERROR_OTHER;
145
+ }
146
+
147
+ return LIBUSB_SUCCESS;
148
+ }
149
+
150
+ int linux_netlink_stop_event_monitor(void)
151
+ {
152
+ int r;
153
+ char dummy = 1;
154
+
155
+ if (-1 == linux_netlink_socket) {
156
+ /* already closed. nothing to do */
157
+ return LIBUSB_SUCCESS;
158
+ }
159
+
160
+ /* Write some dummy data to the control pipe and
161
+ * wait for the thread to exit */
162
+ r = usbi_write(netlink_control_pipe[1], &dummy, sizeof(dummy));
163
+ if (r <= 0) {
164
+ usbi_warn(NULL, "netlink control pipe signal failed");
165
+ }
166
+ pthread_join(libusb_linux_event_thread, NULL);
167
+
168
+ close(linux_netlink_socket);
169
+ linux_netlink_socket = -1;
170
+
171
+ /* close and reset control pipe */
172
+ close(netlink_control_pipe[0]);
173
+ close(netlink_control_pipe[1]);
174
+ netlink_control_pipe[0] = -1;
175
+ netlink_control_pipe[1] = -1;
176
+
177
+ return LIBUSB_SUCCESS;
178
+ }
179
+
180
+ static const char *netlink_message_parse (const char *buffer, size_t len, const char *key)
181
+ {
182
+ size_t keylen = strlen(key);
183
+ size_t offset;
184
+
185
+ for (offset = 0 ; offset < len && '\0' != buffer[offset] ; offset += strlen(buffer + offset) + 1) {
186
+ if (0 == strncmp(buffer + offset, key, keylen) &&
187
+ '=' == buffer[offset + keylen]) {
188
+ return buffer + offset + keylen + 1;
189
+ }
190
+ }
191
+
192
+ return NULL;
193
+ }
194
+
195
+ /* parse parts of netlink message common to both libudev and the kernel */
196
+ static int linux_netlink_parse(char *buffer, size_t len, int *detached, const char **sys_name,
197
+ uint8_t *busnum, uint8_t *devaddr) {
198
+ const char *tmp;
199
+ int i;
200
+
201
+ errno = 0;
202
+
203
+ *sys_name = NULL;
204
+ *detached = 0;
205
+ *busnum = 0;
206
+ *devaddr = 0;
207
+
208
+ tmp = netlink_message_parse((const char *) buffer, len, "ACTION");
209
+ if (tmp == NULL)
210
+ return -1;
211
+ if (0 == strcmp(tmp, "remove")) {
212
+ *detached = 1;
213
+ } else if (0 != strcmp(tmp, "add")) {
214
+ usbi_dbg("unknown device action %s", tmp);
215
+ return -1;
216
+ }
217
+
218
+ /* check that this is a usb message */
219
+ tmp = netlink_message_parse(buffer, len, "SUBSYSTEM");
220
+ if (NULL == tmp || 0 != strcmp(tmp, "usb")) {
221
+ /* not usb. ignore */
222
+ return -1;
223
+ }
224
+
225
+ tmp = netlink_message_parse(buffer, len, "BUSNUM");
226
+ if (NULL == tmp) {
227
+ /* no bus number (likely a usb interface). ignore*/
228
+ return -1;
229
+ }
230
+
231
+ *busnum = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff);
232
+ if (errno) {
233
+ errno = 0;
234
+ return -1;
235
+ }
236
+
237
+ tmp = netlink_message_parse(buffer, len, "DEVNUM");
238
+ if (NULL == tmp) {
239
+ return -1;
240
+ }
241
+
242
+ *devaddr = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff);
243
+ if (errno) {
244
+ errno = 0;
245
+ return -1;
246
+ }
247
+
248
+ tmp = netlink_message_parse(buffer, len, "DEVPATH");
249
+ if (NULL == tmp) {
250
+ return -1;
251
+ }
252
+
253
+ for (i = strlen(tmp) - 1 ; i ; --i) {
254
+ if ('/' ==tmp[i]) {
255
+ *sys_name = tmp + i + 1;
256
+ break;
257
+ }
258
+ }
259
+
260
+ /* found a usb device */
261
+ return 0;
262
+ }
263
+
264
+ static int linux_netlink_read_message(void)
265
+ {
266
+ unsigned char buffer[1024];
267
+ struct iovec iov = {.iov_base = buffer, .iov_len = sizeof(buffer)};
268
+ struct msghdr meh = { .msg_iov=&iov, .msg_iovlen=1,
269
+ .msg_name=&snl, .msg_namelen=sizeof(snl) };
270
+ const char *sys_name = NULL;
271
+ uint8_t busnum, devaddr;
272
+ int detached, r;
273
+ size_t len;
274
+
275
+ /* read netlink message */
276
+ memset(buffer, 0, sizeof(buffer));
277
+ len = recvmsg(linux_netlink_socket, &meh, 0);
278
+ if (len < 32) {
279
+ if (errno != EAGAIN)
280
+ usbi_dbg("error recieving message from netlink");
281
+ return -1;
282
+ }
283
+
284
+ /* TODO -- authenticate this message is from the kernel or udevd */
285
+
286
+ r = linux_netlink_parse(buffer, len, &detached, &sys_name,
287
+ &busnum, &devaddr);
288
+ if (r)
289
+ return r;
290
+
291
+ usbi_dbg("netlink hotplug found device busnum: %hhu, devaddr: %hhu, sys_name: %s, removed: %s",
292
+ busnum, devaddr, sys_name, detached ? "yes" : "no");
293
+
294
+ /* signal device is available (or not) to all contexts */
295
+ if (detached)
296
+ linux_device_disconnected(busnum, devaddr, sys_name);
297
+ else
298
+ linux_hotplug_enumerate(busnum, devaddr, sys_name);
299
+
300
+ return 0;
301
+ }
302
+
303
+ static void *linux_netlink_event_thread_main(void *arg)
304
+ {
305
+ char dummy;
306
+ int r;
307
+ struct pollfd fds[] = {
308
+ { .fd = netlink_control_pipe[0],
309
+ .events = POLLIN },
310
+ { .fd = linux_netlink_socket,
311
+ .events = POLLIN },
312
+ };
313
+
314
+ /* silence compiler warning */
315
+ (void) arg;
316
+
317
+ while (poll(fds, 2, -1) >= 0) {
318
+ if (fds[0].revents & POLLIN) {
319
+ /* activity on control pipe, read the byte and exit */
320
+ r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy));
321
+ if (r <= 0) {
322
+ usbi_warn(NULL, "netlink control pipe read failed");
323
+ }
324
+ break;
325
+ }
326
+ if (fds[1].revents & POLLIN) {
327
+ usbi_mutex_static_lock(&linux_hotplug_lock);
328
+ linux_netlink_read_message();
329
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
330
+ }
331
+ }
332
+
333
+ return NULL;
334
+ }
335
+
336
+ void linux_netlink_hotplug_poll(void)
337
+ {
338
+ int r;
339
+
340
+ usbi_mutex_static_lock(&linux_hotplug_lock);
341
+ do {
342
+ r = linux_netlink_read_message();
343
+ } while (r == 0);
344
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
345
+ }