usb 1.7.2 → 1.8.0-libusb.2

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 (188) hide show
  1. package/.gitmodules +1 -1
  2. package/Readme.md +2 -2
  3. package/binding.gyp +2 -2
  4. package/libusb/.private/pre-commit.sh +7 -1
  5. package/libusb/.travis.yml +49 -0
  6. package/libusb/AUTHORS +44 -3
  7. package/libusb/Brewfile +4 -0
  8. package/libusb/ChangeLog +74 -2
  9. package/libusb/README.md +32 -0
  10. package/libusb/TODO +1 -1
  11. package/libusb/Xcode/common.xcconfig +12 -0
  12. package/libusb/Xcode/config.h +25 -0
  13. package/libusb/Xcode/libusb.xcodeproj/project.pbxproj +959 -1
  14. package/libusb/android/README +4 -2
  15. package/libusb/android/config.h +75 -0
  16. package/libusb/appveyor.yml +41 -0
  17. package/libusb/appveyor_cygwin.bat +11 -0
  18. package/libusb/appveyor_minGW.bat +19 -0
  19. package/libusb/autogen.sh +1 -1
  20. package/libusb/bootstrap.sh +3 -16
  21. package/libusb/configure.ac +108 -80
  22. package/libusb/doc/doxygen.cfg.in +1785 -739
  23. package/libusb/examples/Makefile.am +1 -1
  24. package/libusb/examples/dpfp.c +3 -1
  25. package/libusb/examples/dpfp_threaded.c +23 -10
  26. package/libusb/examples/ezusb.c +3 -3
  27. package/libusb/examples/ezusb.h +2 -2
  28. package/libusb/examples/fxload.c +31 -9
  29. package/libusb/examples/hotplugtest.c +35 -7
  30. package/libusb/examples/listdevs.c +3 -1
  31. package/libusb/examples/sam3u_benchmark.c +3 -3
  32. package/libusb/examples/testlibusb.c +277 -0
  33. package/libusb/examples/xusb.c +40 -34
  34. package/libusb/libusb/Makefile.am +49 -23
  35. package/libusb/libusb/core.c +855 -457
  36. package/libusb/libusb/descriptor.c +72 -78
  37. package/libusb/libusb/hotplug.c +122 -76
  38. package/libusb/libusb/hotplug.h +42 -25
  39. package/libusb/libusb/io.c +625 -390
  40. package/libusb/libusb/libusb-1.0.def +12 -0
  41. package/libusb/libusb/libusb.h +218 -150
  42. package/libusb/libusb/libusbi.h +346 -176
  43. package/libusb/libusb/os/darwin_usb.c +604 -319
  44. package/libusb/libusb/os/darwin_usb.h +61 -20
  45. package/libusb/libusb/os/haiku_pollfs.cpp +367 -0
  46. package/libusb/libusb/os/haiku_usb.h +113 -0
  47. package/libusb/libusb/os/haiku_usb_backend.cpp +533 -0
  48. package/libusb/libusb/os/haiku_usb_raw.cpp +267 -0
  49. package/libusb/libusb/os/haiku_usb_raw.h +188 -0
  50. package/libusb/libusb/os/linux_netlink.c +186 -146
  51. package/libusb/libusb/os/linux_udev.c +36 -14
  52. package/libusb/libusb/os/linux_usbfs.c +426 -225
  53. package/libusb/libusb/os/linux_usbfs.h +5 -3
  54. package/libusb/libusb/os/netbsd_usb.c +21 -77
  55. package/libusb/libusb/os/openbsd_usb.c +32 -115
  56. package/libusb/libusb/os/poll_posix.c +38 -5
  57. package/libusb/libusb/os/poll_posix.h +3 -0
  58. package/libusb/libusb/os/poll_windows.c +277 -626
  59. package/libusb/libusb/os/poll_windows.h +11 -44
  60. package/libusb/libusb/os/sunos_usb.c +1695 -0
  61. package/libusb/libusb/os/sunos_usb.h +80 -0
  62. package/libusb/libusb/os/threads_posix.c +24 -26
  63. package/libusb/libusb/os/threads_posix.h +73 -21
  64. package/libusb/libusb/os/threads_windows.c +71 -157
  65. package/libusb/libusb/os/threads_windows.h +68 -44
  66. package/libusb/libusb/os/wince_usb.c +276 -420
  67. package/libusb/libusb/os/wince_usb.h +23 -28
  68. package/libusb/libusb/os/windows_common.h +78 -58
  69. package/libusb/libusb/os/windows_nt_common.c +1010 -0
  70. package/libusb/libusb/os/windows_nt_common.h +110 -0
  71. package/libusb/libusb/os/windows_nt_shared_types.h +147 -0
  72. package/libusb/libusb/os/windows_usbdk.c +830 -0
  73. package/libusb/libusb/os/windows_usbdk.h +103 -0
  74. package/libusb/libusb/os/windows_winusb.c +4391 -0
  75. package/libusb/libusb/os/windows_winusb.h +783 -0
  76. package/libusb/libusb/strerror.c +41 -7
  77. package/libusb/libusb/sync.c +41 -13
  78. package/libusb/libusb/version.h +1 -1
  79. package/libusb/libusb/version_nano.h +1 -1
  80. package/libusb/libusb-1.0.pc.in +1 -1
  81. package/libusb/msvc/appveyor.bat +27 -0
  82. package/libusb/msvc/config.h +5 -4
  83. package/libusb/msvc/ddk_build.cmd +87 -43
  84. package/libusb/msvc/fxload_2010.vcxproj +24 -104
  85. package/libusb/msvc/fxload_2012.vcxproj +24 -107
  86. package/libusb/msvc/fxload_2013.vcxproj +24 -107
  87. package/libusb/msvc/fxload_2015.vcxproj +91 -0
  88. package/libusb/msvc/fxload_2017.vcxproj +114 -0
  89. package/libusb/msvc/fxload_sources +1 -1
  90. package/libusb/msvc/getopt_2010.vcxproj +16 -75
  91. package/libusb/msvc/getopt_2012.vcxproj +16 -79
  92. package/libusb/msvc/getopt_2013.vcxproj +16 -79
  93. package/libusb/msvc/getopt_2015.vcxproj +73 -0
  94. package/libusb/msvc/getopt_2017.vcxproj +98 -0
  95. package/libusb/msvc/getopt_sources +6 -2
  96. package/libusb/msvc/hotplugtest_2010.vcxproj +18 -99
  97. package/libusb/msvc/hotplugtest_2012.vcxproj +18 -102
  98. package/libusb/msvc/hotplugtest_2013.vcxproj +18 -102
  99. package/libusb/msvc/hotplugtest_2015.vcxproj +83 -0
  100. package/libusb/msvc/hotplugtest_2017.vcxproj +106 -0
  101. package/libusb/msvc/hotplugtest_sources +1 -1
  102. package/libusb/msvc/libusb_2005.sln +20 -20
  103. package/libusb/msvc/libusb_2010.sln +57 -46
  104. package/libusb/msvc/libusb_2012.sln +57 -46
  105. package/libusb/msvc/libusb_2013.sln +57 -50
  106. package/libusb/msvc/libusb_2015.sln +59 -52
  107. package/libusb/msvc/libusb_2017.sln +186 -0
  108. package/libusb/msvc/libusb_dll.dsp +2 -2
  109. package/libusb/msvc/libusb_dll_2005.vcproj +30 -2
  110. package/libusb/msvc/libusb_dll_2010.vcxproj +26 -90
  111. package/libusb/msvc/libusb_dll_2012.vcxproj +28 -96
  112. package/libusb/msvc/libusb_dll_2013.vcxproj +28 -96
  113. package/libusb/msvc/libusb_dll_2015.vcxproj +107 -0
  114. package/libusb/msvc/libusb_dll_2017.vcxproj +134 -0
  115. package/libusb/msvc/libusb_dll_wince.vcproj +9 -1
  116. package/libusb/msvc/libusb_sources +10 -5
  117. package/libusb/msvc/libusb_static.dsp +2 -2
  118. package/libusb/msvc/libusb_static_2005.vcproj +32 -4
  119. package/libusb/msvc/libusb_static_2010.vcxproj +24 -83
  120. package/libusb/msvc/libusb_static_2012.vcxproj +25 -87
  121. package/libusb/msvc/libusb_static_2013.vcxproj +25 -87
  122. package/libusb/msvc/libusb_static_2015.vcxproj +98 -0
  123. package/libusb/msvc/libusb_static_2017.vcxproj +117 -0
  124. package/libusb/msvc/libusb_static_wince.vcproj +20 -26
  125. package/libusb/msvc/libusb_wince.sln +88 -88
  126. package/libusb/msvc/listdevs_2010.vcxproj +16 -99
  127. package/libusb/msvc/listdevs_2012.vcxproj +16 -102
  128. package/libusb/msvc/listdevs_2013.vcxproj +16 -102
  129. package/libusb/msvc/listdevs_2015.vcxproj +83 -0
  130. package/libusb/msvc/listdevs_2017.vcxproj +106 -0
  131. package/libusb/msvc/listdevs_sources +2 -1
  132. package/libusb/msvc/stress_2010.vcxproj +20 -101
  133. package/libusb/msvc/stress_2012.vcxproj +20 -104
  134. package/libusb/msvc/stress_2013.vcxproj +20 -104
  135. package/libusb/msvc/stress_2015.vcxproj +87 -0
  136. package/libusb/msvc/stress_2017.vcxproj +110 -0
  137. package/libusb/msvc/stress_sources +21 -0
  138. package/libusb/msvc/testlibusb_2010.vcxproj +82 -0
  139. package/libusb/msvc/testlibusb_2012.vcxproj +83 -0
  140. package/libusb/msvc/testlibusb_2013.vcxproj +83 -0
  141. package/libusb/msvc/testlibusb_2015.vcxproj +83 -0
  142. package/libusb/msvc/testlibusb_2017.vcxproj +106 -0
  143. package/libusb/msvc/testlibusb_sources +20 -0
  144. package/libusb/msvc/xusb_2010.vcxproj +17 -98
  145. package/libusb/msvc/xusb_2012.vcxproj +17 -101
  146. package/libusb/msvc/xusb_2013.vcxproj +17 -101
  147. package/libusb/msvc/xusb_2015.vcxproj +83 -0
  148. package/libusb/msvc/xusb_2017.vcxproj +106 -0
  149. package/libusb/msvc/xusb_sources +1 -1
  150. package/libusb/tests/stress.c +2 -2
  151. package/libusb/tests/testlib.c +0 -4
  152. package/libusb/travis-autogen.sh +39 -0
  153. package/libusb.gypi +13 -2
  154. package/package.json +20 -11
  155. package/prebuilds/android-arm/node.napi.armv7.node +0 -0
  156. package/prebuilds/android-arm64/node.napi.armv8.node +0 -0
  157. package/prebuilds/darwin-x64+arm64/node.napi.node +0 -0
  158. package/prebuilds/linux-arm/node.napi.armv6.node +0 -0
  159. package/prebuilds/linux-arm/node.napi.armv7.node +0 -0
  160. package/prebuilds/linux-arm64/node.napi.armv8.node +0 -0
  161. package/prebuilds/linux-ia32/node.napi.node +0 -0
  162. package/prebuilds/linux-x64/node.napi.glibc.node +0 -0
  163. package/prebuilds/linux-x64/node.napi.musl.node +0 -0
  164. package/prebuilds/win32-ia32/node.napi.node +0 -0
  165. package/prebuilds/win32-x64/node.napi.node +0 -0
  166. package/src/device.cc +1 -1
  167. package/usb.js +1 -1
  168. package/.github/workflows/prebuild.yml +0 -49
  169. package/libusb/INSTALL +0 -234
  170. package/libusb/README +0 -28
  171. package/libusb/libusb/os/windows_usb.c +0 -5347
  172. package/libusb/libusb/os/windows_usb.h +0 -971
  173. package/libusb/msvc/fxload_2010.vcxproj.filters +0 -25
  174. package/libusb/msvc/fxload_2012.vcxproj.filters +0 -25
  175. package/libusb/msvc/getopt_2010.vcxproj.filters +0 -26
  176. package/libusb/msvc/getopt_2012.vcxproj.filters +0 -26
  177. package/libusb/msvc/hotplugtest_2010.vcxproj.filters +0 -14
  178. package/libusb/msvc/hotplugtest_2012.vcxproj.filters +0 -14
  179. package/libusb/msvc/libusb_dll_2010.vcxproj.filters +0 -81
  180. package/libusb/msvc/libusb_dll_2012.vcxproj.filters +0 -84
  181. package/libusb/msvc/libusb_static_2010.vcxproj.filters +0 -74
  182. package/libusb/msvc/libusb_static_2012.vcxproj.filters +0 -74
  183. package/libusb/msvc/listdevs_2010.vcxproj.filters +0 -14
  184. package/libusb/msvc/listdevs_2012.vcxproj.filters +0 -14
  185. package/libusb/msvc/stress_2010.vcxproj.filters +0 -25
  186. package/libusb/msvc/stress_2012.vcxproj.filters +0 -25
  187. package/libusb/msvc/xusb_2010.vcxproj.filters +0 -14
  188. package/libusb/msvc/xusb_2012.vcxproj.filters +0 -14
