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
@@ -0,0 +1,306 @@
|
|
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) 2012-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
|
+
|
25
|
+
#include <assert.h>
|
26
|
+
#include <ctype.h>
|
27
|
+
#include <dirent.h>
|
28
|
+
#include <errno.h>
|
29
|
+
#include <fcntl.h>
|
30
|
+
#include <poll.h>
|
31
|
+
#include <stdio.h>
|
32
|
+
#include <stdlib.h>
|
33
|
+
#include <string.h>
|
34
|
+
#include <sys/ioctl.h>
|
35
|
+
#include <sys/stat.h>
|
36
|
+
#include <sys/types.h>
|
37
|
+
#include <sys/utsname.h>
|
38
|
+
#include <sys/socket.h>
|
39
|
+
#include <unistd.h>
|
40
|
+
#include <libudev.h>
|
41
|
+
|
42
|
+
#include "libusb.h"
|
43
|
+
#include "libusbi.h"
|
44
|
+
#include "linux_usbfs.h"
|
45
|
+
|
46
|
+
/* udev context */
|
47
|
+
static struct udev *udev_ctx = NULL;
|
48
|
+
static int udev_monitor_fd = -1;
|
49
|
+
static int udev_control_pipe[2] = {-1, -1};
|
50
|
+
static struct udev_monitor *udev_monitor = NULL;
|
51
|
+
static pthread_t linux_event_thread;
|
52
|
+
|
53
|
+
static void udev_hotplug_event(struct udev_device* udev_dev);
|
54
|
+
static void *linux_udev_event_thread_main(void *arg);
|
55
|
+
|
56
|
+
int linux_udev_start_event_monitor(void)
|
57
|
+
{
|
58
|
+
int r;
|
59
|
+
|
60
|
+
assert(udev_ctx == NULL);
|
61
|
+
udev_ctx = udev_new();
|
62
|
+
if (!udev_ctx) {
|
63
|
+
usbi_err(NULL, "could not create udev context");
|
64
|
+
return LIBUSB_ERROR_OTHER;
|
65
|
+
}
|
66
|
+
|
67
|
+
udev_monitor = udev_monitor_new_from_netlink(udev_ctx, "udev");
|
68
|
+
if (!udev_monitor) {
|
69
|
+
usbi_err(NULL, "could not initialize udev monitor");
|
70
|
+
goto err_free_ctx;
|
71
|
+
}
|
72
|
+
|
73
|
+
r = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "usb", 0);
|
74
|
+
if (r) {
|
75
|
+
usbi_err(NULL, "could not initialize udev monitor filter for \"usb\" subsystem");
|
76
|
+
goto err_free_monitor;
|
77
|
+
}
|
78
|
+
|
79
|
+
if (udev_monitor_enable_receiving(udev_monitor)) {
|
80
|
+
usbi_err(NULL, "failed to enable the udev monitor");
|
81
|
+
goto err_free_monitor;
|
82
|
+
}
|
83
|
+
|
84
|
+
udev_monitor_fd = udev_monitor_get_fd(udev_monitor);
|
85
|
+
|
86
|
+
/* Some older versions of udev are not non-blocking by default,
|
87
|
+
* so make sure this is set */
|
88
|
+
r = fcntl(udev_monitor_fd, F_GETFL);
|
89
|
+
if (r == -1) {
|
90
|
+
usbi_err(NULL, "getting udev monitor fd flags (%d)", errno);
|
91
|
+
goto err_free_monitor;
|
92
|
+
}
|
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;
|
97
|
+
}
|
98
|
+
|
99
|
+
r = usbi_pipe(udev_control_pipe);
|
100
|
+
if (r) {
|
101
|
+
usbi_err(NULL, "could not create udev control pipe");
|
102
|
+
goto err_free_monitor;
|
103
|
+
}
|
104
|
+
|
105
|
+
r = pthread_create(&linux_event_thread, NULL, linux_udev_event_thread_main, NULL);
|
106
|
+
if (r) {
|
107
|
+
usbi_err(NULL, "creating hotplug event thread (%d)", r);
|
108
|
+
goto err_close_pipe;
|
109
|
+
}
|
110
|
+
|
111
|
+
return LIBUSB_SUCCESS;
|
112
|
+
|
113
|
+
err_close_pipe:
|
114
|
+
close(udev_control_pipe[0]);
|
115
|
+
close(udev_control_pipe[1]);
|
116
|
+
err_free_monitor:
|
117
|
+
udev_monitor_unref(udev_monitor);
|
118
|
+
udev_monitor = NULL;
|
119
|
+
udev_monitor_fd = -1;
|
120
|
+
err_free_ctx:
|
121
|
+
udev_unref(udev_ctx);
|
122
|
+
udev_ctx = NULL;
|
123
|
+
return LIBUSB_ERROR_OTHER;
|
124
|
+
}
|
125
|
+
|
126
|
+
int linux_udev_stop_event_monitor(void)
|
127
|
+
{
|
128
|
+
char dummy = 1;
|
129
|
+
int r;
|
130
|
+
|
131
|
+
assert(udev_ctx != NULL);
|
132
|
+
assert(udev_monitor != NULL);
|
133
|
+
assert(udev_monitor_fd != -1);
|
134
|
+
|
135
|
+
/* Write some dummy data to the control pipe and
|
136
|
+
* wait for the thread to exit */
|
137
|
+
r = usbi_write(udev_control_pipe[1], &dummy, sizeof(dummy));
|
138
|
+
if (r <= 0) {
|
139
|
+
usbi_warn(NULL, "udev control pipe signal failed");
|
140
|
+
}
|
141
|
+
pthread_join(linux_event_thread, NULL);
|
142
|
+
|
143
|
+
/* Release the udev monitor */
|
144
|
+
udev_monitor_unref(udev_monitor);
|
145
|
+
udev_monitor = NULL;
|
146
|
+
udev_monitor_fd = -1;
|
147
|
+
|
148
|
+
/* Clean up the udev context */
|
149
|
+
udev_unref(udev_ctx);
|
150
|
+
udev_ctx = NULL;
|
151
|
+
|
152
|
+
/* close and reset control pipe */
|
153
|
+
close(udev_control_pipe[0]);
|
154
|
+
close(udev_control_pipe[1]);
|
155
|
+
udev_control_pipe[0] = -1;
|
156
|
+
udev_control_pipe[1] = -1;
|
157
|
+
|
158
|
+
return LIBUSB_SUCCESS;
|
159
|
+
}
|
160
|
+
|
161
|
+
static void *linux_udev_event_thread_main(void *arg)
|
162
|
+
{
|
163
|
+
char dummy;
|
164
|
+
int r;
|
165
|
+
struct udev_device* udev_dev;
|
166
|
+
struct pollfd fds[] = {
|
167
|
+
{.fd = udev_control_pipe[0],
|
168
|
+
.events = POLLIN},
|
169
|
+
{.fd = udev_monitor_fd,
|
170
|
+
.events = POLLIN},
|
171
|
+
};
|
172
|
+
|
173
|
+
usbi_dbg("udev event thread entering.");
|
174
|
+
|
175
|
+
while (poll(fds, 2, -1) >= 0) {
|
176
|
+
if (fds[0].revents & POLLIN) {
|
177
|
+
/* activity on control pipe, read the byte and exit */
|
178
|
+
r = usbi_read(udev_control_pipe[0], &dummy, sizeof(dummy));
|
179
|
+
if (r <= 0) {
|
180
|
+
usbi_warn(NULL, "udev control pipe read failed");
|
181
|
+
}
|
182
|
+
break;
|
183
|
+
}
|
184
|
+
if (fds[1].revents & POLLIN) {
|
185
|
+
usbi_mutex_static_lock(&linux_hotplug_lock);
|
186
|
+
udev_dev = udev_monitor_receive_device(udev_monitor);
|
187
|
+
if (udev_dev)
|
188
|
+
udev_hotplug_event(udev_dev);
|
189
|
+
usbi_mutex_static_unlock(&linux_hotplug_lock);
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
usbi_dbg("udev event thread exiting");
|
194
|
+
|
195
|
+
return NULL;
|
196
|
+
}
|
197
|
+
|
198
|
+
static int udev_device_info(struct libusb_context *ctx, int detached,
|
199
|
+
struct udev_device *udev_dev, uint8_t *busnum,
|
200
|
+
uint8_t *devaddr, const char **sys_name) {
|
201
|
+
const char *dev_node;
|
202
|
+
|
203
|
+
dev_node = udev_device_get_devnode(udev_dev);
|
204
|
+
if (!dev_node) {
|
205
|
+
return LIBUSB_ERROR_OTHER;
|
206
|
+
}
|
207
|
+
|
208
|
+
*sys_name = udev_device_get_sysname(udev_dev);
|
209
|
+
if (!*sys_name) {
|
210
|
+
return LIBUSB_ERROR_OTHER;
|
211
|
+
}
|
212
|
+
|
213
|
+
return linux_get_device_address(ctx, detached, busnum, devaddr,
|
214
|
+
dev_node, *sys_name);
|
215
|
+
}
|
216
|
+
|
217
|
+
static void udev_hotplug_event(struct udev_device* udev_dev)
|
218
|
+
{
|
219
|
+
const char* udev_action;
|
220
|
+
const char* sys_name = NULL;
|
221
|
+
uint8_t busnum = 0, devaddr = 0;
|
222
|
+
int detached;
|
223
|
+
int r;
|
224
|
+
|
225
|
+
do {
|
226
|
+
udev_action = udev_device_get_action(udev_dev);
|
227
|
+
if (!udev_action) {
|
228
|
+
break;
|
229
|
+
}
|
230
|
+
|
231
|
+
detached = !strncmp(udev_action, "remove", 6);
|
232
|
+
|
233
|
+
r = udev_device_info(NULL, detached, udev_dev, &busnum, &devaddr, &sys_name);
|
234
|
+
if (LIBUSB_SUCCESS != r) {
|
235
|
+
break;
|
236
|
+
}
|
237
|
+
|
238
|
+
usbi_dbg("udev hotplug event. action: %s.", udev_action);
|
239
|
+
|
240
|
+
if (strncmp(udev_action, "add", 3) == 0) {
|
241
|
+
linux_hotplug_enumerate(busnum, devaddr, sys_name);
|
242
|
+
} else if (detached) {
|
243
|
+
linux_device_disconnected(busnum, devaddr, sys_name);
|
244
|
+
} else {
|
245
|
+
usbi_err(NULL, "ignoring udev action %s", udev_action);
|
246
|
+
}
|
247
|
+
} while (0);
|
248
|
+
|
249
|
+
udev_device_unref(udev_dev);
|
250
|
+
}
|
251
|
+
|
252
|
+
int linux_udev_scan_devices(struct libusb_context *ctx)
|
253
|
+
{
|
254
|
+
struct udev_enumerate *enumerator;
|
255
|
+
struct udev_list_entry *devices, *entry;
|
256
|
+
struct udev_device *udev_dev;
|
257
|
+
const char *sys_name;
|
258
|
+
int r;
|
259
|
+
|
260
|
+
assert(udev_ctx != NULL);
|
261
|
+
|
262
|
+
enumerator = udev_enumerate_new(udev_ctx);
|
263
|
+
if (NULL == enumerator) {
|
264
|
+
usbi_err(ctx, "error creating udev enumerator");
|
265
|
+
return LIBUSB_ERROR_OTHER;
|
266
|
+
}
|
267
|
+
|
268
|
+
udev_enumerate_add_match_subsystem(enumerator, "usb");
|
269
|
+
udev_enumerate_scan_devices(enumerator);
|
270
|
+
devices = udev_enumerate_get_list_entry(enumerator);
|
271
|
+
|
272
|
+
udev_list_entry_foreach(entry, devices) {
|
273
|
+
const char *path = udev_list_entry_get_name(entry);
|
274
|
+
uint8_t busnum = 0, devaddr = 0;
|
275
|
+
|
276
|
+
udev_dev = udev_device_new_from_syspath(udev_ctx, path);
|
277
|
+
|
278
|
+
r = udev_device_info(ctx, 0, udev_dev, &busnum, &devaddr, &sys_name);
|
279
|
+
if (r) {
|
280
|
+
udev_device_unref(udev_dev);
|
281
|
+
continue;
|
282
|
+
}
|
283
|
+
|
284
|
+
linux_enumerate_device(ctx, busnum, devaddr, sys_name);
|
285
|
+
udev_device_unref(udev_dev);
|
286
|
+
}
|
287
|
+
|
288
|
+
udev_enumerate_unref(enumerator);
|
289
|
+
|
290
|
+
return LIBUSB_SUCCESS;
|
291
|
+
}
|
292
|
+
|
293
|
+
void linux_udev_hotplug_poll(void)
|
294
|
+
{
|
295
|
+
struct udev_device* udev_dev;
|
296
|
+
|
297
|
+
usbi_mutex_static_lock(&linux_hotplug_lock);
|
298
|
+
do {
|
299
|
+
udev_dev = udev_monitor_receive_device(udev_monitor);
|
300
|
+
if (udev_dev) {
|
301
|
+
usbi_dbg("Handling hotplug event from hotplug_poll");
|
302
|
+
udev_hotplug_event(udev_dev);
|
303
|
+
}
|
304
|
+
} while (udev_dev);
|
305
|
+
usbi_mutex_static_unlock(&linux_hotplug_lock);
|
306
|
+
}
|
@@ -1,7 +1,10 @@
|
|
1
|
+
/* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */
|
1
2
|
/*
|
2
3
|
* Linux usbfs backend for libusbx
|
3
4
|
* Copyright © 2007-2009 Daniel Drake <dsd@gentoo.org>
|
4
5
|
* Copyright © 2001 Johannes Erdfelt <johannes@erdfelt.com>
|
6
|
+
* Copyright © 2013 Nathan Hjelm <hjelmn@mac.com>
|
7
|
+
* Copyright © 2012-2013 Hans de Goede <hdegoede@redhat.com>
|
5
8
|
*
|
6
9
|
* This library is free software; you can redistribute it and/or
|
7
10
|
* modify it under the terms of the GNU Lesser General Public
|
@@ -18,7 +21,9 @@
|
|
18
21
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
19
22
|
*/
|
20
23
|
|
21
|
-
#include
|
24
|
+
#include "config.h"
|
25
|
+
|
26
|
+
#include <assert.h>
|
22
27
|
#include <ctype.h>
|
23
28
|
#include <dirent.h>
|
24
29
|
#include <errno.h>
|
@@ -43,23 +48,23 @@
|
|
43
48
|
*
|
44
49
|
* sysfs allows us to read the kernel's in-memory copies of device descriptors
|
45
50
|
* and so forth, avoiding the need to open the device:
|
46
|
-
* - The binary "descriptors" file
|
47
|
-
*
|
51
|
+
* - The binary "descriptors" file contains all config descriptors since
|
52
|
+
* 2.6.26, commit 217a9081d8e69026186067711131b77f0ce219ed
|
53
|
+
* - The binary "descriptors" file was added in 2.6.23, commit
|
54
|
+
* 69d42a78f935d19384d1f6e4f94b65bb162b36df, but it only contains the
|
55
|
+
* active config descriptors
|
56
|
+
* - The "busnum" file was added in 2.6.22, commit
|
57
|
+
* 83f7d958eab2fbc6b159ee92bf1493924e1d0f72
|
48
58
|
* - The "devnum" file has been present since pre-2.6.18
|
49
59
|
* - the "bConfigurationValue" file has been present since pre-2.6.18
|
50
60
|
*
|
51
61
|
* If we have bConfigurationValue, busnum, and devnum, then we can determine
|
52
62
|
* the active configuration without having to open the usbfs node in RDWR mode.
|
53
|
-
* We assume this is the case if we see the busnum file (indicates 2.6.22+).
|
54
63
|
* The busnum file is important as that is the only way we can relate sysfs
|
55
64
|
* devices to usbfs nodes.
|
56
65
|
*
|
57
|
-
* If we also have descriptors, we can obtain the device descriptor and
|
66
|
+
* If we also have all descriptors, we can obtain the device descriptor and
|
58
67
|
* configuration without touching usbfs at all.
|
59
|
-
*
|
60
|
-
* The descriptors file originally only contained the active configuration
|
61
|
-
* descriptor alongside the device descriptor, but all configurations are
|
62
|
-
* included as of Linux 2.6.26.
|
63
68
|
*/
|
64
69
|
|
65
70
|
/* endianness for multi-byte fields:
|
@@ -67,6 +72,8 @@
|
|
67
72
|
* Descriptors exposed by usbfs have the multi-byte fields in the device
|
68
73
|
* descriptor as host endian. Multi-byte fields in the other descriptors are
|
69
74
|
* bus-endian. The kernel documentation says otherwise, but it is wrong.
|
75
|
+
*
|
76
|
+
* In sysfs all descriptors are bus-endian.
|
70
77
|
*/
|
71
78
|
|
72
79
|
static const char *usbfs_path = NULL;
|
@@ -101,17 +108,39 @@ static int supports_flag_zero_packet = -1;
|
|
101
108
|
* systems. appropriate choice made at initialization time. */
|
102
109
|
static clockid_t monotonic_clkid = -1;
|
103
110
|
|
104
|
-
/*
|
111
|
+
/* Linux 2.6.22 (commit 83f7d958eab2fbc6b159ee92bf1493924e1d0f72) adds a busnum
|
112
|
+
* to sysfs, so we can relate devices. This also implies that we can read
|
105
113
|
* the active configuration through bConfigurationValue */
|
106
|
-
static int sysfs_can_relate_devices =
|
114
|
+
static int sysfs_can_relate_devices = -1;
|
115
|
+
|
116
|
+
/* Linux 2.6.26 (commit 217a9081d8e69026186067711131b77f0ce219ed) adds all
|
117
|
+
* config descriptors (rather then just the active config) to the sysfs
|
118
|
+
* descriptors file, so from then on we can use them. */
|
119
|
+
static int sysfs_has_descriptors = -1;
|
120
|
+
|
121
|
+
/* how many times have we initted (and not exited) ? */
|
122
|
+
static volatile int init_count = 0;
|
123
|
+
|
124
|
+
/* Serialize hotplug start/stop */
|
125
|
+
usbi_mutex_static_t linux_hotplug_startstop_lock = USBI_MUTEX_INITIALIZER;
|
126
|
+
/* Serialize scan-devices, event-thread, and poll */
|
127
|
+
usbi_mutex_static_t linux_hotplug_lock = USBI_MUTEX_INITIALIZER;
|
107
128
|
|
108
|
-
|
109
|
-
static int
|
129
|
+
static int linux_start_event_monitor(void);
|
130
|
+
static int linux_stop_event_monitor(void);
|
131
|
+
static int linux_scan_devices(struct libusb_context *ctx);
|
132
|
+
static int sysfs_scan_device(struct libusb_context *ctx, const char *devname);
|
133
|
+
static int detach_kernel_driver_and_claim(struct libusb_device_handle *, int);
|
134
|
+
|
135
|
+
#if !defined(USE_UDEV)
|
136
|
+
static int linux_default_scan_devices (struct libusb_context *ctx);
|
137
|
+
#endif
|
110
138
|
|
111
139
|
struct linux_device_priv {
|
112
140
|
char *sysfs_dir;
|
113
|
-
unsigned char *
|
114
|
-
|
141
|
+
unsigned char *descriptors;
|
142
|
+
int descriptors_len;
|
143
|
+
int active_config; /* cache val for !sysfs_can_relate_devices */
|
115
144
|
};
|
116
145
|
|
117
146
|
struct linux_device_handle_priv {
|
@@ -150,14 +179,36 @@ struct linux_transfer_priv {
|
|
150
179
|
int iso_packet_offset;
|
151
180
|
};
|
152
181
|
|
153
|
-
static
|
182
|
+
static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
|
154
183
|
{
|
184
|
+
struct libusb_context *ctx = DEVICE_CTX(dev);
|
185
|
+
char path[PATH_MAX];
|
186
|
+
int fd;
|
187
|
+
|
155
188
|
if (usbdev_names)
|
156
189
|
snprintf(path, PATH_MAX, "%s/usbdev%d.%d",
|
157
190
|
usbfs_path, dev->bus_number, dev->device_address);
|
158
191
|
else
|
159
192
|
snprintf(path, PATH_MAX, "%s/%03d/%03d",
|
160
193
|
usbfs_path, dev->bus_number, dev->device_address);
|
194
|
+
|
195
|
+
fd = open(path, mode);
|
196
|
+
if (fd != -1)
|
197
|
+
return fd; /* Success */
|
198
|
+
|
199
|
+
if (!silent) {
|
200
|
+
usbi_err(ctx, "libusbx couldn't open USB device %s: %s",
|
201
|
+
path, strerror(errno));
|
202
|
+
if (errno == EACCES && mode == O_RDWR)
|
203
|
+
usbi_err(ctx, "libusbx requires write access to USB "
|
204
|
+
"device nodes.");
|
205
|
+
}
|
206
|
+
|
207
|
+
if (errno == EACCES)
|
208
|
+
return LIBUSB_ERROR_ACCESS;
|
209
|
+
if (errno == ENOENT)
|
210
|
+
return LIBUSB_ERROR_NO_DEVICE;
|
211
|
+
return LIBUSB_ERROR_IO;
|
161
212
|
}
|
162
213
|
|
163
214
|
static struct linux_device_priv *_device_priv(struct libusb_device *dev)
|
@@ -300,22 +351,6 @@ static int kernel_version_ge(int major, int minor, int sublevel)
|
|
300
351
|
return ksublevel >= sublevel;
|
301
352
|
}
|
302
353
|
|
303
|
-
/* Return 1 if filename exists inside dirname in sysfs.
|
304
|
-
SYSFS_DEVICE_PATH is assumed to be the beginning of the path. */
|
305
|
-
static int sysfs_has_file(const char *dirname, const char *filename)
|
306
|
-
{
|
307
|
-
struct stat statbuf;
|
308
|
-
char path[PATH_MAX];
|
309
|
-
int r;
|
310
|
-
|
311
|
-
snprintf(path, PATH_MAX, "%s/%s/%s", SYSFS_DEVICE_PATH, dirname, filename);
|
312
|
-
r = stat(path, &statbuf);
|
313
|
-
if (r == 0 && S_ISREG(statbuf.st_mode))
|
314
|
-
return 1;
|
315
|
-
|
316
|
-
return 0;
|
317
|
-
}
|
318
|
-
|
319
354
|
static int op_init(struct libusb_context *ctx)
|
320
355
|
{
|
321
356
|
struct stat statbuf;
|
@@ -354,79 +389,111 @@ static int op_init(struct libusb_context *ctx)
|
|
354
389
|
if (supports_flag_zero_packet)
|
355
390
|
usbi_dbg("zero length packet flag supported");
|
356
391
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
392
|
+
if (-1 == sysfs_has_descriptors) {
|
393
|
+
/* sysfs descriptors has all descriptors since Linux 2.6.26 */
|
394
|
+
sysfs_has_descriptors = kernel_version_ge(2,6,26);
|
395
|
+
if (-1 == sysfs_has_descriptors) {
|
396
|
+
usbi_err(ctx, "error checking for sysfs descriptors");
|
397
|
+
return LIBUSB_ERROR_OTHER;
|
398
|
+
}
|
399
|
+
}
|
363
400
|
|
364
|
-
|
365
|
-
|
366
|
-
|
401
|
+
if (-1 == sysfs_can_relate_devices) {
|
402
|
+
/* sysfs has busnum since Linux 2.6.22 */
|
403
|
+
sysfs_can_relate_devices = kernel_version_ge(2,6,22);
|
404
|
+
if (-1 == sysfs_can_relate_devices) {
|
405
|
+
usbi_err(ctx, "error checking for sysfs busnum");
|
406
|
+
return LIBUSB_ERROR_OTHER;
|
367
407
|
}
|
408
|
+
}
|
368
409
|
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
* because a device disconnection will cause a race
|
378
|
-
* condition regarding which files are available, sometimes
|
379
|
-
* causing an incorrect result. The root hubs are used
|
380
|
-
* because it is assumed that they will always be present.
|
381
|
-
* See the "sysfs vs usbfs" comment at the top of this file
|
382
|
-
* for more details. */
|
383
|
-
while ((entry = readdir(devices))) {
|
384
|
-
int has_busnum=0, has_devnum=0, has_descriptors=0;
|
385
|
-
int has_configuration_value=0;
|
386
|
-
|
387
|
-
/* Only check the usbN directories. */
|
388
|
-
if (strncmp(entry->d_name, "usb", 3) != 0)
|
389
|
-
continue;
|
410
|
+
if (sysfs_can_relate_devices || sysfs_has_descriptors) {
|
411
|
+
r = stat(SYSFS_DEVICE_PATH, &statbuf);
|
412
|
+
if (r != 0 || !S_ISDIR(statbuf.st_mode)) {
|
413
|
+
usbi_warn(ctx, "sysfs not mounted");
|
414
|
+
sysfs_can_relate_devices = 0;
|
415
|
+
sysfs_has_descriptors = 0;
|
416
|
+
}
|
417
|
+
}
|
390
418
|
|
391
|
-
|
392
|
-
|
393
|
-
has_devnum = sysfs_has_file(entry->d_name, "devnum");
|
394
|
-
has_descriptors = sysfs_has_file(entry->d_name, "descriptors");
|
395
|
-
has_configuration_value = sysfs_has_file(entry->d_name, "bConfigurationValue");
|
419
|
+
if (sysfs_can_relate_devices)
|
420
|
+
usbi_dbg("sysfs can relate devices");
|
396
421
|
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
422
|
+
if (sysfs_has_descriptors)
|
423
|
+
usbi_dbg("sysfs has complete descriptors");
|
424
|
+
|
425
|
+
usbi_mutex_static_lock(&linux_hotplug_startstop_lock);
|
426
|
+
r = LIBUSB_SUCCESS;
|
427
|
+
if (init_count == 0) {
|
428
|
+
/* start up hotplug event handler */
|
429
|
+
r = linux_start_event_monitor();
|
430
|
+
}
|
431
|
+
if (r == LIBUSB_SUCCESS) {
|
432
|
+
r = linux_scan_devices(ctx);
|
433
|
+
if (r == LIBUSB_SUCCESS)
|
434
|
+
init_count++;
|
435
|
+
else if (init_count == 0)
|
436
|
+
linux_stop_event_monitor();
|
437
|
+
} else
|
438
|
+
usbi_err(ctx, "error starting hotplug event monitor");
|
439
|
+
usbi_mutex_static_unlock(&linux_hotplug_startstop_lock);
|
401
440
|
|
402
|
-
|
403
|
-
|
404
|
-
if (sysfs_has_descriptors && sysfs_can_relate_devices)
|
405
|
-
break;
|
406
|
-
}
|
407
|
-
closedir(devices);
|
441
|
+
return r;
|
442
|
+
}
|
408
443
|
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
sysfs_can_relate_devices = 0;
|
444
|
+
static void op_exit(void)
|
445
|
+
{
|
446
|
+
usbi_mutex_static_lock(&linux_hotplug_startstop_lock);
|
447
|
+
assert(init_count != 0);
|
448
|
+
if (!--init_count) {
|
449
|
+
/* tear down event handler */
|
450
|
+
(void)linux_stop_event_monitor();
|
417
451
|
}
|
452
|
+
usbi_mutex_static_unlock(&linux_hotplug_startstop_lock);
|
453
|
+
}
|
418
454
|
|
419
|
-
|
455
|
+
static int linux_start_event_monitor(void)
|
456
|
+
{
|
457
|
+
#if defined(USE_UDEV)
|
458
|
+
return linux_udev_start_event_monitor();
|
459
|
+
#else
|
460
|
+
return linux_netlink_start_event_monitor();
|
461
|
+
#endif
|
420
462
|
}
|
421
463
|
|
422
|
-
static int
|
423
|
-
unsigned char *buffer)
|
464
|
+
static int linux_stop_event_monitor(void)
|
424
465
|
{
|
425
|
-
|
466
|
+
#if defined(USE_UDEV)
|
467
|
+
return linux_udev_stop_event_monitor();
|
468
|
+
#else
|
469
|
+
return linux_netlink_stop_event_monitor();
|
470
|
+
#endif
|
471
|
+
}
|
426
472
|
|
427
|
-
|
428
|
-
|
429
|
-
|
473
|
+
static int linux_scan_devices(struct libusb_context *ctx)
|
474
|
+
{
|
475
|
+
int ret;
|
476
|
+
|
477
|
+
usbi_mutex_static_lock(&linux_hotplug_lock);
|
478
|
+
|
479
|
+
#if defined(USE_UDEV)
|
480
|
+
ret = linux_udev_scan_devices(ctx);
|
481
|
+
#else
|
482
|
+
ret = linux_default_scan_devices(ctx);
|
483
|
+
#endif
|
484
|
+
|
485
|
+
usbi_mutex_static_unlock(&linux_hotplug_lock);
|
486
|
+
|
487
|
+
return ret;
|
488
|
+
}
|
489
|
+
|
490
|
+
static void op_hotplug_poll(void)
|
491
|
+
{
|
492
|
+
#if defined(USE_UDEV)
|
493
|
+
linux_udev_hotplug_poll();
|
494
|
+
#else
|
495
|
+
linux_netlink_hotplug_poll();
|
496
|
+
#endif
|
430
497
|
}
|
431
498
|
|
432
499
|
static int _open_sysfs_attr(struct libusb_device *dev, const char *attr)
|
@@ -482,52 +549,14 @@ static int __read_sysfs_attr(struct libusb_context *ctx,
|
|
482
549
|
return value;
|
483
550
|
}
|
484
551
|
|
485
|
-
static int sysfs_get_device_descriptor(struct libusb_device *dev,
|
486
|
-
unsigned char *buffer)
|
487
|
-
{
|
488
|
-
int fd;
|
489
|
-
ssize_t r;
|
490
|
-
|
491
|
-
/* sysfs provides access to an in-memory copy of the device descriptor,
|
492
|
-
* so we use that rather than keeping our own copy */
|
493
|
-
|
494
|
-
fd = _open_sysfs_attr(dev, "descriptors");
|
495
|
-
if (fd < 0)
|
496
|
-
return fd;
|
497
|
-
|
498
|
-
r = read(fd, buffer, DEVICE_DESC_LENGTH);;
|
499
|
-
close(fd);
|
500
|
-
if (r < 0) {
|
501
|
-
usbi_err(DEVICE_CTX(dev), "read failed, ret=%d errno=%d", fd, errno);
|
502
|
-
return LIBUSB_ERROR_IO;
|
503
|
-
} else if (r < DEVICE_DESC_LENGTH) {
|
504
|
-
usbi_err(DEVICE_CTX(dev), "short read %d/%d", r, DEVICE_DESC_LENGTH);
|
505
|
-
return LIBUSB_ERROR_IO;
|
506
|
-
}
|
507
|
-
|
508
|
-
return 0;
|
509
|
-
}
|
510
|
-
|
511
552
|
static int op_get_device_descriptor(struct libusb_device *dev,
|
512
553
|
unsigned char *buffer, int *host_endian)
|
513
|
-
{
|
514
|
-
if (sysfs_has_descriptors) {
|
515
|
-
return sysfs_get_device_descriptor(dev, buffer);
|
516
|
-
} else {
|
517
|
-
*host_endian = 1;
|
518
|
-
return usbfs_get_device_descriptor(dev, buffer);
|
519
|
-
}
|
520
|
-
}
|
521
|
-
|
522
|
-
static int usbfs_get_active_config_descriptor(struct libusb_device *dev,
|
523
|
-
unsigned char *buffer, size_t len)
|
524
554
|
{
|
525
555
|
struct linux_device_priv *priv = _device_priv(dev);
|
526
|
-
if (!priv->config_descriptor)
|
527
|
-
return LIBUSB_ERROR_NOT_FOUND; /* device is unconfigured */
|
528
556
|
|
529
|
-
|
530
|
-
memcpy(buffer, priv->
|
557
|
+
*host_endian = sysfs_has_descriptors ? 0 : 1;
|
558
|
+
memcpy(buffer, priv->descriptors, DEVICE_DESC_LENGTH);
|
559
|
+
|
531
560
|
return 0;
|
532
561
|
}
|
533
562
|
|
@@ -574,250 +603,220 @@ static int sysfs_get_active_config(struct libusb_device *dev, int *config)
|
|
574
603
|
return 0;
|
575
604
|
}
|
576
605
|
|
577
|
-
|
578
|
-
*
|
579
|
-
|
580
|
-
int host_endian)
|
606
|
+
int linux_get_device_address (struct libusb_context *ctx, int detached,
|
607
|
+
uint8_t *busnum, uint8_t *devaddr,const char *dev_node,
|
608
|
+
const char *sys_name)
|
581
609
|
{
|
582
|
-
|
583
|
-
unsigned char tmp[6];
|
584
|
-
off_t off;
|
585
|
-
ssize_t r;
|
610
|
+
int sysfs_attr;
|
586
611
|
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
return LIBUSB_ERROR_IO;
|
595
|
-
}
|
612
|
+
usbi_dbg("getting address for device: %s detached: %d", sys_name, detached);
|
613
|
+
/* can't use sysfs to read the bus and device number if the
|
614
|
+
* device has been detached */
|
615
|
+
if (!sysfs_can_relate_devices || detached || NULL == sys_name) {
|
616
|
+
if (NULL == dev_node) {
|
617
|
+
return LIBUSB_ERROR_OTHER;
|
618
|
+
}
|
596
619
|
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
620
|
+
/* will this work with all supported kernel versions? */
|
621
|
+
if (!strncmp(dev_node, "/dev/bus/usb", 12)) {
|
622
|
+
sscanf (dev_node, "/dev/bus/usb/%hhd/%hhd", busnum, devaddr);
|
623
|
+
} else if (!strncmp(dev_node, "/proc/bus/usb", 13)) {
|
624
|
+
sscanf (dev_node, "/proc/bus/usb/%hhd/%hhd", busnum, devaddr);
|
625
|
+
}
|
626
|
+
|
627
|
+
return LIBUSB_SUCCESS;
|
603
628
|
}
|
604
629
|
|
605
|
-
|
630
|
+
usbi_dbg("scan %s", sys_name);
|
631
|
+
|
632
|
+
sysfs_attr = __read_sysfs_attr(ctx, sys_name, "busnum");
|
633
|
+
if (0 > sysfs_attr)
|
634
|
+
return sysfs_attr;
|
635
|
+
if (sysfs_attr > 255)
|
636
|
+
return LIBUSB_ERROR_INVALID_PARAM;
|
637
|
+
*busnum = (uint8_t) sysfs_attr;
|
638
|
+
|
639
|
+
sysfs_attr = __read_sysfs_attr(ctx, sys_name, "devnum");
|
640
|
+
if (0 > sysfs_attr)
|
641
|
+
return sysfs_attr;
|
642
|
+
if (sysfs_attr > 255)
|
643
|
+
return LIBUSB_ERROR_INVALID_PARAM;
|
644
|
+
|
645
|
+
*devaddr = (uint8_t) sysfs_attr;
|
646
|
+
|
647
|
+
usbi_dbg("bus=%d dev=%d", *busnum, *devaddr);
|
648
|
+
|
649
|
+
return LIBUSB_SUCCESS;
|
606
650
|
}
|
607
651
|
|
608
|
-
|
609
|
-
|
652
|
+
/* Return offset of the next descriptor with the given type */
|
653
|
+
static int seek_to_next_descriptor(struct libusb_context *ctx,
|
654
|
+
uint8_t descriptor_type, unsigned char *buffer, int size)
|
610
655
|
{
|
611
|
-
|
612
|
-
|
613
|
-
off_t off;
|
614
|
-
int to_copy;
|
615
|
-
int config;
|
616
|
-
unsigned char tmp[6];
|
656
|
+
struct usb_descriptor_header header;
|
657
|
+
int i;
|
617
658
|
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
if (config == -1)
|
622
|
-
return LIBUSB_ERROR_NOT_FOUND;
|
659
|
+
for (i = 0; size >= 0; i += header.bLength, size -= header.bLength) {
|
660
|
+
if (size == 0)
|
661
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
623
662
|
|
624
|
-
|
663
|
+
if (size < 2) {
|
664
|
+
usbi_err(ctx, "short descriptor read %d/2", size);
|
665
|
+
return LIBUSB_ERROR_IO;
|
666
|
+
}
|
667
|
+
usbi_parse_descriptor(buffer + i, "bb", &header, 0);
|
625
668
|
|
626
|
-
|
627
|
-
|
669
|
+
if (i && header.bDescriptorType == descriptor_type)
|
670
|
+
return i;
|
671
|
+
}
|
672
|
+
usbi_err(ctx, "bLength overflow by %d bytes", -size);
|
673
|
+
return LIBUSB_ERROR_IO;
|
674
|
+
}
|
628
675
|
|
629
|
-
|
630
|
-
|
631
|
-
|
676
|
+
/* Return offset to next config */
|
677
|
+
static int seek_to_next_config(struct libusb_context *ctx,
|
678
|
+
unsigned char *buffer, int size)
|
679
|
+
{
|
680
|
+
struct libusb_config_descriptor config;
|
632
681
|
|
633
|
-
|
634
|
-
* so first check that there is any config descriptor data at all... */
|
635
|
-
off = lseek(fd, 0, SEEK_END);
|
636
|
-
if (off < 1) {
|
637
|
-
usbi_err(DEVICE_CTX(dev), "end seek failed, ret=%d errno=%d",
|
638
|
-
off, errno);
|
639
|
-
close(fd);
|
640
|
-
return LIBUSB_ERROR_IO;
|
641
|
-
} else if (off == DEVICE_DESC_LENGTH) {
|
642
|
-
close(fd);
|
682
|
+
if (size == 0)
|
643
683
|
return LIBUSB_ERROR_NOT_FOUND;
|
684
|
+
|
685
|
+
if (size < LIBUSB_DT_CONFIG_SIZE) {
|
686
|
+
usbi_err(ctx, "short descriptor read %d/%d",
|
687
|
+
size, LIBUSB_DT_CONFIG_SIZE);
|
688
|
+
return LIBUSB_ERROR_IO;
|
644
689
|
}
|
645
690
|
|
646
|
-
|
647
|
-
if (
|
648
|
-
usbi_err(
|
649
|
-
|
691
|
+
usbi_parse_descriptor(buffer, "bbwbbbbb", &config, 0);
|
692
|
+
if (config.bDescriptorType != LIBUSB_DT_CONFIG) {
|
693
|
+
usbi_err(ctx, "descriptor is not a config desc (type 0x%02x)",
|
694
|
+
config.bDescriptorType);
|
650
695
|
return LIBUSB_ERROR_IO;
|
651
696
|
}
|
652
697
|
|
653
|
-
/*
|
654
|
-
*
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
698
|
+
/*
|
699
|
+
* In usbfs the config descriptors are config.wTotalLength bytes apart,
|
700
|
+
* with any short reads from the device appearing as holes in the file.
|
701
|
+
*
|
702
|
+
* In sysfs wTotalLength is ignored, instead the kernel returns a
|
703
|
+
* config descriptor with verified bLength fields, with descriptors
|
704
|
+
* with an invalid bLength removed.
|
705
|
+
*/
|
706
|
+
if (sysfs_has_descriptors) {
|
707
|
+
int next = seek_to_next_descriptor(ctx, LIBUSB_DT_CONFIG,
|
708
|
+
buffer, size);
|
709
|
+
if (next == LIBUSB_ERROR_NOT_FOUND)
|
710
|
+
next = size;
|
711
|
+
if (next < 0)
|
712
|
+
return next;
|
713
|
+
|
714
|
+
if (next != config.wTotalLength)
|
715
|
+
usbi_warn(ctx, "config length mismatch wTotalLength "
|
716
|
+
"%d real %d", config.wTotalLength, next);
|
717
|
+
return next;
|
718
|
+
} else {
|
719
|
+
if (config.wTotalLength < LIBUSB_DT_CONFIG_SIZE) {
|
720
|
+
usbi_err(ctx, "invalid wTotalLength %d",
|
721
|
+
config.wTotalLength);
|
663
722
|
return LIBUSB_ERROR_IO;
|
664
|
-
}
|
723
|
+
} else if (config.wTotalLength > size) {
|
724
|
+
usbi_warn(ctx, "short descriptor read %d/%d",
|
725
|
+
size, config.wTotalLength);
|
726
|
+
return size;
|
727
|
+
} else
|
728
|
+
return config.wTotalLength;
|
729
|
+
}
|
730
|
+
}
|
665
731
|
|
666
|
-
|
667
|
-
|
668
|
-
|
732
|
+
static int op_get_config_descriptor_by_value(struct libusb_device *dev,
|
733
|
+
uint8_t value, unsigned char **buffer, int *host_endian)
|
734
|
+
{
|
735
|
+
struct libusb_context *ctx = DEVICE_CTX(dev);
|
736
|
+
struct linux_device_priv *priv = _device_priv(dev);
|
737
|
+
unsigned char *descriptors = priv->descriptors;
|
738
|
+
int size = priv->descriptors_len;
|
739
|
+
struct libusb_config_descriptor *config;
|
669
740
|
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
return LIBUSB_ERROR_IO;
|
741
|
+
*buffer = NULL;
|
742
|
+
/* Unlike the device desc. config descs. are always in raw format */
|
743
|
+
*host_endian = 0;
|
674
744
|
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
}
|
745
|
+
/* Skip device header */
|
746
|
+
descriptors += DEVICE_DESC_LENGTH;
|
747
|
+
size -= DEVICE_DESC_LENGTH;
|
679
748
|
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
usbi_dbg("device is unconfigured");
|
690
|
-
r = LIBUSB_ERROR_NOT_FOUND;
|
691
|
-
} else if (r < len - sizeof(tmp)) {
|
692
|
-
usbi_err(DEVICE_CTX(dev), "short read %d/%d", r, len);
|
693
|
-
r = LIBUSB_ERROR_IO;
|
749
|
+
/* Seek till the config is found, or till "EOF" */
|
750
|
+
while (1) {
|
751
|
+
int next = seek_to_next_config(ctx, descriptors, size);
|
752
|
+
if (next < 0)
|
753
|
+
return next;
|
754
|
+
config = (struct libusb_config_descriptor *)descriptors;
|
755
|
+
if (config->bConfigurationValue == value) {
|
756
|
+
*buffer = descriptors;
|
757
|
+
return next;
|
694
758
|
}
|
695
|
-
|
696
|
-
|
759
|
+
size -= next;
|
760
|
+
descriptors += next;
|
697
761
|
}
|
698
|
-
|
699
|
-
close(fd);
|
700
|
-
return r;
|
701
762
|
}
|
702
763
|
|
703
764
|
static int op_get_active_config_descriptor(struct libusb_device *dev,
|
704
765
|
unsigned char *buffer, size_t len, int *host_endian)
|
705
766
|
{
|
706
|
-
|
707
|
-
|
708
|
-
} else {
|
709
|
-
return usbfs_get_active_config_descriptor(dev, buffer, len);
|
710
|
-
}
|
711
|
-
}
|
767
|
+
int r, config;
|
768
|
+
unsigned char *config_desc;
|
712
769
|
|
713
|
-
|
714
|
-
|
715
|
-
static int get_config_descriptor(struct libusb_context *ctx, int fd,
|
716
|
-
uint8_t config_index, unsigned char *buffer, size_t len)
|
717
|
-
{
|
718
|
-
off_t off;
|
719
|
-
ssize_t r;
|
720
|
-
|
721
|
-
off = lseek(fd, DEVICE_DESC_LENGTH, SEEK_SET);
|
722
|
-
if (off < 0) {
|
723
|
-
usbi_err(ctx, "seek failed ret=%d errno=%d", off, errno);
|
724
|
-
return LIBUSB_ERROR_IO;
|
725
|
-
}
|
726
|
-
|
727
|
-
/* might need to skip some configuration descriptors to reach the
|
728
|
-
* requested configuration */
|
729
|
-
while (config_index > 0) {
|
730
|
-
r = seek_to_next_config(ctx, fd, 1);
|
770
|
+
if (sysfs_can_relate_devices) {
|
771
|
+
r = sysfs_get_active_config(dev, &config);
|
731
772
|
if (r < 0)
|
732
773
|
return r;
|
733
|
-
|
774
|
+
} else {
|
775
|
+
/* Use cached bConfigurationValue */
|
776
|
+
struct linux_device_priv *priv = _device_priv(dev);
|
777
|
+
config = priv->active_config;
|
734
778
|
}
|
779
|
+
if (config == -1)
|
780
|
+
return LIBUSB_ERROR_NOT_FOUND;
|
735
781
|
|
736
|
-
|
737
|
-
|
738
|
-
if (r < 0)
|
739
|
-
|
740
|
-
return LIBUSB_ERROR_IO;
|
741
|
-
} else if (r < len) {
|
742
|
-
usbi_err(ctx, "short output read %d/%d", r, len);
|
743
|
-
return LIBUSB_ERROR_IO;
|
744
|
-
}
|
782
|
+
r = op_get_config_descriptor_by_value(dev, config, &config_desc,
|
783
|
+
host_endian);
|
784
|
+
if (r < 0)
|
785
|
+
return r;
|
745
786
|
|
746
|
-
|
787
|
+
len = MIN(len, r);
|
788
|
+
memcpy(buffer, config_desc, len);
|
789
|
+
return len;
|
747
790
|
}
|
748
791
|
|
749
792
|
static int op_get_config_descriptor(struct libusb_device *dev,
|
750
793
|
uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian)
|
751
794
|
{
|
752
|
-
|
753
|
-
|
754
|
-
int r;
|
755
|
-
|
756
|
-
/* always read from usbfs: sysfs only has the active descriptor
|
757
|
-
* this will involve waking the device up, but oh well! */
|
758
|
-
|
759
|
-
/* FIXME: the above is no longer true, new kernels have all descriptors
|
760
|
-
* in the descriptors file. but its kinda hard to detect if the kernel
|
761
|
-
* is sufficiently new. */
|
762
|
-
|
763
|
-
_get_usbfs_path(dev, filename);
|
764
|
-
fd = open(filename, O_RDONLY);
|
765
|
-
if (fd < 0) {
|
766
|
-
usbi_err(DEVICE_CTX(dev),
|
767
|
-
"open '%s' failed, ret=%d errno=%d", filename, fd, errno);
|
768
|
-
return LIBUSB_ERROR_IO;
|
769
|
-
}
|
795
|
+
struct linux_device_priv *priv = _device_priv(dev);
|
796
|
+
unsigned char *descriptors = priv->descriptors;
|
797
|
+
int i, r, size = priv->descriptors_len;
|
770
798
|
|
771
|
-
|
772
|
-
|
773
|
-
return r;
|
774
|
-
}
|
799
|
+
/* Unlike the device desc. config descs. are always in raw format */
|
800
|
+
*host_endian = 0;
|
775
801
|
|
776
|
-
/*
|
777
|
-
|
778
|
-
|
779
|
-
static int cache_active_config(struct libusb_device *dev, int fd,
|
780
|
-
int active_config)
|
781
|
-
{
|
782
|
-
struct linux_device_priv *priv = _device_priv(dev);
|
783
|
-
struct libusb_config_descriptor config;
|
784
|
-
unsigned char tmp[8];
|
785
|
-
unsigned char *buf;
|
786
|
-
int idx;
|
787
|
-
int r;
|
802
|
+
/* Skip device header */
|
803
|
+
descriptors += DEVICE_DESC_LENGTH;
|
804
|
+
size -= DEVICE_DESC_LENGTH;
|
788
805
|
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
r = usbi_get_config_index_by_value(dev, active_config, &idx);
|
806
|
+
/* Seek till the config is found, or till "EOF" */
|
807
|
+
for (i = 0; ; i++) {
|
808
|
+
r = seek_to_next_config(DEVICE_CTX(dev), descriptors, size);
|
793
809
|
if (r < 0)
|
794
810
|
return r;
|
795
|
-
if (
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
r = get_config_descriptor(DEVICE_CTX(dev), fd, idx, tmp, sizeof(tmp));
|
800
|
-
if (r < 0) {
|
801
|
-
usbi_err(DEVICE_CTX(dev), "first read error %d", r);
|
802
|
-
return r;
|
803
|
-
}
|
804
|
-
|
805
|
-
usbi_parse_descriptor(tmp, "bbw", &config, 0);
|
806
|
-
buf = malloc(config.wTotalLength);
|
807
|
-
if (!buf)
|
808
|
-
return LIBUSB_ERROR_NO_MEM;
|
809
|
-
|
810
|
-
r = get_config_descriptor(DEVICE_CTX(dev), fd, idx, buf,
|
811
|
-
config.wTotalLength);
|
812
|
-
if (r < 0) {
|
813
|
-
free(buf);
|
814
|
-
return r;
|
811
|
+
if (i == config_index)
|
812
|
+
break;
|
813
|
+
size -= r;
|
814
|
+
descriptors += r;
|
815
815
|
}
|
816
816
|
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
return 0;
|
817
|
+
len = MIN(len, r);
|
818
|
+
memcpy(buffer, descriptors, len);
|
819
|
+
return len;
|
821
820
|
}
|
822
821
|
|
823
822
|
/* send a control message to retrieve active configuration */
|
@@ -854,11 +853,9 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
|
|
854
853
|
uint8_t devaddr, const char *sysfs_dir)
|
855
854
|
{
|
856
855
|
struct linux_device_priv *priv = _device_priv(dev);
|
857
|
-
|
858
|
-
|
856
|
+
struct libusb_context *ctx = DEVICE_CTX(dev);
|
857
|
+
int descriptors_size = 512; /* Begin with a 1024 byte alloc */
|
859
858
|
int fd, speed;
|
860
|
-
int active_config = 0;
|
861
|
-
int device_configured = 1;
|
862
859
|
ssize_t r;
|
863
860
|
|
864
861
|
dev->bus_number = busnum;
|
@@ -885,113 +882,162 @@ static int initialize_device(struct libusb_device *dev, uint8_t busnum,
|
|
885
882
|
}
|
886
883
|
}
|
887
884
|
|
885
|
+
/* cache descriptors in memory */
|
888
886
|
if (sysfs_has_descriptors)
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
887
|
+
fd = _open_sysfs_attr(dev, "descriptors");
|
888
|
+
else
|
889
|
+
fd = _get_usbfs_fd(dev, O_RDONLY, 0);
|
890
|
+
if (fd < 0)
|
891
|
+
return fd;
|
893
892
|
|
894
|
-
|
895
|
-
|
893
|
+
do {
|
894
|
+
descriptors_size *= 2;
|
895
|
+
priv->descriptors = usbi_reallocf(priv->descriptors,
|
896
|
+
descriptors_size);
|
897
|
+
if (!priv->descriptors) {
|
898
|
+
close(fd);
|
899
|
+
return LIBUSB_ERROR_NO_MEM;
|
900
|
+
}
|
901
|
+
/* usbfs has holes in the file */
|
902
|
+
if (!sysfs_has_descriptors) {
|
903
|
+
memset(priv->descriptors + priv->descriptors_len,
|
904
|
+
0, descriptors_size - priv->descriptors_len);
|
905
|
+
}
|
906
|
+
r = read(fd, priv->descriptors + priv->descriptors_len,
|
907
|
+
descriptors_size - priv->descriptors_len);
|
908
|
+
if (r < 0) {
|
909
|
+
usbi_err(ctx, "read descriptor failed ret=%d errno=%d",
|
910
|
+
fd, errno);
|
911
|
+
close(fd);
|
912
|
+
return LIBUSB_ERROR_IO;
|
913
|
+
}
|
914
|
+
priv->descriptors_len += r;
|
915
|
+
} while (priv->descriptors_len == descriptors_size);
|
916
|
+
|
917
|
+
close(fd);
|
896
918
|
|
897
|
-
if (
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
if (active_config == -1)
|
902
|
-
device_configured = 0;
|
919
|
+
if (priv->descriptors_len < DEVICE_DESC_LENGTH) {
|
920
|
+
usbi_err(ctx, "short descriptor read (%d)",
|
921
|
+
priv->descriptors_len);
|
922
|
+
return LIBUSB_ERROR_IO;
|
903
923
|
}
|
904
924
|
|
905
|
-
|
906
|
-
|
907
|
-
if (fd < 0 && errno == EACCES) {
|
908
|
-
fd = open(path, O_RDONLY);
|
909
|
-
/* if we only have read-only access to the device, we cannot
|
910
|
-
* send a control message to determine the active config. just
|
911
|
-
* assume the first one is active. */
|
912
|
-
active_config = -1;
|
913
|
-
}
|
925
|
+
if (sysfs_can_relate_devices)
|
926
|
+
return LIBUSB_SUCCESS;
|
914
927
|
|
928
|
+
/* cache active config */
|
929
|
+
fd = _get_usbfs_fd(dev, O_RDWR, 1);
|
915
930
|
if (fd < 0) {
|
916
|
-
|
917
|
-
|
918
|
-
|
931
|
+
/* cannot send a control message to determine the active
|
932
|
+
* config. just assume the first one is active. */
|
933
|
+
usbi_warn(ctx, "Missing rw usbfs access; cannot determine "
|
934
|
+
"active configuration descriptor");
|
935
|
+
if (priv->descriptors_len >=
|
936
|
+
(DEVICE_DESC_LENGTH + LIBUSB_DT_CONFIG_SIZE)) {
|
937
|
+
struct libusb_config_descriptor config;
|
938
|
+
usbi_parse_descriptor(
|
939
|
+
priv->descriptors + DEVICE_DESC_LENGTH,
|
940
|
+
"bbwbbbbb", &config, 0);
|
941
|
+
priv->active_config = config.bConfigurationValue;
|
942
|
+
} else
|
943
|
+
priv->active_config = -1; /* No config dt */
|
944
|
+
|
945
|
+
return LIBUSB_SUCCESS;
|
946
|
+
}
|
947
|
+
|
948
|
+
r = usbfs_get_active_config(dev, fd);
|
949
|
+
if (r > 0) {
|
950
|
+
priv->active_config = r;
|
951
|
+
r = LIBUSB_SUCCESS;
|
952
|
+
} else if (r == 0) {
|
953
|
+
/* some buggy devices have a configuration 0, but we're
|
954
|
+
* reaching into the corner of a corner case here, so let's
|
955
|
+
* not support buggy devices in these circumstances.
|
956
|
+
* stick to the specs: a configuration value of 0 means
|
957
|
+
* unconfigured. */
|
958
|
+
usbi_dbg("active cfg 0? assuming unconfigured device");
|
959
|
+
priv->active_config = -1;
|
960
|
+
r = LIBUSB_SUCCESS;
|
961
|
+
} else if (r == LIBUSB_ERROR_IO) {
|
962
|
+
/* buggy devices sometimes fail to report their active config.
|
963
|
+
* assume unconfigured and continue the probing */
|
964
|
+
usbi_warn(ctx, "couldn't query active configuration, assuming"
|
965
|
+
" unconfigured");
|
966
|
+
priv->active_config = -1;
|
967
|
+
r = LIBUSB_SUCCESS;
|
968
|
+
} /* else r < 0, just return the error code */
|
919
969
|
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
970
|
+
close(fd);
|
971
|
+
return r;
|
972
|
+
}
|
973
|
+
|
974
|
+
static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_dir)
|
975
|
+
{
|
976
|
+
struct libusb_context *ctx = DEVICE_CTX(dev);
|
977
|
+
struct libusb_device *it;
|
978
|
+
char *parent_sysfs_dir, *tmp;
|
979
|
+
int ret, add_parent = 1;
|
980
|
+
|
981
|
+
/* XXX -- can we figure out the topology when using usbfs? */
|
982
|
+
if (NULL == sysfs_dir || 0 == strncmp(sysfs_dir, "usb", 3)) {
|
983
|
+
/* either using usbfs or finding the parent of a root hub */
|
984
|
+
return LIBUSB_SUCCESS;
|
985
|
+
}
|
986
|
+
|
987
|
+
parent_sysfs_dir = strdup(sysfs_dir);
|
988
|
+
if (NULL != (tmp = strrchr(parent_sysfs_dir, '.')) ||
|
989
|
+
NULL != (tmp = strrchr(parent_sysfs_dir, '-'))) {
|
990
|
+
dev->port_number = atoi(tmp + 1);
|
991
|
+
*tmp = '\0';
|
992
|
+
} else {
|
993
|
+
usbi_warn(ctx, "Can not parse sysfs_dir: %s, no parent info",
|
994
|
+
parent_sysfs_dir);
|
995
|
+
free (parent_sysfs_dir);
|
996
|
+
return LIBUSB_SUCCESS;
|
997
|
+
}
|
998
|
+
|
999
|
+
/* is the parent a root hub? */
|
1000
|
+
if (NULL == strchr(parent_sysfs_dir, '-')) {
|
1001
|
+
tmp = parent_sysfs_dir;
|
1002
|
+
ret = asprintf (&parent_sysfs_dir, "usb%s", tmp);
|
1003
|
+
free (tmp);
|
1004
|
+
if (0 > ret) {
|
1005
|
+
return LIBUSB_ERROR_NO_MEM;
|
947
1006
|
}
|
948
1007
|
}
|
949
1008
|
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
1009
|
+
retry:
|
1010
|
+
/* find the parent in the context */
|
1011
|
+
usbi_mutex_lock(&ctx->usb_devs_lock);
|
1012
|
+
list_for_each_entry(it, &ctx->usb_devs, list, struct libusb_device) {
|
1013
|
+
struct linux_device_priv *priv = _device_priv(it);
|
1014
|
+
if (0 == strcmp (priv->sysfs_dir, parent_sysfs_dir)) {
|
1015
|
+
dev->parent_dev = libusb_ref_device(it);
|
1016
|
+
break;
|
1017
|
+
}
|
954
1018
|
}
|
1019
|
+
usbi_mutex_unlock(&ctx->usb_devs_lock);
|
955
1020
|
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
return LIBUSB_ERROR_IO;
|
963
|
-
} else if (r < DEVICE_DESC_LENGTH) {
|
964
|
-
usbi_err(DEVICE_CTX(dev), "short descriptor read (%d)", r);
|
965
|
-
free(dev_buf);
|
966
|
-
close(fd);
|
967
|
-
return LIBUSB_ERROR_IO;
|
1021
|
+
if (!dev->parent_dev && add_parent) {
|
1022
|
+
usbi_dbg("parent_dev %s not enumerated yet, enumerating now",
|
1023
|
+
parent_sysfs_dir);
|
1024
|
+
sysfs_scan_device(ctx, parent_sysfs_dir);
|
1025
|
+
add_parent = 0;
|
1026
|
+
goto retry;
|
968
1027
|
}
|
969
1028
|
|
970
|
-
|
971
|
-
|
972
|
-
dev->num_configurations = dev_buf[DEVICE_DESC_LENGTH - 1];
|
1029
|
+
usbi_dbg("Dev %p (%s) has parent %p (%s) port %d", dev, sysfs_dir,
|
1030
|
+
dev->parent_dev, parent_sysfs_dir, dev->port_number);
|
973
1031
|
|
974
|
-
|
975
|
-
r = cache_active_config(dev, fd, active_config);
|
976
|
-
if (r < 0) {
|
977
|
-
close(fd);
|
978
|
-
free(dev_buf);
|
979
|
-
return r;
|
980
|
-
}
|
981
|
-
}
|
1032
|
+
free (parent_sysfs_dir);
|
982
1033
|
|
983
|
-
|
984
|
-
priv->dev_descriptor = dev_buf;
|
985
|
-
return 0;
|
1034
|
+
return LIBUSB_SUCCESS;
|
986
1035
|
}
|
987
1036
|
|
988
|
-
|
989
|
-
|
990
|
-
const char *sysfs_dir)
|
1037
|
+
int linux_enumerate_device(struct libusb_context *ctx,
|
1038
|
+
uint8_t busnum, uint8_t devaddr, const char *sysfs_dir)
|
991
1039
|
{
|
992
|
-
struct discovered_devs *discdevs;
|
993
1040
|
unsigned long session_id;
|
994
|
-
int need_unref = 0;
|
995
1041
|
struct libusb_device *dev;
|
996
1042
|
int r = 0;
|
997
1043
|
|
@@ -1002,48 +1048,73 @@ static int enumerate_device(struct libusb_context *ctx,
|
|
1002
1048
|
usbi_dbg("busnum %d devaddr %d session_id %ld", busnum, devaddr,
|
1003
1049
|
session_id);
|
1004
1050
|
|
1005
|
-
|
1006
|
-
|
1007
|
-
usbi_dbg("
|
1008
|
-
|
1009
|
-
} else {
|
1010
|
-
usbi_dbg("allocating new device for %d/%d (session %ld)",
|
1011
|
-
busnum, devaddr, session_id);
|
1012
|
-
dev = usbi_alloc_device(ctx, session_id);
|
1013
|
-
if (!dev)
|
1014
|
-
return LIBUSB_ERROR_NO_MEM;
|
1015
|
-
need_unref = 1;
|
1016
|
-
r = initialize_device(dev, busnum, devaddr, sysfs_dir);
|
1017
|
-
if (r < 0)
|
1018
|
-
goto out;
|
1019
|
-
r = usbi_sanitize_device(dev);
|
1020
|
-
if (r < 0)
|
1021
|
-
goto out;
|
1051
|
+
if (usbi_get_device_by_session_id(ctx, session_id)) {
|
1052
|
+
/* device already exists in the context */
|
1053
|
+
usbi_dbg("session_id %ld already exists", session_id);
|
1054
|
+
return LIBUSB_SUCCESS;
|
1022
1055
|
}
|
1023
1056
|
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1057
|
+
usbi_dbg("allocating new device for %d/%d (session %ld)",
|
1058
|
+
busnum, devaddr, session_id);
|
1059
|
+
dev = usbi_alloc_device(ctx, session_id);
|
1060
|
+
if (!dev)
|
1061
|
+
return LIBUSB_ERROR_NO_MEM;
|
1029
1062
|
|
1063
|
+
r = initialize_device(dev, busnum, devaddr, sysfs_dir);
|
1064
|
+
if (r < 0)
|
1065
|
+
goto out;
|
1066
|
+
r = usbi_sanitize_device(dev);
|
1067
|
+
if (r < 0)
|
1068
|
+
goto out;
|
1069
|
+
|
1070
|
+
r = linux_get_parent_info(dev, sysfs_dir);
|
1071
|
+
if (r < 0)
|
1072
|
+
goto out;
|
1030
1073
|
out:
|
1031
|
-
if (
|
1074
|
+
if (r < 0)
|
1032
1075
|
libusb_unref_device(dev);
|
1076
|
+
else
|
1077
|
+
usbi_connect_device(dev);
|
1078
|
+
|
1033
1079
|
return r;
|
1034
1080
|
}
|
1035
1081
|
|
1036
|
-
|
1037
|
-
|
1038
|
-
*
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1082
|
+
void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name)
|
1083
|
+
{
|
1084
|
+
struct libusb_context *ctx;
|
1085
|
+
|
1086
|
+
usbi_mutex_static_lock(&active_contexts_lock);
|
1087
|
+
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
|
1088
|
+
linux_enumerate_device(ctx, busnum, devaddr, sys_name);
|
1089
|
+
}
|
1090
|
+
usbi_mutex_static_unlock(&active_contexts_lock);
|
1091
|
+
}
|
1092
|
+
|
1093
|
+
void linux_device_disconnected(uint8_t busnum, uint8_t devaddr, const char *sys_name)
|
1094
|
+
{
|
1095
|
+
struct libusb_context *ctx;
|
1096
|
+
struct libusb_device *dev;
|
1097
|
+
unsigned long session_id = busnum << 8 | devaddr;
|
1098
|
+
|
1099
|
+
usbi_mutex_static_lock(&active_contexts_lock);
|
1100
|
+
list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) {
|
1101
|
+
dev = usbi_get_device_by_session_id (ctx, session_id);
|
1102
|
+
if (NULL != dev) {
|
1103
|
+
usbi_disconnect_device (dev);
|
1104
|
+
} else {
|
1105
|
+
usbi_dbg("device not found for session %x", session_id);
|
1106
|
+
}
|
1107
|
+
}
|
1108
|
+
usbi_mutex_static_unlock(&active_contexts_lock);
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
#if !defined(USE_UDEV)
|
1112
|
+
/* open a bus directory and adds all discovered devices to the context */
|
1113
|
+
static int usbfs_scan_busdir(struct libusb_context *ctx, uint8_t busnum)
|
1042
1114
|
{
|
1043
1115
|
DIR *dir;
|
1044
1116
|
char dirpath[PATH_MAX];
|
1045
1117
|
struct dirent *entry;
|
1046
|
-
struct discovered_devs *discdevs = *_discdevs;
|
1047
1118
|
int r = LIBUSB_ERROR_IO;
|
1048
1119
|
|
1049
1120
|
snprintf(dirpath, PATH_MAX, "%s/%03d", usbfs_path, busnum);
|
@@ -1068,7 +1139,7 @@ static int usbfs_scan_busdir(struct libusb_context *ctx,
|
|
1068
1139
|
continue;
|
1069
1140
|
}
|
1070
1141
|
|
1071
|
-
if (
|
1142
|
+
if (linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL)) {
|
1072
1143
|
usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
|
1073
1144
|
continue;
|
1074
1145
|
}
|
@@ -1076,18 +1147,14 @@ static int usbfs_scan_busdir(struct libusb_context *ctx,
|
|
1076
1147
|
r = 0;
|
1077
1148
|
}
|
1078
1149
|
|
1079
|
-
if (!r)
|
1080
|
-
*_discdevs = discdevs;
|
1081
1150
|
closedir(dir);
|
1082
1151
|
return r;
|
1083
1152
|
}
|
1084
1153
|
|
1085
|
-
static int usbfs_get_device_list(struct libusb_context *ctx
|
1086
|
-
struct discovered_devs **_discdevs)
|
1154
|
+
static int usbfs_get_device_list(struct libusb_context *ctx)
|
1087
1155
|
{
|
1088
1156
|
struct dirent *entry;
|
1089
1157
|
DIR *buses = opendir(usbfs_path);
|
1090
|
-
struct discovered_devs *discdevs = *_discdevs;
|
1091
1158
|
int r = 0;
|
1092
1159
|
|
1093
1160
|
if (!buses) {
|
@@ -1096,7 +1163,6 @@ static int usbfs_get_device_list(struct libusb_context *ctx,
|
|
1096
1163
|
}
|
1097
1164
|
|
1098
1165
|
while ((entry = readdir(buses))) {
|
1099
|
-
struct discovered_devs *discdevs_new = discdevs;
|
1100
1166
|
int busnum;
|
1101
1167
|
|
1102
1168
|
if (entry->d_name[0] == '.')
|
@@ -1107,8 +1173,7 @@ static int usbfs_get_device_list(struct libusb_context *ctx,
|
|
1107
1173
|
if (!_is_usbdev_entry(entry, &busnum, &devaddr))
|
1108
1174
|
continue;
|
1109
1175
|
|
1110
|
-
r =
|
1111
|
-
(uint8_t) devaddr, NULL);
|
1176
|
+
r = linux_enumerate_device(ctx, busnum, (uint8_t) devaddr, NULL);
|
1112
1177
|
if (r < 0) {
|
1113
1178
|
usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
|
1114
1179
|
continue;
|
@@ -1120,116 +1185,35 @@ static int usbfs_get_device_list(struct libusb_context *ctx,
|
|
1120
1185
|
continue;
|
1121
1186
|
}
|
1122
1187
|
|
1123
|
-
r = usbfs_scan_busdir(ctx,
|
1188
|
+
r = usbfs_scan_busdir(ctx, busnum);
|
1124
1189
|
if (r < 0)
|
1125
|
-
|
1190
|
+
break;
|
1126
1191
|
}
|
1127
|
-
discdevs = discdevs_new;
|
1128
1192
|
}
|
1129
1193
|
|
1130
|
-
out:
|
1131
1194
|
closedir(buses);
|
1132
|
-
*_discdevs = discdevs;
|
1133
1195
|
return r;
|
1134
1196
|
|
1135
1197
|
}
|
1198
|
+
#endif
|
1136
1199
|
|
1137
|
-
static int sysfs_scan_device(struct libusb_context *ctx,
|
1138
|
-
struct discovered_devs **_discdevs, const char *devname)
|
1200
|
+
static int sysfs_scan_device(struct libusb_context *ctx, const char *devname)
|
1139
1201
|
{
|
1140
|
-
|
1141
|
-
int
|
1142
|
-
|
1143
|
-
usbi_dbg("scan %s", devname);
|
1202
|
+
uint8_t busnum, devaddr;
|
1203
|
+
int ret;
|
1144
1204
|
|
1145
|
-
|
1146
|
-
if (
|
1147
|
-
return
|
1148
|
-
|
1149
|
-
devaddr = __read_sysfs_attr(ctx, devname, "devnum");
|
1150
|
-
if (devaddr < 0)
|
1151
|
-
return devaddr;
|
1152
|
-
|
1153
|
-
usbi_dbg("bus=%d dev=%d", busnum, devaddr);
|
1154
|
-
if (busnum > 255 || devaddr > 255)
|
1155
|
-
return LIBUSB_ERROR_INVALID_PARAM;
|
1205
|
+
ret = linux_get_device_address (ctx, 0, &busnum, &devaddr, NULL, devname);
|
1206
|
+
if (LIBUSB_SUCCESS != ret) {
|
1207
|
+
return ret;
|
1208
|
+
}
|
1156
1209
|
|
1157
|
-
return
|
1210
|
+
return linux_enumerate_device(ctx, busnum & 0xff, devaddr & 0xff,
|
1158
1211
|
devname);
|
1159
1212
|
}
|
1160
1213
|
|
1161
|
-
|
1162
|
-
|
1163
|
-
struct linux_device_priv *priv;
|
1164
|
-
int i, j;
|
1165
|
-
struct libusb_device *dev1, *dev2;
|
1166
|
-
const char *sysfs_dir1, *sysfs_dir2;
|
1167
|
-
const char *p;
|
1168
|
-
int n, boundary_char;
|
1169
|
-
|
1170
|
-
/* Fill in the port_number and parent_dev fields for each device */
|
1171
|
-
|
1172
|
-
for (i = 0; i < discdevs->len; ++i) {
|
1173
|
-
dev1 = discdevs->devices[i];
|
1174
|
-
priv = _device_priv(dev1);
|
1175
|
-
if (!priv)
|
1176
|
-
continue;
|
1177
|
-
sysfs_dir1 = priv->sysfs_dir;
|
1178
|
-
|
1179
|
-
/* Root hubs have sysfs_dir names of the form "usbB",
|
1180
|
-
* where B is the bus number. All other devices have
|
1181
|
-
* sysfs_dir names of the form "B-P[.P ...]", where the
|
1182
|
-
* P values are port numbers leading from the root hub
|
1183
|
-
* to the device.
|
1184
|
-
*/
|
1185
|
-
|
1186
|
-
/* Root hubs don't have parents or port numbers */
|
1187
|
-
if (sysfs_dir1[0] == 'u')
|
1188
|
-
continue;
|
1189
|
-
|
1190
|
-
/* The rightmost component is the device's port number */
|
1191
|
-
p = strrchr(sysfs_dir1, '.');
|
1192
|
-
if (!p) {
|
1193
|
-
p = strchr(sysfs_dir1, '-');
|
1194
|
-
if (!p)
|
1195
|
-
continue; /* Should never happen */
|
1196
|
-
}
|
1197
|
-
dev1->port_number = atoi(p + 1);
|
1198
|
-
|
1199
|
-
/* Search for the parent device */
|
1200
|
-
boundary_char = *p;
|
1201
|
-
n = p - sysfs_dir1;
|
1202
|
-
for (j = 0; j < discdevs->len; ++j) {
|
1203
|
-
dev2 = discdevs->devices[j];
|
1204
|
-
priv = _device_priv(dev2);
|
1205
|
-
if (!priv)
|
1206
|
-
continue;
|
1207
|
-
sysfs_dir2 = priv->sysfs_dir;
|
1208
|
-
|
1209
|
-
if (boundary_char == '-') {
|
1210
|
-
/* The parent's name must begin with 'usb';
|
1211
|
-
* skip past that part of sysfs_dir2.
|
1212
|
-
*/
|
1213
|
-
if (sysfs_dir2[0] != 'u')
|
1214
|
-
continue;
|
1215
|
-
sysfs_dir2 += 3;
|
1216
|
-
}
|
1217
|
-
|
1218
|
-
/* The remainder of the parent's name must be equal to
|
1219
|
-
* the first n bytes of sysfs_dir1.
|
1220
|
-
*/
|
1221
|
-
if (memcmp(sysfs_dir1, sysfs_dir2, n) == 0 && !sysfs_dir2[n]) {
|
1222
|
-
dev1->parent_dev = dev2;
|
1223
|
-
break;
|
1224
|
-
}
|
1225
|
-
}
|
1226
|
-
}
|
1227
|
-
}
|
1228
|
-
|
1229
|
-
static int sysfs_get_device_list(struct libusb_context *ctx,
|
1230
|
-
struct discovered_devs **_discdevs)
|
1214
|
+
#if !defined(USE_UDEV)
|
1215
|
+
static int sysfs_get_device_list(struct libusb_context *ctx)
|
1231
1216
|
{
|
1232
|
-
struct discovered_devs *discdevs = *_discdevs;
|
1233
1217
|
DIR *devices = opendir(SYSFS_DEVICE_PATH);
|
1234
1218
|
struct dirent *entry;
|
1235
1219
|
int r = LIBUSB_ERROR_IO;
|
@@ -1240,30 +1224,23 @@ static int sysfs_get_device_list(struct libusb_context *ctx,
|
|
1240
1224
|
}
|
1241
1225
|
|
1242
1226
|
while ((entry = readdir(devices))) {
|
1243
|
-
struct discovered_devs *discdevs_new = discdevs;
|
1244
|
-
|
1245
1227
|
if ((!isdigit(entry->d_name[0]) && strncmp(entry->d_name, "usb", 3))
|
1246
1228
|
|| strchr(entry->d_name, ':'))
|
1247
1229
|
continue;
|
1248
1230
|
|
1249
|
-
if (sysfs_scan_device(ctx,
|
1231
|
+
if (sysfs_scan_device(ctx, entry->d_name)) {
|
1250
1232
|
usbi_dbg("failed to enumerate dir entry %s", entry->d_name);
|
1251
1233
|
continue;
|
1252
1234
|
}
|
1253
1235
|
|
1254
1236
|
r = 0;
|
1255
|
-
discdevs = discdevs_new;
|
1256
1237
|
}
|
1257
1238
|
|
1258
|
-
if (!r)
|
1259
|
-
*_discdevs = discdevs;
|
1260
1239
|
closedir(devices);
|
1261
|
-
sysfs_analyze_topology(discdevs);
|
1262
1240
|
return r;
|
1263
1241
|
}
|
1264
1242
|
|
1265
|
-
static int
|
1266
|
-
struct discovered_devs **_discdevs)
|
1243
|
+
static int linux_default_scan_devices (struct libusb_context *ctx)
|
1267
1244
|
{
|
1268
1245
|
/* we can retrieve device list and descriptors from sysfs or usbfs.
|
1269
1246
|
* sysfs is preferable, because if we use usbfs we end up resuming
|
@@ -1276,45 +1253,39 @@ static int op_get_device_list(struct libusb_context *ctx,
|
|
1276
1253
|
* adequacy of sysfs and sets sysfs_can_relate_devices.
|
1277
1254
|
*/
|
1278
1255
|
if (sysfs_can_relate_devices != 0)
|
1279
|
-
return sysfs_get_device_list(ctx
|
1256
|
+
return sysfs_get_device_list(ctx);
|
1280
1257
|
else
|
1281
|
-
return usbfs_get_device_list(ctx
|
1258
|
+
return usbfs_get_device_list(ctx);
|
1282
1259
|
}
|
1260
|
+
#endif
|
1283
1261
|
|
1284
1262
|
static int op_open(struct libusb_device_handle *handle)
|
1285
1263
|
{
|
1286
1264
|
struct linux_device_handle_priv *hpriv = _device_handle_priv(handle);
|
1287
|
-
char filename[PATH_MAX];
|
1288
1265
|
int r;
|
1289
1266
|
|
1290
|
-
|
1291
|
-
usbi_dbg("opening %s", filename);
|
1292
|
-
hpriv->fd = open(filename, O_RDWR);
|
1267
|
+
hpriv->fd = _get_usbfs_fd(handle->dev, O_RDWR, 0);
|
1293
1268
|
if (hpriv->fd < 0) {
|
1294
|
-
if (
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
|
1303
|
-
|
1304
|
-
} else {
|
1305
|
-
usbi_err(HANDLE_CTX(handle),
|
1306
|
-
"open failed, code %d errno %d", hpriv->fd, errno);
|
1307
|
-
return LIBUSB_ERROR_IO;
|
1269
|
+
if (hpriv->fd == LIBUSB_ERROR_NO_DEVICE) {
|
1270
|
+
/* device will still be marked as attached if hotplug monitor thread
|
1271
|
+
* hasn't processed remove event yet */
|
1272
|
+
usbi_mutex_static_lock(&linux_hotplug_lock);
|
1273
|
+
if (handle->dev->attached) {
|
1274
|
+
usbi_dbg("open failed with no device, but device still attached");
|
1275
|
+
linux_device_disconnected(handle->dev->bus_number,
|
1276
|
+
handle->dev->device_address, NULL);
|
1277
|
+
}
|
1278
|
+
usbi_mutex_static_unlock(&linux_hotplug_lock);
|
1308
1279
|
}
|
1280
|
+
return hpriv->fd;
|
1309
1281
|
}
|
1310
1282
|
|
1311
1283
|
r = ioctl(hpriv->fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
|
1312
1284
|
if (r < 0) {
|
1313
1285
|
if (errno == ENOTTY)
|
1314
|
-
usbi_dbg("
|
1286
|
+
usbi_dbg("getcap not available");
|
1315
1287
|
else
|
1316
|
-
usbi_err(HANDLE_CTX(handle),
|
1317
|
-
"%s: getcap failed (%d)", filename, errno);
|
1288
|
+
usbi_err(HANDLE_CTX(handle), "getcap failed (%d)", errno);
|
1318
1289
|
hpriv->caps = 0;
|
1319
1290
|
if (supports_flag_zero_packet)
|
1320
1291
|
hpriv->caps |= USBFS_CAP_ZERO_PACKET;
|
@@ -1336,10 +1307,13 @@ static int op_get_configuration(struct libusb_device_handle *handle,
|
|
1336
1307
|
int *config)
|
1337
1308
|
{
|
1338
1309
|
int r;
|
1339
|
-
if (sysfs_can_relate_devices != 1)
|
1340
|
-
return LIBUSB_ERROR_NOT_SUPPORTED;
|
1341
1310
|
|
1342
|
-
|
1311
|
+
if (sysfs_can_relate_devices) {
|
1312
|
+
r = sysfs_get_active_config(handle->dev, config);
|
1313
|
+
} else {
|
1314
|
+
r = usbfs_get_active_config(handle->dev,
|
1315
|
+
_device_handle_priv(handle)->fd);
|
1316
|
+
}
|
1343
1317
|
if (r < 0)
|
1344
1318
|
return r;
|
1345
1319
|
|
@@ -1368,25 +1342,13 @@ static int op_set_configuration(struct libusb_device_handle *handle, int config)
|
|
1368
1342
|
return LIBUSB_ERROR_OTHER;
|
1369
1343
|
}
|
1370
1344
|
|
1371
|
-
|
1372
|
-
|
1373
|
-
if (config == -1) {
|
1374
|
-
if (priv->config_descriptor) {
|
1375
|
-
free(priv->config_descriptor);
|
1376
|
-
priv->config_descriptor = NULL;
|
1377
|
-
}
|
1378
|
-
} else {
|
1379
|
-
r = cache_active_config(handle->dev, fd, config);
|
1380
|
-
if (r < 0)
|
1381
|
-
usbi_warn(HANDLE_CTX(handle),
|
1382
|
-
"failed to update cached config descriptor, error %d", r);
|
1383
|
-
}
|
1384
|
-
}
|
1345
|
+
/* update our cached active config descriptor */
|
1346
|
+
priv->active_config = config;
|
1385
1347
|
|
1386
|
-
return
|
1348
|
+
return LIBUSB_SUCCESS;
|
1387
1349
|
}
|
1388
1350
|
|
1389
|
-
static int
|
1351
|
+
static int claim_interface(struct libusb_device_handle *handle, int iface)
|
1390
1352
|
{
|
1391
1353
|
int fd = _device_handle_priv(handle)->fd;
|
1392
1354
|
int r = ioctl(fd, IOCTL_USBFS_CLAIMINTF, &iface);
|
@@ -1405,7 +1367,7 @@ static int op_claim_interface(struct libusb_device_handle *handle, int iface)
|
|
1405
1367
|
return 0;
|
1406
1368
|
}
|
1407
1369
|
|
1408
|
-
static int
|
1370
|
+
static int release_interface(struct libusb_device_handle *handle, int iface)
|
1409
1371
|
{
|
1410
1372
|
int fd = _device_handle_priv(handle)->fd;
|
1411
1373
|
int r = ioctl(fd, IOCTL_USBFS_RELEASEINTF, &iface);
|
@@ -1476,7 +1438,7 @@ static int op_reset_device(struct libusb_device_handle *handle)
|
|
1476
1438
|
getting bound to the in kernel driver if any). */
|
1477
1439
|
for (i = 0; i < USB_MAXINTERFACES; i++) {
|
1478
1440
|
if (handle->claimed_interfaces & (1L << i)) {
|
1479
|
-
|
1441
|
+
release_interface(handle, i);
|
1480
1442
|
}
|
1481
1443
|
}
|
1482
1444
|
|
@@ -1497,11 +1459,18 @@ static int op_reset_device(struct libusb_device_handle *handle)
|
|
1497
1459
|
/* And re-claim any interfaces which were claimed before the reset */
|
1498
1460
|
for (i = 0; i < USB_MAXINTERFACES; i++) {
|
1499
1461
|
if (handle->claimed_interfaces & (1L << i)) {
|
1500
|
-
|
1462
|
+
/*
|
1463
|
+
* A driver may have completed modprobing during
|
1464
|
+
* IOCTL_USBFS_RESET, and bound itself as soon as
|
1465
|
+
* IOCTL_USBFS_RESET released the device lock
|
1466
|
+
*/
|
1467
|
+
r = detach_kernel_driver_and_claim(handle, i);
|
1501
1468
|
if (r) {
|
1502
1469
|
usbi_warn(HANDLE_CTX(handle),
|
1503
|
-
"failed to re-claim interface %d after reset",
|
1470
|
+
"failed to re-claim interface %d after reset: %s",
|
1471
|
+
i, libusb_error_name(r));
|
1504
1472
|
handle->claimed_interfaces &= ~(1L << i);
|
1473
|
+
ret = LIBUSB_ERROR_NOT_FOUND;
|
1505
1474
|
}
|
1506
1475
|
}
|
1507
1476
|
}
|
@@ -1530,7 +1499,7 @@ static int op_kernel_driver_active(struct libusb_device_handle *handle,
|
|
1530
1499
|
return LIBUSB_ERROR_OTHER;
|
1531
1500
|
}
|
1532
1501
|
|
1533
|
-
return 1;
|
1502
|
+
return (strcmp(getdrv.driver, "usbfs") == 0) ? 0 : 1;
|
1534
1503
|
}
|
1535
1504
|
|
1536
1505
|
static int op_detach_kernel_driver(struct libusb_device_handle *handle,
|
@@ -1599,15 +1568,69 @@ static int op_attach_kernel_driver(struct libusb_device_handle *handle,
|
|
1599
1568
|
return 0;
|
1600
1569
|
}
|
1601
1570
|
|
1571
|
+
static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle,
|
1572
|
+
int interface)
|
1573
|
+
{
|
1574
|
+
struct usbfs_disconnect_claim dc;
|
1575
|
+
int r, fd = _device_handle_priv(handle)->fd;
|
1576
|
+
|
1577
|
+
dc.interface = interface;
|
1578
|
+
strcpy(dc.driver, "usbfs");
|
1579
|
+
dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER;
|
1580
|
+
r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc);
|
1581
|
+
if (r == 0 || (r != 0 && errno != ENOTTY)) {
|
1582
|
+
if (r == 0)
|
1583
|
+
return 0;
|
1584
|
+
|
1585
|
+
switch (errno) {
|
1586
|
+
case EBUSY:
|
1587
|
+
return LIBUSB_ERROR_BUSY;
|
1588
|
+
case EINVAL:
|
1589
|
+
return LIBUSB_ERROR_INVALID_PARAM;
|
1590
|
+
case ENODEV:
|
1591
|
+
return LIBUSB_ERROR_NO_DEVICE;
|
1592
|
+
}
|
1593
|
+
usbi_err(HANDLE_CTX(handle),
|
1594
|
+
"disconnect-and-claim failed errno %d", errno);
|
1595
|
+
return LIBUSB_ERROR_OTHER;
|
1596
|
+
}
|
1597
|
+
|
1598
|
+
/* Fallback code for kernels which don't support the
|
1599
|
+
disconnect-and-claim ioctl */
|
1600
|
+
r = op_detach_kernel_driver(handle, interface);
|
1601
|
+
if (r != 0 && r != LIBUSB_ERROR_NOT_FOUND)
|
1602
|
+
return r;
|
1603
|
+
|
1604
|
+
return claim_interface(handle, interface);
|
1605
|
+
}
|
1606
|
+
|
1607
|
+
static int op_claim_interface(struct libusb_device_handle *handle, int iface)
|
1608
|
+
{
|
1609
|
+
if (handle->auto_detach_kernel_driver)
|
1610
|
+
return detach_kernel_driver_and_claim(handle, iface);
|
1611
|
+
else
|
1612
|
+
return claim_interface(handle, iface);
|
1613
|
+
}
|
1614
|
+
|
1615
|
+
static int op_release_interface(struct libusb_device_handle *handle, int iface)
|
1616
|
+
{
|
1617
|
+
int r;
|
1618
|
+
|
1619
|
+
r = release_interface(handle, iface);
|
1620
|
+
if (r)
|
1621
|
+
return r;
|
1622
|
+
|
1623
|
+
if (handle->auto_detach_kernel_driver)
|
1624
|
+
op_attach_kernel_driver(handle, iface);
|
1625
|
+
|
1626
|
+
return 0;
|
1627
|
+
}
|
1628
|
+
|
1602
1629
|
static void op_destroy_device(struct libusb_device *dev)
|
1603
1630
|
{
|
1604
1631
|
struct linux_device_priv *priv = _device_priv(dev);
|
1605
|
-
if (
|
1606
|
-
|
1607
|
-
free(priv->dev_descriptor);
|
1608
|
-
if (priv->config_descriptor)
|
1609
|
-
free(priv->config_descriptor);
|
1610
|
-
}
|
1632
|
+
if (priv->descriptors)
|
1633
|
+
free(priv->descriptors);
|
1611
1634
|
if (priv->sysfs_dir)
|
1612
1635
|
free(priv->sysfs_dir);
|
1613
1636
|
}
|
@@ -1755,7 +1778,8 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer,
|
|
1755
1778
|
urb->type = urb_type;
|
1756
1779
|
urb->endpoint = transfer->endpoint;
|
1757
1780
|
urb->buffer = transfer->buffer + (i * bulk_buffer_len);
|
1758
|
-
|
1781
|
+
/* don't set the short not ok flag for the last URB */
|
1782
|
+
if (use_bulk_continuation && !is_out && (i < num_urbs - 1))
|
1759
1783
|
urb->flags = USBFS_URB_SHORT_NOT_OK;
|
1760
1784
|
if (i == num_urbs - 1 && last_urb_partial)
|
1761
1785
|
urb->buffer_length = transfer->length % bulk_buffer_len;
|
@@ -2488,10 +2512,19 @@ static int op_handle_events(struct libusb_context *ctx,
|
|
2488
2512
|
if (pollfd->revents & POLLERR) {
|
2489
2513
|
usbi_remove_pollfd(HANDLE_CTX(handle), hpriv->fd);
|
2490
2514
|
usbi_handle_disconnect(handle);
|
2515
|
+
/* device will still be marked as attached if hotplug monitor thread
|
2516
|
+
* hasn't processed remove event yet */
|
2517
|
+
usbi_mutex_static_lock(&linux_hotplug_lock);
|
2518
|
+
if (handle->dev->attached)
|
2519
|
+
linux_device_disconnected(handle->dev->bus_number,
|
2520
|
+
handle->dev->device_address, NULL);
|
2521
|
+
usbi_mutex_static_unlock(&linux_hotplug_lock);
|
2491
2522
|
continue;
|
2492
2523
|
}
|
2493
2524
|
|
2494
|
-
|
2525
|
+
do {
|
2526
|
+
r = reap_for_handle(handle);
|
2527
|
+
} while (r == 0);
|
2495
2528
|
if (r == 1 || r == LIBUSB_ERROR_NO_DEVICE)
|
2496
2529
|
continue;
|
2497
2530
|
else if (r < 0)
|
@@ -2526,12 +2559,15 @@ static clockid_t op_get_timerfd_clockid(void)
|
|
2526
2559
|
|
2527
2560
|
const struct usbi_os_backend linux_usbfs_backend = {
|
2528
2561
|
.name = "Linux usbfs",
|
2562
|
+
.caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
|
2529
2563
|
.init = op_init,
|
2530
|
-
.exit =
|
2531
|
-
.get_device_list =
|
2564
|
+
.exit = op_exit,
|
2565
|
+
.get_device_list = NULL,
|
2566
|
+
.hotplug_poll = op_hotplug_poll,
|
2532
2567
|
.get_device_descriptor = op_get_device_descriptor,
|
2533
2568
|
.get_active_config_descriptor = op_get_active_config_descriptor,
|
2534
2569
|
.get_config_descriptor = op_get_config_descriptor,
|
2570
|
+
.get_config_descriptor_by_value = op_get_config_descriptor_by_value,
|
2535
2571
|
|
2536
2572
|
.open = op_open,
|
2537
2573
|
.close = op_close,
|