libusb 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Gemfile +1 -0
  5. data/History.md +10 -0
  6. data/README.md +19 -6
  7. data/Rakefile +1 -1
  8. data/ext/extconf.rb +17 -1
  9. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/AUTHORS +18 -6
  10. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/COPYING +0 -0
  11. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ChangeLog +58 -1
  12. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/INSTALL +0 -0
  13. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.am +6 -1
  14. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/Makefile.in +248 -174
  15. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/NEWS +2 -2
  16. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/PORTING +0 -0
  17. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/README +2 -1
  18. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/TODO +0 -0
  19. data/ext/libusbx-1.0.17/Xcode/common.xcconfig +40 -0
  20. data/ext/libusbx-1.0.17/Xcode/config.h +28 -0
  21. data/ext/libusbx-1.0.17/Xcode/debug.xcconfig +29 -0
  22. data/ext/libusbx-1.0.17/Xcode/libusbx.xcconfig +21 -0
  23. data/ext/libusbx-1.0.17/Xcode/libusbx.xcodeproj/project.pbxproj +864 -0
  24. data/ext/libusbx-1.0.17/Xcode/libusbx_debug.xcconfig +21 -0
  25. data/ext/libusbx-1.0.17/Xcode/libusbx_release.xcconfig +21 -0
  26. data/ext/libusbx-1.0.17/Xcode/release.xcconfig +29 -0
  27. data/ext/libusbx-1.0.17/aclocal.m4 +1112 -0
  28. data/ext/libusbx-1.0.17/android/README +114 -0
  29. data/ext/libusbx-1.0.17/android/config.h +90 -0
  30. data/ext/libusbx-1.0.17/android/jni/Android.mk +23 -0
  31. data/ext/libusbx-1.0.17/android/jni/Application.mk +19 -0
  32. data/ext/libusbx-1.0.17/android/jni/examples.mk +134 -0
  33. data/ext/libusbx-1.0.17/android/jni/libusb.mk +54 -0
  34. data/ext/libusbx-1.0.17/android/jni/tests.mk +56 -0
  35. data/ext/libusbx-1.0.17/compile +347 -0
  36. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.guess +164 -130
  37. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.h.in +37 -1
  38. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/config.sub +174 -89
  39. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure +723 -302
  40. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/configure.ac +71 -20
  41. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/depcomp +345 -185
  42. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.am +0 -0
  43. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/Makefile.in +95 -32
  44. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/doc/doxygen.cfg.in +1 -1
  45. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.am +5 -4
  46. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/Makefile.in +208 -104
  47. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp.c +1 -1
  48. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/dpfp_threaded.c +1 -1
  49. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.c +188 -8
  50. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/ezusb.h +18 -5
  51. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/fxload.c +90 -64
  52. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.c +0 -0
  53. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt.h +0 -0
  54. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/getopt/getopt1.c +0 -0
  55. data/ext/libusbx-1.0.17/examples/hotplugtest.c +97 -0
  56. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/listdevs.c +12 -4
  57. data/ext/libusbx-1.0.17/examples/sam3u_benchmark.c +193 -0
  58. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/examples/xusb.c +106 -49
  59. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/install-sh +21 -14
  60. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb-1.0.pc.in +1 -1
  61. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/Makefile.am +29 -10
  62. data/ext/libusbx-1.0.17/libusb/Makefile.in +914 -0
  63. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/core.c +378 -87
  64. data/ext/libusbx-1.0.17/libusb/descriptor.c +1199 -0
  65. data/ext/libusbx-1.0.17/libusb/hotplug.c +322 -0
  66. data/ext/libusbx-1.0.17/libusb/hotplug.h +82 -0
  67. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/io.c +182 -62
  68. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.def +32 -0
  69. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb-1.0.rc +2 -0
  70. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusb.h +481 -32
  71. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/libusbi.h +135 -38
  72. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.c +591 -496
  73. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/darwin_usb.h +39 -46
  74. data/ext/libusbx-1.0.17/libusb/os/linux_netlink.c +345 -0
  75. data/ext/libusbx-1.0.17/libusb/os/linux_udev.c +306 -0
  76. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.c +653 -617
  77. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/linux_usbfs.h +32 -0
  78. data/ext/{libusbx-1.0.14/libusb/os/openbsd_usb.c → libusbx-1.0.17/libusb/os/netbsd_usb.c} +70 -63
  79. data/ext/libusbx-1.0.17/libusb/os/openbsd_usb.c +823 -0
  80. data/ext/libusbx-1.0.17/libusb/os/poll_posix.c +51 -0
  81. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_posix.h +2 -1
  82. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.c +85 -106
  83. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/poll_windows.h +14 -3
  84. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.c +3 -1
  85. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_posix.h +0 -0
  86. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.c +6 -5
  87. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/threads_windows.h +0 -0
  88. data/ext/libusbx-1.0.17/libusb/os/wince_usb.c +1026 -0
  89. data/ext/libusbx-1.0.17/libusb/os/wince_usb.h +131 -0
  90. data/ext/libusbx-1.0.17/libusb/os/windows_common.h +108 -0
  91. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.c +92 -57
  92. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/os/windows_usb.h +2 -63
  93. data/ext/libusbx-1.0.17/libusb/strerror.c +184 -0
  94. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/sync.c +24 -38
  95. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/libusb/version.h +1 -1
  96. data/ext/libusbx-1.0.17/libusb/version_nano.h +1 -0
  97. data/ext/{libusbx-1.0.14 → libusbx-1.0.17}/ltmain.sh +60 -41
  98. data/ext/{libusbx-1.0.14/aclocal.m4 → libusbx-1.0.17/m4/libtool.m4} +229 -1723
  99. data/ext/libusbx-1.0.17/m4/ltoptions.m4 +384 -0
  100. data/ext/libusbx-1.0.17/m4/ltsugar.m4 +123 -0
  101. data/ext/libusbx-1.0.17/m4/ltversion.m4 +23 -0
  102. data/ext/libusbx-1.0.17/m4/lt~obsolete.m4 +98 -0
  103. data/ext/libusbx-1.0.17/missing +215 -0
  104. data/ext/libusbx-1.0.17/tests/Makefile.am +6 -0
  105. data/ext/libusbx-1.0.17/tests/Makefile.in +583 -0
  106. data/ext/libusbx-1.0.17/tests/libusbx_testlib.h +107 -0
  107. data/ext/libusbx-1.0.17/tests/stress.c +160 -0
  108. data/ext/libusbx-1.0.17/tests/testlib.c +276 -0
  109. data/lib/libusb.rb +4 -0
  110. data/lib/libusb/call.rb +43 -1
  111. data/lib/libusb/constants.rb +5 -0
  112. data/lib/libusb/context.rb +100 -0
  113. data/lib/libusb/dev_handle.rb +27 -0
  114. data/lib/libusb/device.rb +10 -4
  115. data/lib/libusb/version_gem.rb +1 -1
  116. data/test/test_libusb_capability.rb +2 -2
  117. data/test/test_libusb_compat.rb +2 -2
  118. data/test/test_libusb_compat_mass_storage.rb +2 -2
  119. data/test/test_libusb_descriptors.rb +4 -2
  120. data/test/test_libusb_event_machine.rb +2 -2
  121. data/test/test_libusb_gc.rb +2 -2
  122. data/test/test_libusb_hotplug.rb +115 -0
  123. data/test/test_libusb_iso_transfer.rb +3 -3
  124. data/test/test_libusb_mass_storage.rb +6 -16
  125. data/test/test_libusb_mass_storage2.rb +26 -3
  126. data/test/test_libusb_structs.rb +2 -2
  127. data/test/test_libusb_threads.rb +2 -2
  128. data/test/test_libusb_version.rb +2 -2
  129. metadata +127 -68
  130. metadata.gz.sig +0 -0
  131. data/ext/libusbx-1.0.14/THANKS +0 -7
  132. data/ext/libusbx-1.0.14/compile +0 -143
  133. data/ext/libusbx-1.0.14/libusb/Makefile.in +0 -721
  134. data/ext/libusbx-1.0.14/libusb/descriptor.c +0 -731
  135. data/ext/libusbx-1.0.14/libusb/version_nano.h +0 -1
  136. data/ext/libusbx-1.0.14/missing +0 -376
@@ -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
+ }