@@ -4,6 +4,7 @@
4
4
  * Copyright (C) 2007-2009 Daniel Drake <dsd@gentoo.org>
5
5
  * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
6
6
  * Copyright (c) 2013 Nathan Hjelm <hjelmn@mac.com>
7
+ * Copyright (c) 2016 Chris Dickens <christopher.a.dickens@gmail.com>
7
8
  *
8
9
  * This library is free software; you can redistribute it and/or
9
10
  * modify it under the terms of the GNU Lesser General Public
@@ -20,40 +21,37 @@
20
21
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
22
  */
22
23
 
23
- #include "config.h"
24
- #include "libusb.h"
25
- #include "libusbi.h"
26
- #include "linux_usbfs.h"
24
+ #include <config.h>
27
25
 
28
- #include <ctype.h>
29
- #include <dirent.h>
26
+ #include <assert.h>
30
27
  #include <errno.h>
31
28
  #include <fcntl.h>
32
29
  #include <poll.h>
33
30
  #include <stdio.h>
34
31
  #include <stdlib.h>
35
32
  #include <string.h>
33
+ #include <unistd.h>
36
34
  #include <sys/types.h>
37
35
 
38
36
  #ifdef HAVE_ASM_TYPES_H
39
37
  #include <asm/types.h>
40
38
  #endif
41
39
 
42
- #ifdef HAVE_SYS_SOCKET_H
43
40
  #include <sys/socket.h>
44
- #endif
41
+ #include <linux/netlink.h>
45
42
 
46
- #include <arpa/inet.h>
43
+ #include "libusbi.h"
44
+ #include "linux_usbfs.h"
47
45
 
48
- #ifdef HAVE_LINUX_NETLINK_H
49
- #include <linux/netlink.h>
50
- #endif
46
+ #define NL_GROUP_KERNEL 1
51
47
 
52
- #ifdef HAVE_LINUX_FILTER_H
53
- #include <linux/filter.h>
48
+ #ifndef SOCK_CLOEXEC
49
+ #define SOCK_CLOEXEC 0
54
50
  #endif
55
51
 
56
- #define KERNEL 1
52
+ #ifndef SOCK_NONBLOCK
53
+ #define SOCK_NONBLOCK 0
54
+ #endif
57
55
 
58
56
  static int linux_netlink_socket = -1;
59
57
  static int netlink_control_pipe[2] = { -1, -1 };
@@ -61,30 +59,38 @@ static pthread_t libusb_linux_event_thread;
61
59
 
62
60
  static void *linux_netlink_event_thread_main(void *arg);
63
61
 
64
- struct sockaddr_nl snl = { .nl_family=AF_NETLINK, .nl_groups=KERNEL };
65
-
66
- static int set_fd_cloexec_nb (int fd)
62
+ static int set_fd_cloexec_nb(int fd, int socktype)
67
63
  {
68
64
  int flags;
69
65
 
70
66
  #if defined(FD_CLOEXEC)
71
- flags = fcntl (linux_netlink_socket, F_GETFD);
72
- if (0 > flags) {
73
- return -1;
74
- }
67
+ /* Make sure the netlink socket file descriptor is marked as CLOEXEC */
68
+ if (!(socktype & SOCK_CLOEXEC)) {
69
+ flags = fcntl(fd, F_GETFD);
70
+ if (flags == -1) {
71
+ usbi_err(NULL, "failed to get netlink fd flags (%d)", errno);
72
+ return -1;
73
+ }
75
74
 
76
- if (!(flags & FD_CLOEXEC)) {
77
- fcntl (linux_netlink_socket, F_SETFD, flags | FD_CLOEXEC);
75
+ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
76
+ usbi_err(NULL, "failed to set netlink fd flags (%d)", errno);
77
+ return -1;
78
+ }
78
79
  }
79
80
  #endif
80
81
 
81
- flags = fcntl (linux_netlink_socket, F_GETFL);
82
- if (0 > flags) {
83
- return -1;
84
- }
82
+ /* Make sure the netlink socket is non-blocking */
83
+ if (!(socktype & SOCK_NONBLOCK)) {
84
+ flags = fcntl(fd, F_GETFL);
85
+ if (flags == -1) {
86
+ usbi_err(NULL, "failed to get netlink fd status flags (%d)", errno);
87
+ return -1;
88
+ }
85
89
 
86
- if (!(flags & O_NONBLOCK)) {
87
- fcntl (linux_netlink_socket, F_SETFL, flags | O_NONBLOCK);
90
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
91
+ usbi_err(NULL, "failed to set netlink fd status flags (%d)", errno);
92
+ return -1;
93
+ }
88
94
  }
89
95
 
90
96
  return 0;
@@ -92,77 +98,78 @@ static int set_fd_cloexec_nb (int fd)
92
98
 
93
99
  int linux_netlink_start_event_monitor(void)
94
100
  {
95
- int socktype = SOCK_RAW;
101
+ struct sockaddr_nl sa_nl = { .nl_family = AF_NETLINK, .nl_groups = NL_GROUP_KERNEL };
102
+ int socktype = SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC;
103
+ int opt = 1;
96
104
  int ret;
97
105
 
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
106
  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);
107
+ if (linux_netlink_socket == -1 && errno == EINVAL) {
108
+ usbi_dbg("failed to create netlink socket of type %d, attempting SOCK_RAW", socktype);
109
+ socktype = SOCK_RAW;
110
+ linux_netlink_socket = socket(PF_NETLINK, socktype, NETLINK_KOBJECT_UEVENT);
110
111
  }
111
112
 
112
- if (-1 == linux_netlink_socket) {
113
- return LIBUSB_ERROR_OTHER;
113
+ if (linux_netlink_socket == -1) {
114
+ usbi_err(NULL, "failed to create netlink socket (%d)", errno);
115
+ goto err;
114
116
  }
115
117
 
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
- }
118
+ ret = set_fd_cloexec_nb(linux_netlink_socket, socktype);
119
+ if (ret == -1)
120
+ goto err_close_socket;
122
121
 
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;
122
+ ret = bind(linux_netlink_socket, (struct sockaddr *)&sa_nl, sizeof(sa_nl));
123
+ if (ret == -1) {
124
+ usbi_err(NULL, "failed to bind netlink socket (%d)", errno);
125
+ goto err_close_socket;
127
126
  }
128
127
 
129
- /* TODO -- add authentication */
130
- /* setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)); */
128
+ ret = setsockopt(linux_netlink_socket, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt));
129
+ if (ret == -1) {
130
+ usbi_err(NULL, "failed to set netlink socket SO_PASSCRED option (%d)", errno);
131
+ goto err_close_socket;
132
+ }
131
133
 
132
134
  ret = usbi_pipe(netlink_control_pipe);
133
135
  if (ret) {
134
- usbi_err(NULL, "could not create netlink control pipe");
135
- close(linux_netlink_socket);
136
- return LIBUSB_ERROR_OTHER;
136
+ usbi_err(NULL, "failed to create netlink control pipe");
137
+ goto err_close_socket;
137
138
  }
138
139
 
139
140
  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;
141
+ if (ret != 0) {
142
+ usbi_err(NULL, "failed to create netlink event thread (%d)", ret);
143
+ goto err_close_pipe;
145
144
  }
146
145
 
147
146
  return LIBUSB_SUCCESS;
147
+
148
+ err_close_pipe:
149
+ close(netlink_control_pipe[0]);
150
+ close(netlink_control_pipe[1]);
151
+ netlink_control_pipe[0] = -1;
152
+ netlink_control_pipe[1] = -1;
153
+ err_close_socket:
154
+ close(linux_netlink_socket);
155
+ linux_netlink_socket = -1;
156
+ err:
157
+ return LIBUSB_ERROR_OTHER;
148
158
  }
149
159
 
150
160
  int linux_netlink_stop_event_monitor(void)
151
161
  {
152
- int r;
153
162
  char dummy = 1;
163
+ ssize_t r;
154
164
 
155
- if (-1 == linux_netlink_socket) {
156
- /* already closed. nothing to do */
157
- return LIBUSB_SUCCESS;
158
- }
165
+ assert(linux_netlink_socket != -1);
159
166
 
160
167
  /* Write some dummy data to the control pipe and
161
168
  * wait for the thread to exit */
162
- r = usbi_write(netlink_control_pipe[1], &dummy, sizeof(dummy));
163
- if (r <= 0) {
169
+ r = write(netlink_control_pipe[1], &dummy, sizeof(dummy));
170
+ if (r <= 0)
164
171
  usbi_warn(NULL, "netlink control pipe signal failed");
165
- }
172
+
166
173
  pthread_join(libusb_linux_event_thread, NULL);
167
174
 
168
175
  close(linux_netlink_socket);
@@ -177,26 +184,25 @@ int linux_netlink_stop_event_monitor(void)
177
184
  return LIBUSB_SUCCESS;
178
185
  }
179
186
 
180
- static const char *netlink_message_parse (const char *buffer, size_t len, const char *key)
187
+ static const char *netlink_message_parse(const char *buffer, size_t len, const char *key)
181
188
  {
189
+ const char *end = buffer + len;
182
190
  size_t keylen = strlen(key);
183
- size_t offset;
184
191
 
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
- }
192
+ while (buffer < end && *buffer) {
193
+ if (strncmp(buffer, key, keylen) == 0 && buffer[keylen] == '=')
194
+ return buffer + keylen + 1;
195
+ buffer += strlen(buffer) + 1;
190
196
  }
191
197
 
192
198
  return NULL;
193
199
  }
194
200
 
195
201
  /* 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;
202
+ static int linux_netlink_parse(const char *buffer, size_t len, int *detached,
203
+ const char **sys_name, uint8_t *busnum, uint8_t *devaddr)
204
+ {
205
+ const char *tmp, *slash;
200
206
 
201
207
  errno = 0;
202
208
 
@@ -205,81 +211,82 @@ static int linux_netlink_parse(char *buffer, size_t len, int *detached, const ch
205
211
  *busnum = 0;
206
212
  *devaddr = 0;
207
213
 
208
- tmp = netlink_message_parse((const char *) buffer, len, "ACTION");
209
- if (tmp == NULL)
214
+ tmp = netlink_message_parse(buffer, len, "ACTION");
215
+ if (!tmp) {
210
216
  return -1;
211
- if (0 == strcmp(tmp, "remove")) {
217
+ } else if (strcmp(tmp, "remove") == 0) {
212
218
  *detached = 1;
213
- } else if (0 != strcmp(tmp, "add")) {
219
+ } else if (strcmp(tmp, "add") != 0) {
214
220
  usbi_dbg("unknown device action %s", tmp);
215
221
  return -1;
216
222
  }
217
223
 
218
224
  /* check that this is a usb message */
219
225
  tmp = netlink_message_parse(buffer, len, "SUBSYSTEM");
220
- if (NULL == tmp || 0 != strcmp(tmp, "usb")) {
226
+ if (!tmp || strcmp(tmp, "usb") != 0) {
227
+ /* not usb. ignore */
228
+ return -1;
229
+ }
230
+
231
+ /* check that this is an actual usb device */
232
+ tmp = netlink_message_parse(buffer, len, "DEVTYPE");
233
+ if (!tmp || strcmp(tmp, "usb_device") != 0) {
221
234
  /* not usb. ignore */
222
235
  return -1;
223
236
  }
224
237
 
225
238
  tmp = netlink_message_parse(buffer, len, "BUSNUM");
226
- if (NULL == tmp) {
239
+ if (tmp) {
240
+ *busnum = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff);
241
+ if (errno) {
242
+ errno = 0;
243
+ return -1;
244
+ }
245
+
246
+ tmp = netlink_message_parse(buffer, len, "DEVNUM");
247
+ if (NULL == tmp)
248
+ return -1;
249
+
250
+ *devaddr = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff);
251
+ if (errno) {
252
+ errno = 0;
253
+ return -1;
254
+ }
255
+ } else {
227
256
  /* no bus number. try "DEVICE" */
228
257
  tmp = netlink_message_parse(buffer, len, "DEVICE");
229
- if (NULL == tmp) {
258
+ if (!tmp) {
230
259
  /* not usb. ignore */
231
260
  return -1;
232
261
  }
233
-
262
+
234
263
  /* Parse a device path such as /dev/bus/usb/003/004 */
235
- char *pLastSlash = (char*)strrchr(tmp,'/');
236
- if(NULL == pLastSlash) {
264
+ slash = strrchr(tmp, '/');
265
+ if (!slash)
237
266
  return -1;
238
- }
239
267
 
240
- *devaddr = strtoul(pLastSlash + 1, NULL, 10);
268
+ *busnum = (uint8_t)(strtoul(slash - 3, NULL, 10) & 0xff);
241
269
  if (errno) {
242
270
  errno = 0;
243
271
  return -1;
244
272
  }
245
-
246
- *busnum = strtoul(pLastSlash - 3, NULL, 10);
273
+
274
+ *devaddr = (uint8_t)(strtoul(slash + 1, NULL, 10) & 0xff);
247
275
  if (errno) {
248
276
  errno = 0;
249
277
  return -1;
250
278
  }
251
-
252
- return 0;
253
- }
254
-
255
- *busnum = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff);
256
- if (errno) {
257
- errno = 0;
258
- return -1;
259
- }
260
-
261
- tmp = netlink_message_parse(buffer, len, "DEVNUM");
262
- if (NULL == tmp) {
263
- return -1;
264
- }
265
279
 
266
- *devaddr = (uint8_t)(strtoul(tmp, NULL, 10) & 0xff);
267
- if (errno) {
268
- errno = 0;
269
- return -1;
280
+ return 0;
270
281
  }
271
282
 
272
283
  tmp = netlink_message_parse(buffer, len, "DEVPATH");
273
- if (NULL == tmp) {
284
+ if (!tmp)
274
285
  return -1;
275
- }
276
286
 
277
- for (i = strlen(tmp) - 1 ; i ; --i) {
278
- if ('/' ==tmp[i]) {
279
- *sys_name = tmp + i + 1;
280
- break;
281
- }
282
- }
287
+ slash = strrchr(tmp, '/');
288
+ if (slash)
289
+ *sys_name = slash + 1;
283
290
 
284
291
  /* found a usb device */
285
292
  return 0;
@@ -287,28 +294,54 @@ static int linux_netlink_parse(char *buffer, size_t len, int *detached, const ch
287
294
 
288
295
  static int linux_netlink_read_message(void)
289
296
  {
290
- unsigned char buffer[1024];
291
- struct iovec iov = {.iov_base = buffer, .iov_len = sizeof(buffer)};
292
- struct msghdr meh = { .msg_iov=&iov, .msg_iovlen=1,
293
- .msg_name=&snl, .msg_namelen=sizeof(snl) };
297
+ char cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
298
+ char msg_buffer[2048];
294
299
  const char *sys_name = NULL;
295
300
  uint8_t busnum, devaddr;
296
301
  int detached, r;
297
- size_t len;
302
+ ssize_t len;
303
+ struct cmsghdr *cmsg;
304
+ struct ucred *cred;
305
+ struct sockaddr_nl sa_nl;
306
+ struct iovec iov = { .iov_base = msg_buffer, .iov_len = sizeof(msg_buffer) };
307
+ struct msghdr msg = {
308
+ .msg_iov = &iov, .msg_iovlen = 1,
309
+ .msg_control = cred_buffer, .msg_controllen = sizeof(cred_buffer),
310
+ .msg_name = &sa_nl, .msg_namelen = sizeof(sa_nl)
311
+ };
298
312
 
299
313
  /* read netlink message */
300
- memset(buffer, 0, sizeof(buffer));
301
- len = recvmsg(linux_netlink_socket, &meh, 0);
302
- if (len < 32) {
303
- if (errno != EAGAIN)
304
- usbi_dbg("error recieving message from netlink");
314
+ len = recvmsg(linux_netlink_socket, &msg, 0);
315
+ if (len == -1) {
316
+ if (errno != EAGAIN && errno != EINTR)
317
+ usbi_err(NULL, "error receiving message from netlink (%d)", errno);
318
+ return -1;
319
+ }
320
+
321
+ if (len < 32 || (msg.msg_flags & MSG_TRUNC)) {
322
+ usbi_err(NULL, "invalid netlink message length");
305
323
  return -1;
306
324
  }
307
325
 
308
- /* TODO -- authenticate this message is from the kernel or udevd */
326
+ if (sa_nl.nl_groups != NL_GROUP_KERNEL || sa_nl.nl_pid != 0) {
327
+ usbi_dbg("ignoring netlink message from unknown group/PID (%u/%u)",
328
+ (unsigned int)sa_nl.nl_groups, (unsigned int)sa_nl.nl_pid);
329
+ return -1;
330
+ }
331
+
332
+ cmsg = CMSG_FIRSTHDR(&msg);
333
+ if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) {
334
+ usbi_dbg("ignoring netlink message with no sender credentials");
335
+ return -1;
336
+ }
309
337
 
310
- r = linux_netlink_parse(buffer, len, &detached, &sys_name,
311
- &busnum, &devaddr);
338
+ cred = (struct ucred *)CMSG_DATA(cmsg);
339
+ if (cred->uid != 0) {
340
+ usbi_dbg("ignoring netlink message with non-zero sender UID %u", (unsigned int)cred->uid);
341
+ return -1;
342
+ }
343
+
344
+ r = linux_netlink_parse(msg_buffer, (size_t)len, &detached, &sys_name, &busnum, &devaddr);
312
345
  if (r)
313
346
  return r;
314
347
 
@@ -317,7 +350,7 @@ static int linux_netlink_read_message(void)
317
350
 
318
351
  /* signal device is available (or not) to all contexts */
319
352
  if (detached)
320
- linux_device_disconnected(busnum, devaddr, sys_name);
353
+ linux_device_disconnected(busnum, devaddr);
321
354
  else
322
355
  linux_hotplug_enumerate(busnum, devaddr, sys_name);
323
356
 
@@ -328,6 +361,7 @@ static void *linux_netlink_event_thread_main(void *arg)
328
361
  {
329
362
  char dummy;
330
363
  int r;
364
+ ssize_t nb;
331
365
  struct pollfd fds[] = {
332
366
  { .fd = netlink_control_pipe[0],
333
367
  .events = POLLIN },
@@ -335,25 +369,31 @@ static void *linux_netlink_event_thread_main(void *arg)
335
369
  .events = POLLIN },
336
370
  };
337
371
 
338
- /* silence compiler warning */
339
- (void) arg;
372
+ UNUSED(arg);
373
+
374
+ usbi_dbg("netlink event thread entering");
340
375
 
341
- while (poll(fds, 2, -1) >= 0) {
376
+ while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) {
377
+ if (r < 0) {
378
+ /* temporary failure */
379
+ continue;
380
+ }
342
381
  if (fds[0].revents & POLLIN) {
343
382
  /* activity on control pipe, read the byte and exit */
344
- r = usbi_read(netlink_control_pipe[0], &dummy, sizeof(dummy));
345
- if (r <= 0) {
383
+ nb = read(netlink_control_pipe[0], &dummy, sizeof(dummy));
384
+ if (nb <= 0)
346
385
  usbi_warn(NULL, "netlink control pipe read failed");
347
- }
348
386
  break;
349
387
  }
350
388
  if (fds[1].revents & POLLIN) {
351
- usbi_mutex_static_lock(&linux_hotplug_lock);
352
- linux_netlink_read_message();
353
- usbi_mutex_static_unlock(&linux_hotplug_lock);
389
+ usbi_mutex_static_lock(&linux_hotplug_lock);
390
+ linux_netlink_read_message();
391
+ usbi_mutex_static_unlock(&linux_hotplug_lock);
354
392
  }
355
393
  }
356
394
 
395
+ usbi_dbg("netlink event thread exiting");
396
+
357
397
  return NULL;
358
398
  }
359
399
 
@@ -20,7 +20,7 @@
20
20
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
21
  */
22
22
 
23
- #include "config.h"
23
+ #include <config.h>
24
24
 
25
25
  #include <assert.h>
26
26
  #include <ctype.h>
@@ -39,7 +39,6 @@
39
39
  #include <unistd.h>
40
40
  #include <libudev.h>
41
41
 
42
- #include "libusb.h"
43
42
  #include "libusbi.h"
44
43
  #include "linux_usbfs.h"
45
44
 
@@ -70,7 +69,7 @@ int linux_udev_start_event_monitor(void)
70
69
  goto err_free_ctx;
71
70
  }
72
71
 
73
- r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", 0);
72
+ r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", "usb_device");
74
73
  if (r) {
75
74
  usbi_err(NULL, "could not initialize udev monitor filter for \"usb\" subsystem");
76
75
  goto err_free_monitor;
@@ -83,17 +82,33 @@ int linux_udev_start_event_monitor(void)
83
82
 
84
83
  udev_monitor_fd = udev_monitor_get_fd(udev_monitor);
85
84
 
85
+ #if defined(FD_CLOEXEC)
86
+ /* Make sure the udev file descriptor is marked as CLOEXEC */
87
+ r = fcntl(udev_monitor_fd, F_GETFD);
88
+ if (r == -1) {
89
+ usbi_err(NULL, "geting udev monitor fd flags (%d)", errno);
90
+ goto err_free_monitor;
91
+ }
92
+ if (!(r & FD_CLOEXEC)) {
93
+ if (fcntl(udev_monitor_fd, F_SETFD, r | FD_CLOEXEC) == -1) {
94
+ usbi_err(NULL, "setting udev monitor fd flags (%d)", errno);
95
+ goto err_free_monitor;
96
+ }
97
+ }
98
+ #endif
99
+
86
100
  /* Some older versions of udev are not non-blocking by default,
87
101
  * so make sure this is set */
88
102
  r = fcntl(udev_monitor_fd, F_GETFL);
89
103
  if (r == -1) {
90
- usbi_err(NULL, "getting udev monitor fd flags (%d)", errno);
104
+ usbi_err(NULL, "getting udev monitor fd status flags (%d)", errno);
91
105
  goto err_free_monitor;
92
106
  }
93
- r = fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK);
94
- if (r) {
95
- usbi_err(NULL, "setting udev monitor fd flags (%d)", errno);
96
- goto err_free_monitor;
107
+ if (!(r & O_NONBLOCK)) {
108
+ if (fcntl(udev_monitor_fd, F_SETFL, r | O_NONBLOCK) == -1) {
109
+ usbi_err(NULL, "setting udev monitor fd status flags (%d)", errno);
110
+ goto err_free_monitor;
111
+ }
97
112
  }
98
113
 
99
114
  r = usbi_pipe(udev_control_pipe);
@@ -135,7 +150,7 @@ int linux_udev_stop_event_monitor(void)
135
150
 
136
151
  /* Write some dummy data to the control pipe and
137
152
  * wait for the thread to exit */
138
- r = usbi_write(udev_control_pipe[1], &dummy, sizeof(dummy));
153
+ r = write(udev_control_pipe[1], &dummy, sizeof(dummy));
139
154
  if (r <= 0) {
140
155
  usbi_warn(NULL, "udev control pipe signal failed");
141
156
  }
@@ -163,6 +178,7 @@ static void *linux_udev_event_thread_main(void *arg)
163
178
  {
164
179
  char dummy;
165
180
  int r;
181
+ ssize_t nb;
166
182
  struct udev_device* udev_dev;
167
183
  struct pollfd fds[] = {
168
184
  {.fd = udev_control_pipe[0],
@@ -173,11 +189,15 @@ static void *linux_udev_event_thread_main(void *arg)
173
189
 
174
190
  usbi_dbg("udev event thread entering.");
175
191
 
176
- while (poll(fds, 2, -1) >= 0) {
192
+ while ((r = poll(fds, 2, -1)) >= 0 || errno == EINTR) {
193
+ if (r < 0) {
194
+ /* temporary failure */
195
+ continue;
196
+ }
177
197
  if (fds[0].revents & POLLIN) {
178
198
  /* activity on control pipe, read the byte and exit */
179
- r = usbi_read(udev_control_pipe[0], &dummy, sizeof(dummy));
180
- if (r <= 0) {
199
+ nb = read(udev_control_pipe[0], &dummy, sizeof(dummy));
200
+ if (nb <= 0) {
181
201
  usbi_warn(NULL, "udev control pipe read failed");
182
202
  }
183
203
  break;
@@ -212,7 +232,7 @@ static int udev_device_info(struct libusb_context *ctx, int detached,
212
232
  }
213
233
 
214
234
  return linux_get_device_address(ctx, detached, busnum, devaddr,
215
- dev_node, *sys_name);
235
+ dev_node, *sys_name, -1);
216
236
  }
217
237
 
218
238
  static void udev_hotplug_event(struct udev_device* udev_dev)
@@ -241,7 +261,7 @@ static void udev_hotplug_event(struct udev_device* udev_dev)
241
261
  if (strncmp(udev_action, "add", 3) == 0) {
242
262
  linux_hotplug_enumerate(busnum, devaddr, sys_name);
243
263
  } else if (detached) {
244
- linux_device_disconnected(busnum, devaddr, sys_name);
264
+ linux_device_disconnected(busnum, devaddr);
245
265
  } else {
246
266
  usbi_err(NULL, "ignoring udev action %s", udev_action);
247
267
  }
@@ -267,9 +287,11 @@ int linux_udev_scan_devices(struct libusb_context *ctx)
267
287
  }
268
288
 
269
289
  udev_enumerate_add_match_subsystem(enumerator, "usb");
290
+ udev_enumerate_add_match_property(enumerator, "DEVTYPE", "usb_device");
270
291
  udev_enumerate_scan_devices(enumerator);
271
292
  devices = udev_enumerate_get_list_entry(enumerator);
272
293
 
294
+ entry = NULL;
273
295
  udev_list_entry_foreach(entry, devices) {
274
296
  const char *path = udev_list_entry_get_name(entry);
275
297
  uint8_t busnum = 0, devaddr = 0;