1*86b64dcbSAndroid Build Coastguard Worker /* -*- Mode: C; c-basic-offset:8 ; indent-tabs-mode:t -*- */
2*86b64dcbSAndroid Build Coastguard Worker /*
3*86b64dcbSAndroid Build Coastguard Worker * Linux usbfs backend for libusb
4*86b64dcbSAndroid Build Coastguard Worker * Copyright © 2007-2009 Daniel Drake <[email protected]>
5*86b64dcbSAndroid Build Coastguard Worker * Copyright © 2001 Johannes Erdfelt <[email protected]>
6*86b64dcbSAndroid Build Coastguard Worker * Copyright © 2013 Nathan Hjelm <[email protected]>
7*86b64dcbSAndroid Build Coastguard Worker * Copyright © 2012-2013 Hans de Goede <[email protected]>
8*86b64dcbSAndroid Build Coastguard Worker * Copyright © 2020 Chris Dickens <[email protected]>
9*86b64dcbSAndroid Build Coastguard Worker *
10*86b64dcbSAndroid Build Coastguard Worker * This library is free software; you can redistribute it and/or
11*86b64dcbSAndroid Build Coastguard Worker * modify it under the terms of the GNU Lesser General Public
12*86b64dcbSAndroid Build Coastguard Worker * License as published by the Free Software Foundation; either
13*86b64dcbSAndroid Build Coastguard Worker * version 2.1 of the License, or (at your option) any later version.
14*86b64dcbSAndroid Build Coastguard Worker *
15*86b64dcbSAndroid Build Coastguard Worker * This library is distributed in the hope that it will be useful,
16*86b64dcbSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*86b64dcbSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18*86b64dcbSAndroid Build Coastguard Worker * Lesser General Public License for more details.
19*86b64dcbSAndroid Build Coastguard Worker *
20*86b64dcbSAndroid Build Coastguard Worker * You should have received a copy of the GNU Lesser General Public
21*86b64dcbSAndroid Build Coastguard Worker * License along with this library; if not, write to the Free Software
22*86b64dcbSAndroid Build Coastguard Worker * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23*86b64dcbSAndroid Build Coastguard Worker */
24*86b64dcbSAndroid Build Coastguard Worker
25*86b64dcbSAndroid Build Coastguard Worker #include "libusbi.h"
26*86b64dcbSAndroid Build Coastguard Worker #include "linux_usbfs.h"
27*86b64dcbSAndroid Build Coastguard Worker
28*86b64dcbSAndroid Build Coastguard Worker #include <alloca.h>
29*86b64dcbSAndroid Build Coastguard Worker #include <ctype.h>
30*86b64dcbSAndroid Build Coastguard Worker #include <dirent.h>
31*86b64dcbSAndroid Build Coastguard Worker #include <errno.h>
32*86b64dcbSAndroid Build Coastguard Worker #include <fcntl.h>
33*86b64dcbSAndroid Build Coastguard Worker #include <stdio.h>
34*86b64dcbSAndroid Build Coastguard Worker #include <string.h>
35*86b64dcbSAndroid Build Coastguard Worker #include <sys/ioctl.h>
36*86b64dcbSAndroid Build Coastguard Worker #include <sys/mman.h>
37*86b64dcbSAndroid Build Coastguard Worker #include <sys/utsname.h>
38*86b64dcbSAndroid Build Coastguard Worker #include <sys/vfs.h>
39*86b64dcbSAndroid Build Coastguard Worker #include <unistd.h>
40*86b64dcbSAndroid Build Coastguard Worker
41*86b64dcbSAndroid Build Coastguard Worker /* sysfs vs usbfs:
42*86b64dcbSAndroid Build Coastguard Worker * opening a usbfs node causes the device to be resumed, so we attempt to
43*86b64dcbSAndroid Build Coastguard Worker * avoid this during enumeration.
44*86b64dcbSAndroid Build Coastguard Worker *
45*86b64dcbSAndroid Build Coastguard Worker * sysfs allows us to read the kernel's in-memory copies of device descriptors
46*86b64dcbSAndroid Build Coastguard Worker * and so forth, avoiding the need to open the device:
47*86b64dcbSAndroid Build Coastguard Worker * - The binary "descriptors" file contains all config descriptors since
48*86b64dcbSAndroid Build Coastguard Worker * 2.6.26, commit 217a9081d8e69026186067711131b77f0ce219ed
49*86b64dcbSAndroid Build Coastguard Worker * - The binary "descriptors" file was added in 2.6.23, commit
50*86b64dcbSAndroid Build Coastguard Worker * 69d42a78f935d19384d1f6e4f94b65bb162b36df, but it only contains the
51*86b64dcbSAndroid Build Coastguard Worker * active config descriptors
52*86b64dcbSAndroid Build Coastguard Worker * - The "busnum" file was added in 2.6.22, commit
53*86b64dcbSAndroid Build Coastguard Worker * 83f7d958eab2fbc6b159ee92bf1493924e1d0f72
54*86b64dcbSAndroid Build Coastguard Worker * - The "devnum" file has been present since pre-2.6.18
55*86b64dcbSAndroid Build Coastguard Worker * - the "bConfigurationValue" file has been present since pre-2.6.18
56*86b64dcbSAndroid Build Coastguard Worker *
57*86b64dcbSAndroid Build Coastguard Worker * If we have bConfigurationValue, busnum, and devnum, then we can determine
58*86b64dcbSAndroid Build Coastguard Worker * the active configuration without having to open the usbfs node in RDWR mode.
59*86b64dcbSAndroid Build Coastguard Worker * The busnum file is important as that is the only way we can relate sysfs
60*86b64dcbSAndroid Build Coastguard Worker * devices to usbfs nodes.
61*86b64dcbSAndroid Build Coastguard Worker *
62*86b64dcbSAndroid Build Coastguard Worker * If we also have all descriptors, we can obtain the device descriptor and
63*86b64dcbSAndroid Build Coastguard Worker * configuration without touching usbfs at all.
64*86b64dcbSAndroid Build Coastguard Worker */
65*86b64dcbSAndroid Build Coastguard Worker
66*86b64dcbSAndroid Build Coastguard Worker /* endianness for multi-byte fields:
67*86b64dcbSAndroid Build Coastguard Worker *
68*86b64dcbSAndroid Build Coastguard Worker * Descriptors exposed by usbfs have the multi-byte fields in the device
69*86b64dcbSAndroid Build Coastguard Worker * descriptor as host endian. Multi-byte fields in the other descriptors are
70*86b64dcbSAndroid Build Coastguard Worker * bus-endian. The kernel documentation says otherwise, but it is wrong.
71*86b64dcbSAndroid Build Coastguard Worker *
72*86b64dcbSAndroid Build Coastguard Worker * In sysfs all descriptors are bus-endian.
73*86b64dcbSAndroid Build Coastguard Worker */
74*86b64dcbSAndroid Build Coastguard Worker
75*86b64dcbSAndroid Build Coastguard Worker #define USBDEV_PATH "/dev"
76*86b64dcbSAndroid Build Coastguard Worker #define USB_DEVTMPFS_PATH "/dev/bus/usb"
77*86b64dcbSAndroid Build Coastguard Worker
78*86b64dcbSAndroid Build Coastguard Worker /* use usbdev*.* device names in /dev instead of the usbfs bus directories */
79*86b64dcbSAndroid Build Coastguard Worker static int usbdev_names = 0;
80*86b64dcbSAndroid Build Coastguard Worker
81*86b64dcbSAndroid Build Coastguard Worker /* Linux has changed the maximum length of an individual isochronous packet
82*86b64dcbSAndroid Build Coastguard Worker * over time. Initially this limit was 1,023 bytes, but Linux 2.6.18
83*86b64dcbSAndroid Build Coastguard Worker * (commit 3612242e527eb47ee4756b5350f8bdf791aa5ede) increased this value to
84*86b64dcbSAndroid Build Coastguard Worker * 8,192 bytes to support higher bandwidth devices. Linux 3.10
85*86b64dcbSAndroid Build Coastguard Worker * (commit e2e2f0ea1c935edcf53feb4c4c8fdb4f86d57dd9) further increased this
86*86b64dcbSAndroid Build Coastguard Worker * value to 49,152 bytes to support super speed devices. Linux 5.2
87*86b64dcbSAndroid Build Coastguard Worker * (commit 8a1dbc8d91d3d1602282c7e6b4222c7759c916fa) even further increased
88*86b64dcbSAndroid Build Coastguard Worker * this value to 98,304 bytes to support super speed plus devices.
89*86b64dcbSAndroid Build Coastguard Worker */
90*86b64dcbSAndroid Build Coastguard Worker static unsigned int max_iso_packet_len = 0;
91*86b64dcbSAndroid Build Coastguard Worker
92*86b64dcbSAndroid Build Coastguard Worker /* is sysfs available (mounted) ? */
93*86b64dcbSAndroid Build Coastguard Worker static int sysfs_available = -1;
94*86b64dcbSAndroid Build Coastguard Worker
95*86b64dcbSAndroid Build Coastguard Worker /* how many times have we initted (and not exited) ? */
96*86b64dcbSAndroid Build Coastguard Worker static int init_count = 0;
97*86b64dcbSAndroid Build Coastguard Worker
98*86b64dcbSAndroid Build Coastguard Worker /* Serialize scan-devices, event-thread, and poll */
99*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_static_t linux_hotplug_lock = USBI_MUTEX_INITIALIZER;
100*86b64dcbSAndroid Build Coastguard Worker
101*86b64dcbSAndroid Build Coastguard Worker static int linux_scan_devices(struct libusb_context *ctx);
102*86b64dcbSAndroid Build Coastguard Worker static int detach_kernel_driver_and_claim(struct libusb_device_handle *, uint8_t);
103*86b64dcbSAndroid Build Coastguard Worker
104*86b64dcbSAndroid Build Coastguard Worker #if !defined(HAVE_LIBUDEV)
105*86b64dcbSAndroid Build Coastguard Worker static int linux_default_scan_devices(struct libusb_context *ctx);
106*86b64dcbSAndroid Build Coastguard Worker #endif
107*86b64dcbSAndroid Build Coastguard Worker
108*86b64dcbSAndroid Build Coastguard Worker struct kernel_version {
109*86b64dcbSAndroid Build Coastguard Worker int major;
110*86b64dcbSAndroid Build Coastguard Worker int minor;
111*86b64dcbSAndroid Build Coastguard Worker int sublevel;
112*86b64dcbSAndroid Build Coastguard Worker };
113*86b64dcbSAndroid Build Coastguard Worker
114*86b64dcbSAndroid Build Coastguard Worker struct config_descriptor {
115*86b64dcbSAndroid Build Coastguard Worker struct usbi_configuration_descriptor *desc;
116*86b64dcbSAndroid Build Coastguard Worker size_t actual_len;
117*86b64dcbSAndroid Build Coastguard Worker };
118*86b64dcbSAndroid Build Coastguard Worker
119*86b64dcbSAndroid Build Coastguard Worker struct linux_context_priv {
120*86b64dcbSAndroid Build Coastguard Worker /* no enumeration or hot-plug detection */
121*86b64dcbSAndroid Build Coastguard Worker int no_device_discovery;
122*86b64dcbSAndroid Build Coastguard Worker };
123*86b64dcbSAndroid Build Coastguard Worker
124*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv {
125*86b64dcbSAndroid Build Coastguard Worker char *sysfs_dir;
126*86b64dcbSAndroid Build Coastguard Worker void *descriptors;
127*86b64dcbSAndroid Build Coastguard Worker size_t descriptors_len;
128*86b64dcbSAndroid Build Coastguard Worker struct config_descriptor *config_descriptors;
129*86b64dcbSAndroid Build Coastguard Worker int active_config; /* cache val for !sysfs_available */
130*86b64dcbSAndroid Build Coastguard Worker };
131*86b64dcbSAndroid Build Coastguard Worker
132*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv {
133*86b64dcbSAndroid Build Coastguard Worker int fd;
134*86b64dcbSAndroid Build Coastguard Worker int fd_removed;
135*86b64dcbSAndroid Build Coastguard Worker int fd_keep;
136*86b64dcbSAndroid Build Coastguard Worker uint32_t caps;
137*86b64dcbSAndroid Build Coastguard Worker };
138*86b64dcbSAndroid Build Coastguard Worker
139*86b64dcbSAndroid Build Coastguard Worker enum reap_action {
140*86b64dcbSAndroid Build Coastguard Worker NORMAL = 0,
141*86b64dcbSAndroid Build Coastguard Worker /* submission failed after the first URB, so await cancellation/completion
142*86b64dcbSAndroid Build Coastguard Worker * of all the others */
143*86b64dcbSAndroid Build Coastguard Worker SUBMIT_FAILED,
144*86b64dcbSAndroid Build Coastguard Worker
145*86b64dcbSAndroid Build Coastguard Worker /* cancelled by user or timeout */
146*86b64dcbSAndroid Build Coastguard Worker CANCELLED,
147*86b64dcbSAndroid Build Coastguard Worker
148*86b64dcbSAndroid Build Coastguard Worker /* completed multi-URB transfer in non-final URB */
149*86b64dcbSAndroid Build Coastguard Worker COMPLETED_EARLY,
150*86b64dcbSAndroid Build Coastguard Worker
151*86b64dcbSAndroid Build Coastguard Worker /* one or more urbs encountered a low-level error */
152*86b64dcbSAndroid Build Coastguard Worker ERROR,
153*86b64dcbSAndroid Build Coastguard Worker };
154*86b64dcbSAndroid Build Coastguard Worker
155*86b64dcbSAndroid Build Coastguard Worker struct linux_transfer_priv {
156*86b64dcbSAndroid Build Coastguard Worker union {
157*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb *urbs;
158*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb **iso_urbs;
159*86b64dcbSAndroid Build Coastguard Worker };
160*86b64dcbSAndroid Build Coastguard Worker
161*86b64dcbSAndroid Build Coastguard Worker enum reap_action reap_action;
162*86b64dcbSAndroid Build Coastguard Worker int num_urbs;
163*86b64dcbSAndroid Build Coastguard Worker int num_retired;
164*86b64dcbSAndroid Build Coastguard Worker enum libusb_transfer_status reap_status;
165*86b64dcbSAndroid Build Coastguard Worker
166*86b64dcbSAndroid Build Coastguard Worker /* next iso packet in user-supplied transfer to be populated */
167*86b64dcbSAndroid Build Coastguard Worker int iso_packet_offset;
168*86b64dcbSAndroid Build Coastguard Worker };
169*86b64dcbSAndroid Build Coastguard Worker
dev_has_config0(struct libusb_device * dev)170*86b64dcbSAndroid Build Coastguard Worker static int dev_has_config0(struct libusb_device *dev)
171*86b64dcbSAndroid Build Coastguard Worker {
172*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv *priv = usbi_get_device_priv(dev);
173*86b64dcbSAndroid Build Coastguard Worker struct config_descriptor *config;
174*86b64dcbSAndroid Build Coastguard Worker uint8_t idx;
175*86b64dcbSAndroid Build Coastguard Worker
176*86b64dcbSAndroid Build Coastguard Worker for (idx = 0; idx < dev->device_descriptor.bNumConfigurations; idx++) {
177*86b64dcbSAndroid Build Coastguard Worker config = &priv->config_descriptors[idx];
178*86b64dcbSAndroid Build Coastguard Worker if (config->desc->bConfigurationValue == 0)
179*86b64dcbSAndroid Build Coastguard Worker return 1;
180*86b64dcbSAndroid Build Coastguard Worker }
181*86b64dcbSAndroid Build Coastguard Worker
182*86b64dcbSAndroid Build Coastguard Worker return 0;
183*86b64dcbSAndroid Build Coastguard Worker }
184*86b64dcbSAndroid Build Coastguard Worker
get_usbfs_fd(struct libusb_device * dev,int access_mode,int silent)185*86b64dcbSAndroid Build Coastguard Worker static int get_usbfs_fd(struct libusb_device *dev, int access_mode, int silent)
186*86b64dcbSAndroid Build Coastguard Worker {
187*86b64dcbSAndroid Build Coastguard Worker struct libusb_context *ctx = DEVICE_CTX(dev);
188*86b64dcbSAndroid Build Coastguard Worker char path[24];
189*86b64dcbSAndroid Build Coastguard Worker int fd;
190*86b64dcbSAndroid Build Coastguard Worker
191*86b64dcbSAndroid Build Coastguard Worker if (usbdev_names)
192*86b64dcbSAndroid Build Coastguard Worker snprintf(path, sizeof(path), USBDEV_PATH "/usbdev%u.%u",
193*86b64dcbSAndroid Build Coastguard Worker dev->bus_number, dev->device_address);
194*86b64dcbSAndroid Build Coastguard Worker else
195*86b64dcbSAndroid Build Coastguard Worker snprintf(path, sizeof(path), USB_DEVTMPFS_PATH "/%03u/%03u",
196*86b64dcbSAndroid Build Coastguard Worker dev->bus_number, dev->device_address);
197*86b64dcbSAndroid Build Coastguard Worker
198*86b64dcbSAndroid Build Coastguard Worker fd = open(path, access_mode | O_CLOEXEC);
199*86b64dcbSAndroid Build Coastguard Worker if (fd != -1)
200*86b64dcbSAndroid Build Coastguard Worker return fd; /* Success */
201*86b64dcbSAndroid Build Coastguard Worker
202*86b64dcbSAndroid Build Coastguard Worker if (errno == ENOENT) {
203*86b64dcbSAndroid Build Coastguard Worker const long delay_ms = 10L;
204*86b64dcbSAndroid Build Coastguard Worker const struct timespec delay_ts = { 0L, delay_ms * 1000L * 1000L };
205*86b64dcbSAndroid Build Coastguard Worker
206*86b64dcbSAndroid Build Coastguard Worker if (!silent)
207*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "File doesn't exist, wait %ld ms and try again", delay_ms);
208*86b64dcbSAndroid Build Coastguard Worker
209*86b64dcbSAndroid Build Coastguard Worker /* Wait 10ms for USB device path creation.*/
210*86b64dcbSAndroid Build Coastguard Worker nanosleep(&delay_ts, NULL);
211*86b64dcbSAndroid Build Coastguard Worker
212*86b64dcbSAndroid Build Coastguard Worker fd = open(path, access_mode | O_CLOEXEC);
213*86b64dcbSAndroid Build Coastguard Worker if (fd != -1)
214*86b64dcbSAndroid Build Coastguard Worker return fd; /* Success */
215*86b64dcbSAndroid Build Coastguard Worker }
216*86b64dcbSAndroid Build Coastguard Worker
217*86b64dcbSAndroid Build Coastguard Worker if (!silent) {
218*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "libusb couldn't open USB device %s, errno=%d", path, errno);
219*86b64dcbSAndroid Build Coastguard Worker if (errno == EACCES && access_mode == O_RDWR)
220*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "libusb requires write access to USB device nodes");
221*86b64dcbSAndroid Build Coastguard Worker }
222*86b64dcbSAndroid Build Coastguard Worker
223*86b64dcbSAndroid Build Coastguard Worker if (errno == EACCES)
224*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_ACCESS;
225*86b64dcbSAndroid Build Coastguard Worker if (errno == ENOENT)
226*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
227*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
228*86b64dcbSAndroid Build Coastguard Worker }
229*86b64dcbSAndroid Build Coastguard Worker
230*86b64dcbSAndroid Build Coastguard Worker /* check dirent for a /dev/usbdev%d.%d name
231*86b64dcbSAndroid Build Coastguard Worker * optionally return bus/device on success */
is_usbdev_entry(const char * name,uint8_t * bus_p,uint8_t * dev_p)232*86b64dcbSAndroid Build Coastguard Worker static int is_usbdev_entry(const char *name, uint8_t *bus_p, uint8_t *dev_p)
233*86b64dcbSAndroid Build Coastguard Worker {
234*86b64dcbSAndroid Build Coastguard Worker int busnum, devnum;
235*86b64dcbSAndroid Build Coastguard Worker
236*86b64dcbSAndroid Build Coastguard Worker if (sscanf(name, "usbdev%d.%d", &busnum, &devnum) != 2)
237*86b64dcbSAndroid Build Coastguard Worker return 0;
238*86b64dcbSAndroid Build Coastguard Worker if (busnum < 0 || busnum > UINT8_MAX || devnum < 0 || devnum > UINT8_MAX) {
239*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(NULL, "invalid usbdev format '%s'", name);
240*86b64dcbSAndroid Build Coastguard Worker return 0;
241*86b64dcbSAndroid Build Coastguard Worker }
242*86b64dcbSAndroid Build Coastguard Worker
243*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(NULL, "found: %s", name);
244*86b64dcbSAndroid Build Coastguard Worker if (bus_p)
245*86b64dcbSAndroid Build Coastguard Worker *bus_p = (uint8_t)busnum;
246*86b64dcbSAndroid Build Coastguard Worker if (dev_p)
247*86b64dcbSAndroid Build Coastguard Worker *dev_p = (uint8_t)devnum;
248*86b64dcbSAndroid Build Coastguard Worker return 1;
249*86b64dcbSAndroid Build Coastguard Worker }
250*86b64dcbSAndroid Build Coastguard Worker
find_usbfs_path(void)251*86b64dcbSAndroid Build Coastguard Worker static const char *find_usbfs_path(void)
252*86b64dcbSAndroid Build Coastguard Worker {
253*86b64dcbSAndroid Build Coastguard Worker const char *path;
254*86b64dcbSAndroid Build Coastguard Worker DIR *dir;
255*86b64dcbSAndroid Build Coastguard Worker struct dirent *entry;
256*86b64dcbSAndroid Build Coastguard Worker
257*86b64dcbSAndroid Build Coastguard Worker path = USB_DEVTMPFS_PATH;
258*86b64dcbSAndroid Build Coastguard Worker dir = opendir(path);
259*86b64dcbSAndroid Build Coastguard Worker if (dir) {
260*86b64dcbSAndroid Build Coastguard Worker while ((entry = readdir(dir))) {
261*86b64dcbSAndroid Build Coastguard Worker if (entry->d_name[0] == '.')
262*86b64dcbSAndroid Build Coastguard Worker continue;
263*86b64dcbSAndroid Build Coastguard Worker
264*86b64dcbSAndroid Build Coastguard Worker /* We assume if we find any files that it must be the right place */
265*86b64dcbSAndroid Build Coastguard Worker break;
266*86b64dcbSAndroid Build Coastguard Worker }
267*86b64dcbSAndroid Build Coastguard Worker
268*86b64dcbSAndroid Build Coastguard Worker closedir(dir);
269*86b64dcbSAndroid Build Coastguard Worker
270*86b64dcbSAndroid Build Coastguard Worker if (entry)
271*86b64dcbSAndroid Build Coastguard Worker return path;
272*86b64dcbSAndroid Build Coastguard Worker }
273*86b64dcbSAndroid Build Coastguard Worker
274*86b64dcbSAndroid Build Coastguard Worker /* look for /dev/usbdev*.* if the normal place fails */
275*86b64dcbSAndroid Build Coastguard Worker path = USBDEV_PATH;
276*86b64dcbSAndroid Build Coastguard Worker dir = opendir(path);
277*86b64dcbSAndroid Build Coastguard Worker if (dir) {
278*86b64dcbSAndroid Build Coastguard Worker while ((entry = readdir(dir))) {
279*86b64dcbSAndroid Build Coastguard Worker if (entry->d_name[0] == '.')
280*86b64dcbSAndroid Build Coastguard Worker continue;
281*86b64dcbSAndroid Build Coastguard Worker
282*86b64dcbSAndroid Build Coastguard Worker if (is_usbdev_entry(entry->d_name, NULL, NULL)) {
283*86b64dcbSAndroid Build Coastguard Worker /* found one; that's enough */
284*86b64dcbSAndroid Build Coastguard Worker break;
285*86b64dcbSAndroid Build Coastguard Worker }
286*86b64dcbSAndroid Build Coastguard Worker }
287*86b64dcbSAndroid Build Coastguard Worker
288*86b64dcbSAndroid Build Coastguard Worker closedir(dir);
289*86b64dcbSAndroid Build Coastguard Worker
290*86b64dcbSAndroid Build Coastguard Worker if (entry) {
291*86b64dcbSAndroid Build Coastguard Worker usbdev_names = 1;
292*86b64dcbSAndroid Build Coastguard Worker return path;
293*86b64dcbSAndroid Build Coastguard Worker }
294*86b64dcbSAndroid Build Coastguard Worker }
295*86b64dcbSAndroid Build Coastguard Worker
296*86b64dcbSAndroid Build Coastguard Worker /* On udev based systems without any usb-devices /dev/bus/usb will not
297*86b64dcbSAndroid Build Coastguard Worker * exist. So if we've not found anything and we're using udev for hotplug
298*86b64dcbSAndroid Build Coastguard Worker * simply assume /dev/bus/usb rather then making libusb_init fail.
299*86b64dcbSAndroid Build Coastguard Worker * Make the same assumption for Android where SELinux policies might block us
300*86b64dcbSAndroid Build Coastguard Worker * from reading /dev on newer devices. */
301*86b64dcbSAndroid Build Coastguard Worker #if defined(HAVE_LIBUDEV) || defined(__ANDROID__)
302*86b64dcbSAndroid Build Coastguard Worker return USB_DEVTMPFS_PATH;
303*86b64dcbSAndroid Build Coastguard Worker #else
304*86b64dcbSAndroid Build Coastguard Worker return NULL;
305*86b64dcbSAndroid Build Coastguard Worker #endif
306*86b64dcbSAndroid Build Coastguard Worker }
307*86b64dcbSAndroid Build Coastguard Worker
get_kernel_version(struct libusb_context * ctx,struct kernel_version * ver)308*86b64dcbSAndroid Build Coastguard Worker static int get_kernel_version(struct libusb_context *ctx,
309*86b64dcbSAndroid Build Coastguard Worker struct kernel_version *ver)
310*86b64dcbSAndroid Build Coastguard Worker {
311*86b64dcbSAndroid Build Coastguard Worker struct utsname uts;
312*86b64dcbSAndroid Build Coastguard Worker int atoms;
313*86b64dcbSAndroid Build Coastguard Worker
314*86b64dcbSAndroid Build Coastguard Worker if (uname(&uts) < 0) {
315*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "uname failed, errno=%d", errno);
316*86b64dcbSAndroid Build Coastguard Worker return -1;
317*86b64dcbSAndroid Build Coastguard Worker }
318*86b64dcbSAndroid Build Coastguard Worker
319*86b64dcbSAndroid Build Coastguard Worker atoms = sscanf(uts.release, "%d.%d.%d", &ver->major, &ver->minor, &ver->sublevel);
320*86b64dcbSAndroid Build Coastguard Worker if (atoms < 2) {
321*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "failed to parse uname release '%s'", uts.release);
322*86b64dcbSAndroid Build Coastguard Worker return -1;
323*86b64dcbSAndroid Build Coastguard Worker }
324*86b64dcbSAndroid Build Coastguard Worker
325*86b64dcbSAndroid Build Coastguard Worker if (atoms < 3)
326*86b64dcbSAndroid Build Coastguard Worker ver->sublevel = -1;
327*86b64dcbSAndroid Build Coastguard Worker
328*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "reported kernel version is %s", uts.release);
329*86b64dcbSAndroid Build Coastguard Worker
330*86b64dcbSAndroid Build Coastguard Worker return 0;
331*86b64dcbSAndroid Build Coastguard Worker }
332*86b64dcbSAndroid Build Coastguard Worker
kernel_version_ge(const struct kernel_version * ver,int major,int minor,int sublevel)333*86b64dcbSAndroid Build Coastguard Worker static int kernel_version_ge(const struct kernel_version *ver,
334*86b64dcbSAndroid Build Coastguard Worker int major, int minor, int sublevel)
335*86b64dcbSAndroid Build Coastguard Worker {
336*86b64dcbSAndroid Build Coastguard Worker if (ver->major > major)
337*86b64dcbSAndroid Build Coastguard Worker return 1;
338*86b64dcbSAndroid Build Coastguard Worker else if (ver->major < major)
339*86b64dcbSAndroid Build Coastguard Worker return 0;
340*86b64dcbSAndroid Build Coastguard Worker
341*86b64dcbSAndroid Build Coastguard Worker /* kmajor == major */
342*86b64dcbSAndroid Build Coastguard Worker if (ver->minor > minor)
343*86b64dcbSAndroid Build Coastguard Worker return 1;
344*86b64dcbSAndroid Build Coastguard Worker else if (ver->minor < minor)
345*86b64dcbSAndroid Build Coastguard Worker return 0;
346*86b64dcbSAndroid Build Coastguard Worker
347*86b64dcbSAndroid Build Coastguard Worker /* kminor == minor */
348*86b64dcbSAndroid Build Coastguard Worker if (ver->sublevel == -1)
349*86b64dcbSAndroid Build Coastguard Worker return sublevel == 0;
350*86b64dcbSAndroid Build Coastguard Worker
351*86b64dcbSAndroid Build Coastguard Worker return ver->sublevel >= sublevel;
352*86b64dcbSAndroid Build Coastguard Worker }
353*86b64dcbSAndroid Build Coastguard Worker
op_init(struct libusb_context * ctx)354*86b64dcbSAndroid Build Coastguard Worker static int op_init(struct libusb_context *ctx)
355*86b64dcbSAndroid Build Coastguard Worker {
356*86b64dcbSAndroid Build Coastguard Worker struct kernel_version kversion;
357*86b64dcbSAndroid Build Coastguard Worker const char *usbfs_path;
358*86b64dcbSAndroid Build Coastguard Worker int r;
359*86b64dcbSAndroid Build Coastguard Worker struct linux_context_priv *cpriv = usbi_get_context_priv(ctx);
360*86b64dcbSAndroid Build Coastguard Worker
361*86b64dcbSAndroid Build Coastguard Worker if (get_kernel_version(ctx, &kversion) < 0)
362*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
363*86b64dcbSAndroid Build Coastguard Worker
364*86b64dcbSAndroid Build Coastguard Worker if (!kernel_version_ge(&kversion, 2, 6, 32)) {
365*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "kernel version is too old (reported as %d.%d.%d)",
366*86b64dcbSAndroid Build Coastguard Worker kversion.major, kversion.minor,
367*86b64dcbSAndroid Build Coastguard Worker kversion.sublevel != -1 ? kversion.sublevel : 0);
368*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_SUPPORTED;
369*86b64dcbSAndroid Build Coastguard Worker }
370*86b64dcbSAndroid Build Coastguard Worker
371*86b64dcbSAndroid Build Coastguard Worker usbfs_path = find_usbfs_path();
372*86b64dcbSAndroid Build Coastguard Worker if (!usbfs_path) {
373*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "could not find usbfs");
374*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
375*86b64dcbSAndroid Build Coastguard Worker }
376*86b64dcbSAndroid Build Coastguard Worker
377*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "found usbfs at %s", usbfs_path);
378*86b64dcbSAndroid Build Coastguard Worker
379*86b64dcbSAndroid Build Coastguard Worker if (!max_iso_packet_len) {
380*86b64dcbSAndroid Build Coastguard Worker if (kernel_version_ge(&kversion, 5, 2, 0))
381*86b64dcbSAndroid Build Coastguard Worker max_iso_packet_len = 98304;
382*86b64dcbSAndroid Build Coastguard Worker else if (kernel_version_ge(&kversion, 3, 10, 0))
383*86b64dcbSAndroid Build Coastguard Worker max_iso_packet_len = 49152;
384*86b64dcbSAndroid Build Coastguard Worker else
385*86b64dcbSAndroid Build Coastguard Worker max_iso_packet_len = 8192;
386*86b64dcbSAndroid Build Coastguard Worker }
387*86b64dcbSAndroid Build Coastguard Worker
388*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "max iso packet length is (likely) %u bytes", max_iso_packet_len);
389*86b64dcbSAndroid Build Coastguard Worker
390*86b64dcbSAndroid Build Coastguard Worker if (sysfs_available == -1) {
391*86b64dcbSAndroid Build Coastguard Worker struct statfs statfsbuf;
392*86b64dcbSAndroid Build Coastguard Worker
393*86b64dcbSAndroid Build Coastguard Worker r = statfs(SYSFS_MOUNT_PATH, &statfsbuf);
394*86b64dcbSAndroid Build Coastguard Worker if (r == 0 && statfsbuf.f_type == SYSFS_MAGIC) {
395*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "sysfs is available");
396*86b64dcbSAndroid Build Coastguard Worker sysfs_available = 1;
397*86b64dcbSAndroid Build Coastguard Worker } else {
398*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ctx, "sysfs not mounted");
399*86b64dcbSAndroid Build Coastguard Worker sysfs_available = 0;
400*86b64dcbSAndroid Build Coastguard Worker }
401*86b64dcbSAndroid Build Coastguard Worker }
402*86b64dcbSAndroid Build Coastguard Worker
403*86b64dcbSAndroid Build Coastguard Worker if (cpriv->no_device_discovery) {
404*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
405*86b64dcbSAndroid Build Coastguard Worker }
406*86b64dcbSAndroid Build Coastguard Worker
407*86b64dcbSAndroid Build Coastguard Worker r = LIBUSB_SUCCESS;
408*86b64dcbSAndroid Build Coastguard Worker if (init_count == 0) {
409*86b64dcbSAndroid Build Coastguard Worker /* start up hotplug event handler */
410*86b64dcbSAndroid Build Coastguard Worker r = linux_start_event_monitor();
411*86b64dcbSAndroid Build Coastguard Worker }
412*86b64dcbSAndroid Build Coastguard Worker if (r == LIBUSB_SUCCESS) {
413*86b64dcbSAndroid Build Coastguard Worker r = linux_scan_devices(ctx);
414*86b64dcbSAndroid Build Coastguard Worker if (r == LIBUSB_SUCCESS)
415*86b64dcbSAndroid Build Coastguard Worker init_count++;
416*86b64dcbSAndroid Build Coastguard Worker else if (init_count == 0)
417*86b64dcbSAndroid Build Coastguard Worker linux_stop_event_monitor();
418*86b64dcbSAndroid Build Coastguard Worker } else {
419*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "error starting hotplug event monitor");
420*86b64dcbSAndroid Build Coastguard Worker }
421*86b64dcbSAndroid Build Coastguard Worker
422*86b64dcbSAndroid Build Coastguard Worker return r;
423*86b64dcbSAndroid Build Coastguard Worker }
424*86b64dcbSAndroid Build Coastguard Worker
op_exit(struct libusb_context * ctx)425*86b64dcbSAndroid Build Coastguard Worker static void op_exit(struct libusb_context *ctx)
426*86b64dcbSAndroid Build Coastguard Worker {
427*86b64dcbSAndroid Build Coastguard Worker struct linux_context_priv *cpriv = usbi_get_context_priv(ctx);
428*86b64dcbSAndroid Build Coastguard Worker
429*86b64dcbSAndroid Build Coastguard Worker if (cpriv->no_device_discovery) {
430*86b64dcbSAndroid Build Coastguard Worker return;
431*86b64dcbSAndroid Build Coastguard Worker }
432*86b64dcbSAndroid Build Coastguard Worker
433*86b64dcbSAndroid Build Coastguard Worker assert(init_count != 0);
434*86b64dcbSAndroid Build Coastguard Worker if (!--init_count) {
435*86b64dcbSAndroid Build Coastguard Worker /* tear down event handler */
436*86b64dcbSAndroid Build Coastguard Worker linux_stop_event_monitor();
437*86b64dcbSAndroid Build Coastguard Worker }
438*86b64dcbSAndroid Build Coastguard Worker }
439*86b64dcbSAndroid Build Coastguard Worker
op_set_option(struct libusb_context * ctx,enum libusb_option option,va_list ap)440*86b64dcbSAndroid Build Coastguard Worker static int op_set_option(struct libusb_context *ctx, enum libusb_option option, va_list ap)
441*86b64dcbSAndroid Build Coastguard Worker {
442*86b64dcbSAndroid Build Coastguard Worker UNUSED(ap);
443*86b64dcbSAndroid Build Coastguard Worker
444*86b64dcbSAndroid Build Coastguard Worker if (option == LIBUSB_OPTION_NO_DEVICE_DISCOVERY) {
445*86b64dcbSAndroid Build Coastguard Worker struct linux_context_priv *cpriv = usbi_get_context_priv(ctx);
446*86b64dcbSAndroid Build Coastguard Worker
447*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "no device discovery will be performed");
448*86b64dcbSAndroid Build Coastguard Worker cpriv->no_device_discovery = 1;
449*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
450*86b64dcbSAndroid Build Coastguard Worker }
451*86b64dcbSAndroid Build Coastguard Worker
452*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_SUPPORTED;
453*86b64dcbSAndroid Build Coastguard Worker }
454*86b64dcbSAndroid Build Coastguard Worker
linux_scan_devices(struct libusb_context * ctx)455*86b64dcbSAndroid Build Coastguard Worker static int linux_scan_devices(struct libusb_context *ctx)
456*86b64dcbSAndroid Build Coastguard Worker {
457*86b64dcbSAndroid Build Coastguard Worker int ret;
458*86b64dcbSAndroid Build Coastguard Worker
459*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_static_lock(&linux_hotplug_lock);
460*86b64dcbSAndroid Build Coastguard Worker
461*86b64dcbSAndroid Build Coastguard Worker #if defined(HAVE_LIBUDEV)
462*86b64dcbSAndroid Build Coastguard Worker ret = linux_udev_scan_devices(ctx);
463*86b64dcbSAndroid Build Coastguard Worker #else
464*86b64dcbSAndroid Build Coastguard Worker ret = linux_default_scan_devices(ctx);
465*86b64dcbSAndroid Build Coastguard Worker #endif
466*86b64dcbSAndroid Build Coastguard Worker
467*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_static_unlock(&linux_hotplug_lock);
468*86b64dcbSAndroid Build Coastguard Worker
469*86b64dcbSAndroid Build Coastguard Worker return ret;
470*86b64dcbSAndroid Build Coastguard Worker }
471*86b64dcbSAndroid Build Coastguard Worker
op_hotplug_poll(void)472*86b64dcbSAndroid Build Coastguard Worker static void op_hotplug_poll(void)
473*86b64dcbSAndroid Build Coastguard Worker {
474*86b64dcbSAndroid Build Coastguard Worker linux_hotplug_poll();
475*86b64dcbSAndroid Build Coastguard Worker }
476*86b64dcbSAndroid Build Coastguard Worker
open_sysfs_attr(struct libusb_context * ctx,const char * sysfs_dir,const char * attr)477*86b64dcbSAndroid Build Coastguard Worker static int open_sysfs_attr(struct libusb_context *ctx,
478*86b64dcbSAndroid Build Coastguard Worker const char *sysfs_dir, const char *attr)
479*86b64dcbSAndroid Build Coastguard Worker {
480*86b64dcbSAndroid Build Coastguard Worker char filename[256];
481*86b64dcbSAndroid Build Coastguard Worker int fd;
482*86b64dcbSAndroid Build Coastguard Worker
483*86b64dcbSAndroid Build Coastguard Worker snprintf(filename, sizeof(filename), SYSFS_DEVICE_PATH "/%s/%s", sysfs_dir, attr);
484*86b64dcbSAndroid Build Coastguard Worker fd = open(filename, O_RDONLY | O_CLOEXEC);
485*86b64dcbSAndroid Build Coastguard Worker if (fd < 0) {
486*86b64dcbSAndroid Build Coastguard Worker if (errno == ENOENT) {
487*86b64dcbSAndroid Build Coastguard Worker /* File doesn't exist. Assume the device has been
488*86b64dcbSAndroid Build Coastguard Worker disconnected (see trac ticket #70). */
489*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
490*86b64dcbSAndroid Build Coastguard Worker }
491*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "open %s failed, errno=%d", filename, errno);
492*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
493*86b64dcbSAndroid Build Coastguard Worker }
494*86b64dcbSAndroid Build Coastguard Worker
495*86b64dcbSAndroid Build Coastguard Worker return fd;
496*86b64dcbSAndroid Build Coastguard Worker }
497*86b64dcbSAndroid Build Coastguard Worker
498*86b64dcbSAndroid Build Coastguard Worker /* Note only suitable for attributes which always read >= 0, < 0 is error */
read_sysfs_attr(struct libusb_context * ctx,const char * sysfs_dir,const char * attr,int max_value,int * value_p)499*86b64dcbSAndroid Build Coastguard Worker static int read_sysfs_attr(struct libusb_context *ctx,
500*86b64dcbSAndroid Build Coastguard Worker const char *sysfs_dir, const char *attr, int max_value, int *value_p)
501*86b64dcbSAndroid Build Coastguard Worker {
502*86b64dcbSAndroid Build Coastguard Worker char buf[20], *endptr;
503*86b64dcbSAndroid Build Coastguard Worker long value;
504*86b64dcbSAndroid Build Coastguard Worker ssize_t r;
505*86b64dcbSAndroid Build Coastguard Worker int fd;
506*86b64dcbSAndroid Build Coastguard Worker
507*86b64dcbSAndroid Build Coastguard Worker fd = open_sysfs_attr(ctx, sysfs_dir, attr);
508*86b64dcbSAndroid Build Coastguard Worker if (fd < 0)
509*86b64dcbSAndroid Build Coastguard Worker return fd;
510*86b64dcbSAndroid Build Coastguard Worker
511*86b64dcbSAndroid Build Coastguard Worker r = read(fd, buf, sizeof(buf) - 1);
512*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
513*86b64dcbSAndroid Build Coastguard Worker r = errno;
514*86b64dcbSAndroid Build Coastguard Worker close(fd);
515*86b64dcbSAndroid Build Coastguard Worker if (r == ENODEV)
516*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
517*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "attribute %s read failed, errno=%zd", attr, r);
518*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
519*86b64dcbSAndroid Build Coastguard Worker }
520*86b64dcbSAndroid Build Coastguard Worker close(fd);
521*86b64dcbSAndroid Build Coastguard Worker
522*86b64dcbSAndroid Build Coastguard Worker if (r == 0) {
523*86b64dcbSAndroid Build Coastguard Worker /* Certain attributes (e.g. bConfigurationValue) are not
524*86b64dcbSAndroid Build Coastguard Worker * populated if the device is not configured. */
525*86b64dcbSAndroid Build Coastguard Worker *value_p = -1;
526*86b64dcbSAndroid Build Coastguard Worker return 0;
527*86b64dcbSAndroid Build Coastguard Worker }
528*86b64dcbSAndroid Build Coastguard Worker
529*86b64dcbSAndroid Build Coastguard Worker /* The kernel does *not* NUL-terminate the string, but every attribute
530*86b64dcbSAndroid Build Coastguard Worker * should be terminated with a newline character. */
531*86b64dcbSAndroid Build Coastguard Worker if (!isdigit(buf[0])) {
532*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "attribute %s doesn't have numeric value?", attr);
533*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
534*86b64dcbSAndroid Build Coastguard Worker } else if (buf[r - 1] != '\n') {
535*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ctx, "attribute %s doesn't end with newline?", attr);
536*86b64dcbSAndroid Build Coastguard Worker } else {
537*86b64dcbSAndroid Build Coastguard Worker /* Remove the terminating newline character */
538*86b64dcbSAndroid Build Coastguard Worker r--;
539*86b64dcbSAndroid Build Coastguard Worker }
540*86b64dcbSAndroid Build Coastguard Worker buf[r] = '\0';
541*86b64dcbSAndroid Build Coastguard Worker
542*86b64dcbSAndroid Build Coastguard Worker errno = 0;
543*86b64dcbSAndroid Build Coastguard Worker value = strtol(buf, &endptr, 10);
544*86b64dcbSAndroid Build Coastguard Worker if (buf == endptr || value < 0 || value > (long)max_value || errno) {
545*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "attribute %s contains an invalid value: '%s'", attr, buf);
546*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_INVALID_PARAM;
547*86b64dcbSAndroid Build Coastguard Worker } else if (*endptr != '\0') {
548*86b64dcbSAndroid Build Coastguard Worker /* Consider the value to be valid if the remainder is a '.'
549*86b64dcbSAndroid Build Coastguard Worker * character followed by numbers. This occurs, for example,
550*86b64dcbSAndroid Build Coastguard Worker * when reading the "speed" attribute for a low-speed device
551*86b64dcbSAndroid Build Coastguard Worker * (e.g. "1.5") */
552*86b64dcbSAndroid Build Coastguard Worker if (*endptr == '.' && isdigit(*(endptr + 1))) {
553*86b64dcbSAndroid Build Coastguard Worker endptr++;
554*86b64dcbSAndroid Build Coastguard Worker while (isdigit(*endptr))
555*86b64dcbSAndroid Build Coastguard Worker endptr++;
556*86b64dcbSAndroid Build Coastguard Worker }
557*86b64dcbSAndroid Build Coastguard Worker if (*endptr != '\0') {
558*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "attribute %s contains an invalid value: '%s'", attr, buf);
559*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_INVALID_PARAM;
560*86b64dcbSAndroid Build Coastguard Worker }
561*86b64dcbSAndroid Build Coastguard Worker }
562*86b64dcbSAndroid Build Coastguard Worker
563*86b64dcbSAndroid Build Coastguard Worker *value_p = (int)value;
564*86b64dcbSAndroid Build Coastguard Worker return 0;
565*86b64dcbSAndroid Build Coastguard Worker }
566*86b64dcbSAndroid Build Coastguard Worker
sysfs_scan_device(struct libusb_context * ctx,const char * devname)567*86b64dcbSAndroid Build Coastguard Worker static int sysfs_scan_device(struct libusb_context *ctx, const char *devname)
568*86b64dcbSAndroid Build Coastguard Worker {
569*86b64dcbSAndroid Build Coastguard Worker uint8_t busnum, devaddr;
570*86b64dcbSAndroid Build Coastguard Worker int ret;
571*86b64dcbSAndroid Build Coastguard Worker
572*86b64dcbSAndroid Build Coastguard Worker ret = linux_get_device_address(ctx, 0, &busnum, &devaddr, NULL, devname, -1);
573*86b64dcbSAndroid Build Coastguard Worker if (ret != LIBUSB_SUCCESS)
574*86b64dcbSAndroid Build Coastguard Worker return ret;
575*86b64dcbSAndroid Build Coastguard Worker
576*86b64dcbSAndroid Build Coastguard Worker return linux_enumerate_device(ctx, busnum, devaddr, devname);
577*86b64dcbSAndroid Build Coastguard Worker }
578*86b64dcbSAndroid Build Coastguard Worker
579*86b64dcbSAndroid Build Coastguard Worker /* read the bConfigurationValue for a device */
sysfs_get_active_config(struct libusb_device * dev,int * config)580*86b64dcbSAndroid Build Coastguard Worker static int sysfs_get_active_config(struct libusb_device *dev, int *config)
581*86b64dcbSAndroid Build Coastguard Worker {
582*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv *priv = usbi_get_device_priv(dev);
583*86b64dcbSAndroid Build Coastguard Worker
584*86b64dcbSAndroid Build Coastguard Worker return read_sysfs_attr(DEVICE_CTX(dev), priv->sysfs_dir, "bConfigurationValue",
585*86b64dcbSAndroid Build Coastguard Worker UINT8_MAX, config);
586*86b64dcbSAndroid Build Coastguard Worker }
587*86b64dcbSAndroid Build Coastguard Worker
linux_get_device_address(struct libusb_context * ctx,int detached,uint8_t * busnum,uint8_t * devaddr,const char * dev_node,const char * sys_name,int fd)588*86b64dcbSAndroid Build Coastguard Worker int linux_get_device_address(struct libusb_context *ctx, int detached,
589*86b64dcbSAndroid Build Coastguard Worker uint8_t *busnum, uint8_t *devaddr, const char *dev_node,
590*86b64dcbSAndroid Build Coastguard Worker const char *sys_name, int fd)
591*86b64dcbSAndroid Build Coastguard Worker {
592*86b64dcbSAndroid Build Coastguard Worker int sysfs_val;
593*86b64dcbSAndroid Build Coastguard Worker int r;
594*86b64dcbSAndroid Build Coastguard Worker
595*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "getting address for device: %s detached: %d", sys_name, detached);
596*86b64dcbSAndroid Build Coastguard Worker /* can't use sysfs to read the bus and device number if the
597*86b64dcbSAndroid Build Coastguard Worker * device has been detached */
598*86b64dcbSAndroid Build Coastguard Worker if (!sysfs_available || detached || !sys_name) {
599*86b64dcbSAndroid Build Coastguard Worker if (!dev_node && fd >= 0) {
600*86b64dcbSAndroid Build Coastguard Worker char *fd_path = alloca(PATH_MAX);
601*86b64dcbSAndroid Build Coastguard Worker char proc_path[32];
602*86b64dcbSAndroid Build Coastguard Worker
603*86b64dcbSAndroid Build Coastguard Worker /* try to retrieve the device node from fd */
604*86b64dcbSAndroid Build Coastguard Worker snprintf(proc_path, sizeof(proc_path), "/proc/self/fd/%d", fd);
605*86b64dcbSAndroid Build Coastguard Worker r = readlink(proc_path, fd_path, PATH_MAX - 1);
606*86b64dcbSAndroid Build Coastguard Worker if (r > 0) {
607*86b64dcbSAndroid Build Coastguard Worker fd_path[r] = '\0';
608*86b64dcbSAndroid Build Coastguard Worker dev_node = fd_path;
609*86b64dcbSAndroid Build Coastguard Worker }
610*86b64dcbSAndroid Build Coastguard Worker }
611*86b64dcbSAndroid Build Coastguard Worker
612*86b64dcbSAndroid Build Coastguard Worker if (!dev_node)
613*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
614*86b64dcbSAndroid Build Coastguard Worker
615*86b64dcbSAndroid Build Coastguard Worker /* will this work with all supported kernel versions? */
616*86b64dcbSAndroid Build Coastguard Worker if (!strncmp(dev_node, "/dev/bus/usb", 12))
617*86b64dcbSAndroid Build Coastguard Worker sscanf(dev_node, "/dev/bus/usb/%hhu/%hhu", busnum, devaddr);
618*86b64dcbSAndroid Build Coastguard Worker else
619*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
620*86b64dcbSAndroid Build Coastguard Worker
621*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
622*86b64dcbSAndroid Build Coastguard Worker }
623*86b64dcbSAndroid Build Coastguard Worker
624*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "scan %s", sys_name);
625*86b64dcbSAndroid Build Coastguard Worker
626*86b64dcbSAndroid Build Coastguard Worker r = read_sysfs_attr(ctx, sys_name, "busnum", UINT8_MAX, &sysfs_val);
627*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
628*86b64dcbSAndroid Build Coastguard Worker return r;
629*86b64dcbSAndroid Build Coastguard Worker *busnum = (uint8_t)sysfs_val;
630*86b64dcbSAndroid Build Coastguard Worker
631*86b64dcbSAndroid Build Coastguard Worker r = read_sysfs_attr(ctx, sys_name, "devnum", UINT8_MAX, &sysfs_val);
632*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
633*86b64dcbSAndroid Build Coastguard Worker return r;
634*86b64dcbSAndroid Build Coastguard Worker *devaddr = (uint8_t)sysfs_val;
635*86b64dcbSAndroid Build Coastguard Worker
636*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "bus=%u dev=%u", *busnum, *devaddr);
637*86b64dcbSAndroid Build Coastguard Worker
638*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
639*86b64dcbSAndroid Build Coastguard Worker }
640*86b64dcbSAndroid Build Coastguard Worker
641*86b64dcbSAndroid Build Coastguard Worker /* Return offset of the next config descriptor */
seek_to_next_config(struct libusb_context * ctx,uint8_t * buffer,size_t len)642*86b64dcbSAndroid Build Coastguard Worker static int seek_to_next_config(struct libusb_context *ctx,
643*86b64dcbSAndroid Build Coastguard Worker uint8_t *buffer, size_t len)
644*86b64dcbSAndroid Build Coastguard Worker {
645*86b64dcbSAndroid Build Coastguard Worker struct usbi_descriptor_header *header;
646*86b64dcbSAndroid Build Coastguard Worker int offset;
647*86b64dcbSAndroid Build Coastguard Worker
648*86b64dcbSAndroid Build Coastguard Worker /* Start seeking past the config descriptor */
649*86b64dcbSAndroid Build Coastguard Worker offset = LIBUSB_DT_CONFIG_SIZE;
650*86b64dcbSAndroid Build Coastguard Worker buffer += LIBUSB_DT_CONFIG_SIZE;
651*86b64dcbSAndroid Build Coastguard Worker len -= LIBUSB_DT_CONFIG_SIZE;
652*86b64dcbSAndroid Build Coastguard Worker
653*86b64dcbSAndroid Build Coastguard Worker while (len > 0) {
654*86b64dcbSAndroid Build Coastguard Worker if (len < 2) {
655*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "remaining descriptor length too small %zu/2", len);
656*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
657*86b64dcbSAndroid Build Coastguard Worker }
658*86b64dcbSAndroid Build Coastguard Worker
659*86b64dcbSAndroid Build Coastguard Worker header = (struct usbi_descriptor_header *)buffer;
660*86b64dcbSAndroid Build Coastguard Worker if (header->bDescriptorType == LIBUSB_DT_CONFIG)
661*86b64dcbSAndroid Build Coastguard Worker return offset;
662*86b64dcbSAndroid Build Coastguard Worker
663*86b64dcbSAndroid Build Coastguard Worker if (header->bLength < 2) {
664*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "invalid descriptor bLength %hhu", header->bLength);
665*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
666*86b64dcbSAndroid Build Coastguard Worker }
667*86b64dcbSAndroid Build Coastguard Worker
668*86b64dcbSAndroid Build Coastguard Worker if (len < header->bLength) {
669*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "bLength overflow by %zu bytes",
670*86b64dcbSAndroid Build Coastguard Worker (size_t)header->bLength - len);
671*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
672*86b64dcbSAndroid Build Coastguard Worker }
673*86b64dcbSAndroid Build Coastguard Worker
674*86b64dcbSAndroid Build Coastguard Worker offset += header->bLength;
675*86b64dcbSAndroid Build Coastguard Worker buffer += header->bLength;
676*86b64dcbSAndroid Build Coastguard Worker len -= header->bLength;
677*86b64dcbSAndroid Build Coastguard Worker }
678*86b64dcbSAndroid Build Coastguard Worker
679*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "config descriptor not found");
680*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
681*86b64dcbSAndroid Build Coastguard Worker }
682*86b64dcbSAndroid Build Coastguard Worker
parse_config_descriptors(struct libusb_device * dev)683*86b64dcbSAndroid Build Coastguard Worker static int parse_config_descriptors(struct libusb_device *dev)
684*86b64dcbSAndroid Build Coastguard Worker {
685*86b64dcbSAndroid Build Coastguard Worker struct libusb_context *ctx = DEVICE_CTX(dev);
686*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv *priv = usbi_get_device_priv(dev);
687*86b64dcbSAndroid Build Coastguard Worker struct usbi_device_descriptor *device_desc;
688*86b64dcbSAndroid Build Coastguard Worker uint8_t idx, num_configs;
689*86b64dcbSAndroid Build Coastguard Worker uint8_t *buffer;
690*86b64dcbSAndroid Build Coastguard Worker size_t remaining;
691*86b64dcbSAndroid Build Coastguard Worker
692*86b64dcbSAndroid Build Coastguard Worker device_desc = priv->descriptors;
693*86b64dcbSAndroid Build Coastguard Worker num_configs = device_desc->bNumConfigurations;
694*86b64dcbSAndroid Build Coastguard Worker
695*86b64dcbSAndroid Build Coastguard Worker if (num_configs == 0)
696*86b64dcbSAndroid Build Coastguard Worker return 0; /* no configurations? */
697*86b64dcbSAndroid Build Coastguard Worker
698*86b64dcbSAndroid Build Coastguard Worker priv->config_descriptors = malloc(num_configs * sizeof(priv->config_descriptors[0]));
699*86b64dcbSAndroid Build Coastguard Worker if (!priv->config_descriptors)
700*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_MEM;
701*86b64dcbSAndroid Build Coastguard Worker
702*86b64dcbSAndroid Build Coastguard Worker buffer = (uint8_t *)priv->descriptors + LIBUSB_DT_DEVICE_SIZE;
703*86b64dcbSAndroid Build Coastguard Worker remaining = priv->descriptors_len - LIBUSB_DT_DEVICE_SIZE;
704*86b64dcbSAndroid Build Coastguard Worker
705*86b64dcbSAndroid Build Coastguard Worker for (idx = 0; idx < num_configs; idx++) {
706*86b64dcbSAndroid Build Coastguard Worker struct usbi_configuration_descriptor *config_desc;
707*86b64dcbSAndroid Build Coastguard Worker uint16_t config_len;
708*86b64dcbSAndroid Build Coastguard Worker
709*86b64dcbSAndroid Build Coastguard Worker if (remaining < LIBUSB_DT_CONFIG_SIZE) {
710*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "short descriptor read %zu/%d",
711*86b64dcbSAndroid Build Coastguard Worker remaining, LIBUSB_DT_CONFIG_SIZE);
712*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
713*86b64dcbSAndroid Build Coastguard Worker }
714*86b64dcbSAndroid Build Coastguard Worker
715*86b64dcbSAndroid Build Coastguard Worker config_desc = (struct usbi_configuration_descriptor *)buffer;
716*86b64dcbSAndroid Build Coastguard Worker if (config_desc->bDescriptorType != LIBUSB_DT_CONFIG) {
717*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "descriptor is not a config desc (type 0x%02x)",
718*86b64dcbSAndroid Build Coastguard Worker config_desc->bDescriptorType);
719*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
720*86b64dcbSAndroid Build Coastguard Worker } else if (config_desc->bLength < LIBUSB_DT_CONFIG_SIZE) {
721*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "invalid descriptor bLength %u",
722*86b64dcbSAndroid Build Coastguard Worker config_desc->bLength);
723*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
724*86b64dcbSAndroid Build Coastguard Worker }
725*86b64dcbSAndroid Build Coastguard Worker
726*86b64dcbSAndroid Build Coastguard Worker config_len = libusb_le16_to_cpu(config_desc->wTotalLength);
727*86b64dcbSAndroid Build Coastguard Worker if (config_len < LIBUSB_DT_CONFIG_SIZE) {
728*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "invalid wTotalLength %u", config_len);
729*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
730*86b64dcbSAndroid Build Coastguard Worker }
731*86b64dcbSAndroid Build Coastguard Worker
732*86b64dcbSAndroid Build Coastguard Worker if (priv->sysfs_dir) {
733*86b64dcbSAndroid Build Coastguard Worker /*
734*86b64dcbSAndroid Build Coastguard Worker * In sysfs wTotalLength is ignored, instead the kernel returns a
735*86b64dcbSAndroid Build Coastguard Worker * config descriptor with verified bLength fields, with descriptors
736*86b64dcbSAndroid Build Coastguard Worker * with an invalid bLength removed.
737*86b64dcbSAndroid Build Coastguard Worker */
738*86b64dcbSAndroid Build Coastguard Worker uint16_t sysfs_config_len;
739*86b64dcbSAndroid Build Coastguard Worker int offset;
740*86b64dcbSAndroid Build Coastguard Worker
741*86b64dcbSAndroid Build Coastguard Worker if (num_configs > 1 && idx < num_configs - 1) {
742*86b64dcbSAndroid Build Coastguard Worker offset = seek_to_next_config(ctx, buffer, remaining);
743*86b64dcbSAndroid Build Coastguard Worker if (offset < 0)
744*86b64dcbSAndroid Build Coastguard Worker return offset;
745*86b64dcbSAndroid Build Coastguard Worker sysfs_config_len = (uint16_t)offset;
746*86b64dcbSAndroid Build Coastguard Worker } else {
747*86b64dcbSAndroid Build Coastguard Worker sysfs_config_len = (uint16_t)remaining;
748*86b64dcbSAndroid Build Coastguard Worker }
749*86b64dcbSAndroid Build Coastguard Worker
750*86b64dcbSAndroid Build Coastguard Worker if (config_len != sysfs_config_len) {
751*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ctx, "config length mismatch wTotalLength %u real %u",
752*86b64dcbSAndroid Build Coastguard Worker config_len, sysfs_config_len);
753*86b64dcbSAndroid Build Coastguard Worker config_len = sysfs_config_len;
754*86b64dcbSAndroid Build Coastguard Worker }
755*86b64dcbSAndroid Build Coastguard Worker } else {
756*86b64dcbSAndroid Build Coastguard Worker /*
757*86b64dcbSAndroid Build Coastguard Worker * In usbfs the config descriptors are wTotalLength bytes apart,
758*86b64dcbSAndroid Build Coastguard Worker * with any short reads from the device appearing as holes in the file.
759*86b64dcbSAndroid Build Coastguard Worker */
760*86b64dcbSAndroid Build Coastguard Worker if (config_len > remaining) {
761*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ctx, "short descriptor read %zu/%u", remaining, config_len);
762*86b64dcbSAndroid Build Coastguard Worker config_len = (uint16_t)remaining;
763*86b64dcbSAndroid Build Coastguard Worker }
764*86b64dcbSAndroid Build Coastguard Worker }
765*86b64dcbSAndroid Build Coastguard Worker
766*86b64dcbSAndroid Build Coastguard Worker if (config_desc->bConfigurationValue == 0)
767*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ctx, "device has configuration 0");
768*86b64dcbSAndroid Build Coastguard Worker
769*86b64dcbSAndroid Build Coastguard Worker priv->config_descriptors[idx].desc = config_desc;
770*86b64dcbSAndroid Build Coastguard Worker priv->config_descriptors[idx].actual_len = config_len;
771*86b64dcbSAndroid Build Coastguard Worker
772*86b64dcbSAndroid Build Coastguard Worker buffer += config_len;
773*86b64dcbSAndroid Build Coastguard Worker remaining -= config_len;
774*86b64dcbSAndroid Build Coastguard Worker }
775*86b64dcbSAndroid Build Coastguard Worker
776*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
777*86b64dcbSAndroid Build Coastguard Worker }
778*86b64dcbSAndroid Build Coastguard Worker
op_get_config_descriptor_by_value(struct libusb_device * dev,uint8_t value,void ** buffer)779*86b64dcbSAndroid Build Coastguard Worker static int op_get_config_descriptor_by_value(struct libusb_device *dev,
780*86b64dcbSAndroid Build Coastguard Worker uint8_t value, void **buffer)
781*86b64dcbSAndroid Build Coastguard Worker {
782*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv *priv = usbi_get_device_priv(dev);
783*86b64dcbSAndroid Build Coastguard Worker struct config_descriptor *config;
784*86b64dcbSAndroid Build Coastguard Worker uint8_t idx;
785*86b64dcbSAndroid Build Coastguard Worker
786*86b64dcbSAndroid Build Coastguard Worker for (idx = 0; idx < dev->device_descriptor.bNumConfigurations; idx++) {
787*86b64dcbSAndroid Build Coastguard Worker config = &priv->config_descriptors[idx];
788*86b64dcbSAndroid Build Coastguard Worker if (config->desc->bConfigurationValue == value) {
789*86b64dcbSAndroid Build Coastguard Worker *buffer = config->desc;
790*86b64dcbSAndroid Build Coastguard Worker return (int)config->actual_len;
791*86b64dcbSAndroid Build Coastguard Worker }
792*86b64dcbSAndroid Build Coastguard Worker }
793*86b64dcbSAndroid Build Coastguard Worker
794*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
795*86b64dcbSAndroid Build Coastguard Worker }
796*86b64dcbSAndroid Build Coastguard Worker
op_get_active_config_descriptor(struct libusb_device * dev,void * buffer,size_t len)797*86b64dcbSAndroid Build Coastguard Worker static int op_get_active_config_descriptor(struct libusb_device *dev,
798*86b64dcbSAndroid Build Coastguard Worker void *buffer, size_t len)
799*86b64dcbSAndroid Build Coastguard Worker {
800*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv *priv = usbi_get_device_priv(dev);
801*86b64dcbSAndroid Build Coastguard Worker void *config_desc;
802*86b64dcbSAndroid Build Coastguard Worker int active_config;
803*86b64dcbSAndroid Build Coastguard Worker int r;
804*86b64dcbSAndroid Build Coastguard Worker
805*86b64dcbSAndroid Build Coastguard Worker if (priv->sysfs_dir) {
806*86b64dcbSAndroid Build Coastguard Worker r = sysfs_get_active_config(dev, &active_config);
807*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
808*86b64dcbSAndroid Build Coastguard Worker return r;
809*86b64dcbSAndroid Build Coastguard Worker } else {
810*86b64dcbSAndroid Build Coastguard Worker /* Use cached bConfigurationValue */
811*86b64dcbSAndroid Build Coastguard Worker active_config = priv->active_config;
812*86b64dcbSAndroid Build Coastguard Worker }
813*86b64dcbSAndroid Build Coastguard Worker
814*86b64dcbSAndroid Build Coastguard Worker if (active_config == -1) {
815*86b64dcbSAndroid Build Coastguard Worker usbi_err(DEVICE_CTX(dev), "device unconfigured");
816*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
817*86b64dcbSAndroid Build Coastguard Worker }
818*86b64dcbSAndroid Build Coastguard Worker
819*86b64dcbSAndroid Build Coastguard Worker r = op_get_config_descriptor_by_value(dev, (uint8_t)active_config, &config_desc);
820*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
821*86b64dcbSAndroid Build Coastguard Worker return r;
822*86b64dcbSAndroid Build Coastguard Worker
823*86b64dcbSAndroid Build Coastguard Worker len = MIN(len, (size_t)r);
824*86b64dcbSAndroid Build Coastguard Worker memcpy(buffer, config_desc, len);
825*86b64dcbSAndroid Build Coastguard Worker return len;
826*86b64dcbSAndroid Build Coastguard Worker }
827*86b64dcbSAndroid Build Coastguard Worker
op_get_config_descriptor(struct libusb_device * dev,uint8_t config_index,void * buffer,size_t len)828*86b64dcbSAndroid Build Coastguard Worker static int op_get_config_descriptor(struct libusb_device *dev,
829*86b64dcbSAndroid Build Coastguard Worker uint8_t config_index, void *buffer, size_t len)
830*86b64dcbSAndroid Build Coastguard Worker {
831*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv *priv = usbi_get_device_priv(dev);
832*86b64dcbSAndroid Build Coastguard Worker struct config_descriptor *config;
833*86b64dcbSAndroid Build Coastguard Worker
834*86b64dcbSAndroid Build Coastguard Worker if (config_index >= dev->device_descriptor.bNumConfigurations)
835*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
836*86b64dcbSAndroid Build Coastguard Worker
837*86b64dcbSAndroid Build Coastguard Worker config = &priv->config_descriptors[config_index];
838*86b64dcbSAndroid Build Coastguard Worker len = MIN(len, config->actual_len);
839*86b64dcbSAndroid Build Coastguard Worker memcpy(buffer, config->desc, len);
840*86b64dcbSAndroid Build Coastguard Worker return len;
841*86b64dcbSAndroid Build Coastguard Worker }
842*86b64dcbSAndroid Build Coastguard Worker
843*86b64dcbSAndroid Build Coastguard Worker /* send a control message to retrieve active configuration */
usbfs_get_active_config(struct libusb_device * dev,int fd)844*86b64dcbSAndroid Build Coastguard Worker static int usbfs_get_active_config(struct libusb_device *dev, int fd)
845*86b64dcbSAndroid Build Coastguard Worker {
846*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv *priv = usbi_get_device_priv(dev);
847*86b64dcbSAndroid Build Coastguard Worker uint8_t active_config = 0;
848*86b64dcbSAndroid Build Coastguard Worker int r;
849*86b64dcbSAndroid Build Coastguard Worker
850*86b64dcbSAndroid Build Coastguard Worker struct usbfs_ctrltransfer ctrl = {
851*86b64dcbSAndroid Build Coastguard Worker .bmRequestType = LIBUSB_ENDPOINT_IN,
852*86b64dcbSAndroid Build Coastguard Worker .bRequest = LIBUSB_REQUEST_GET_CONFIGURATION,
853*86b64dcbSAndroid Build Coastguard Worker .wValue = 0,
854*86b64dcbSAndroid Build Coastguard Worker .wIndex = 0,
855*86b64dcbSAndroid Build Coastguard Worker .wLength = 1,
856*86b64dcbSAndroid Build Coastguard Worker .timeout = 1000,
857*86b64dcbSAndroid Build Coastguard Worker .data = &active_config
858*86b64dcbSAndroid Build Coastguard Worker };
859*86b64dcbSAndroid Build Coastguard Worker
860*86b64dcbSAndroid Build Coastguard Worker r = ioctl(fd, IOCTL_USBFS_CONTROL, &ctrl);
861*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
862*86b64dcbSAndroid Build Coastguard Worker if (errno == ENODEV)
863*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
864*86b64dcbSAndroid Build Coastguard Worker
865*86b64dcbSAndroid Build Coastguard Worker /* we hit this error path frequently with buggy devices :( */
866*86b64dcbSAndroid Build Coastguard Worker usbi_warn(DEVICE_CTX(dev), "get configuration failed, errno=%d", errno);
867*86b64dcbSAndroid Build Coastguard Worker
868*86b64dcbSAndroid Build Coastguard Worker /* assume the current configuration is the first one if we have
869*86b64dcbSAndroid Build Coastguard Worker * the configuration descriptors, otherwise treat the device
870*86b64dcbSAndroid Build Coastguard Worker * as unconfigured. */
871*86b64dcbSAndroid Build Coastguard Worker if (priv->config_descriptors)
872*86b64dcbSAndroid Build Coastguard Worker priv->active_config = (int)priv->config_descriptors[0].desc->bConfigurationValue;
873*86b64dcbSAndroid Build Coastguard Worker else
874*86b64dcbSAndroid Build Coastguard Worker priv->active_config = -1;
875*86b64dcbSAndroid Build Coastguard Worker } else if (active_config == 0) {
876*86b64dcbSAndroid Build Coastguard Worker if (dev_has_config0(dev)) {
877*86b64dcbSAndroid Build Coastguard Worker /* some buggy devices have a configuration 0, but we're
878*86b64dcbSAndroid Build Coastguard Worker * reaching into the corner of a corner case here. */
879*86b64dcbSAndroid Build Coastguard Worker priv->active_config = 0;
880*86b64dcbSAndroid Build Coastguard Worker } else {
881*86b64dcbSAndroid Build Coastguard Worker priv->active_config = -1;
882*86b64dcbSAndroid Build Coastguard Worker }
883*86b64dcbSAndroid Build Coastguard Worker } else {
884*86b64dcbSAndroid Build Coastguard Worker priv->active_config = (int)active_config;
885*86b64dcbSAndroid Build Coastguard Worker }
886*86b64dcbSAndroid Build Coastguard Worker
887*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
888*86b64dcbSAndroid Build Coastguard Worker }
889*86b64dcbSAndroid Build Coastguard Worker
usbfs_get_speed(struct libusb_context * ctx,int fd)890*86b64dcbSAndroid Build Coastguard Worker static enum libusb_speed usbfs_get_speed(struct libusb_context *ctx, int fd)
891*86b64dcbSAndroid Build Coastguard Worker {
892*86b64dcbSAndroid Build Coastguard Worker int r;
893*86b64dcbSAndroid Build Coastguard Worker
894*86b64dcbSAndroid Build Coastguard Worker r = ioctl(fd, IOCTL_USBFS_GET_SPEED, NULL);
895*86b64dcbSAndroid Build Coastguard Worker switch (r) {
896*86b64dcbSAndroid Build Coastguard Worker case USBFS_SPEED_UNKNOWN: return LIBUSB_SPEED_UNKNOWN;
897*86b64dcbSAndroid Build Coastguard Worker case USBFS_SPEED_LOW: return LIBUSB_SPEED_LOW;
898*86b64dcbSAndroid Build Coastguard Worker case USBFS_SPEED_FULL: return LIBUSB_SPEED_FULL;
899*86b64dcbSAndroid Build Coastguard Worker case USBFS_SPEED_HIGH: return LIBUSB_SPEED_HIGH;
900*86b64dcbSAndroid Build Coastguard Worker case USBFS_SPEED_WIRELESS: return LIBUSB_SPEED_HIGH;
901*86b64dcbSAndroid Build Coastguard Worker case USBFS_SPEED_SUPER: return LIBUSB_SPEED_SUPER;
902*86b64dcbSAndroid Build Coastguard Worker case USBFS_SPEED_SUPER_PLUS: return LIBUSB_SPEED_SUPER_PLUS;
903*86b64dcbSAndroid Build Coastguard Worker default:
904*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ctx, "Error getting device speed: %d", r);
905*86b64dcbSAndroid Build Coastguard Worker }
906*86b64dcbSAndroid Build Coastguard Worker
907*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SPEED_UNKNOWN;
908*86b64dcbSAndroid Build Coastguard Worker }
909*86b64dcbSAndroid Build Coastguard Worker
initialize_device(struct libusb_device * dev,uint8_t busnum,uint8_t devaddr,const char * sysfs_dir,int wrapped_fd)910*86b64dcbSAndroid Build Coastguard Worker static int initialize_device(struct libusb_device *dev, uint8_t busnum,
911*86b64dcbSAndroid Build Coastguard Worker uint8_t devaddr, const char *sysfs_dir, int wrapped_fd)
912*86b64dcbSAndroid Build Coastguard Worker {
913*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv *priv = usbi_get_device_priv(dev);
914*86b64dcbSAndroid Build Coastguard Worker struct libusb_context *ctx = DEVICE_CTX(dev);
915*86b64dcbSAndroid Build Coastguard Worker size_t alloc_len;
916*86b64dcbSAndroid Build Coastguard Worker int fd, speed, r;
917*86b64dcbSAndroid Build Coastguard Worker ssize_t nb;
918*86b64dcbSAndroid Build Coastguard Worker
919*86b64dcbSAndroid Build Coastguard Worker dev->bus_number = busnum;
920*86b64dcbSAndroid Build Coastguard Worker dev->device_address = devaddr;
921*86b64dcbSAndroid Build Coastguard Worker
922*86b64dcbSAndroid Build Coastguard Worker if (sysfs_dir) {
923*86b64dcbSAndroid Build Coastguard Worker priv->sysfs_dir = strdup(sysfs_dir);
924*86b64dcbSAndroid Build Coastguard Worker if (!priv->sysfs_dir)
925*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_MEM;
926*86b64dcbSAndroid Build Coastguard Worker
927*86b64dcbSAndroid Build Coastguard Worker /* Note speed can contain 1.5, in this case read_sysfs_attr()
928*86b64dcbSAndroid Build Coastguard Worker will stop parsing at the '.' and return 1 */
929*86b64dcbSAndroid Build Coastguard Worker if (read_sysfs_attr(ctx, sysfs_dir, "speed", INT_MAX, &speed) == 0) {
930*86b64dcbSAndroid Build Coastguard Worker switch (speed) {
931*86b64dcbSAndroid Build Coastguard Worker case 1: dev->speed = LIBUSB_SPEED_LOW; break;
932*86b64dcbSAndroid Build Coastguard Worker case 12: dev->speed = LIBUSB_SPEED_FULL; break;
933*86b64dcbSAndroid Build Coastguard Worker case 480: dev->speed = LIBUSB_SPEED_HIGH; break;
934*86b64dcbSAndroid Build Coastguard Worker case 5000: dev->speed = LIBUSB_SPEED_SUPER; break;
935*86b64dcbSAndroid Build Coastguard Worker case 10000: dev->speed = LIBUSB_SPEED_SUPER_PLUS; break;
936*86b64dcbSAndroid Build Coastguard Worker case 20000: dev->speed = LIBUSB_SPEED_SUPER_PLUS_X2; break;
937*86b64dcbSAndroid Build Coastguard Worker default:
938*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ctx, "unknown device speed: %d Mbps", speed);
939*86b64dcbSAndroid Build Coastguard Worker }
940*86b64dcbSAndroid Build Coastguard Worker }
941*86b64dcbSAndroid Build Coastguard Worker } else if (wrapped_fd >= 0) {
942*86b64dcbSAndroid Build Coastguard Worker dev->speed = usbfs_get_speed(ctx, wrapped_fd);
943*86b64dcbSAndroid Build Coastguard Worker }
944*86b64dcbSAndroid Build Coastguard Worker
945*86b64dcbSAndroid Build Coastguard Worker /* cache descriptors in memory */
946*86b64dcbSAndroid Build Coastguard Worker if (sysfs_dir) {
947*86b64dcbSAndroid Build Coastguard Worker fd = open_sysfs_attr(ctx, sysfs_dir, "descriptors");
948*86b64dcbSAndroid Build Coastguard Worker } else if (wrapped_fd < 0) {
949*86b64dcbSAndroid Build Coastguard Worker fd = get_usbfs_fd(dev, O_RDONLY, 0);
950*86b64dcbSAndroid Build Coastguard Worker } else {
951*86b64dcbSAndroid Build Coastguard Worker fd = wrapped_fd;
952*86b64dcbSAndroid Build Coastguard Worker r = lseek(fd, 0, SEEK_SET);
953*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
954*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "lseek failed, errno=%d", errno);
955*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
956*86b64dcbSAndroid Build Coastguard Worker }
957*86b64dcbSAndroid Build Coastguard Worker }
958*86b64dcbSAndroid Build Coastguard Worker if (fd < 0)
959*86b64dcbSAndroid Build Coastguard Worker return fd;
960*86b64dcbSAndroid Build Coastguard Worker
961*86b64dcbSAndroid Build Coastguard Worker alloc_len = 0;
962*86b64dcbSAndroid Build Coastguard Worker do {
963*86b64dcbSAndroid Build Coastguard Worker const size_t desc_read_length = 256;
964*86b64dcbSAndroid Build Coastguard Worker uint8_t *read_ptr;
965*86b64dcbSAndroid Build Coastguard Worker
966*86b64dcbSAndroid Build Coastguard Worker alloc_len += desc_read_length;
967*86b64dcbSAndroid Build Coastguard Worker priv->descriptors = usbi_reallocf(priv->descriptors, alloc_len);
968*86b64dcbSAndroid Build Coastguard Worker if (!priv->descriptors) {
969*86b64dcbSAndroid Build Coastguard Worker if (fd != wrapped_fd)
970*86b64dcbSAndroid Build Coastguard Worker close(fd);
971*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_MEM;
972*86b64dcbSAndroid Build Coastguard Worker }
973*86b64dcbSAndroid Build Coastguard Worker read_ptr = (uint8_t *)priv->descriptors + priv->descriptors_len;
974*86b64dcbSAndroid Build Coastguard Worker /* usbfs has holes in the file */
975*86b64dcbSAndroid Build Coastguard Worker if (!sysfs_dir)
976*86b64dcbSAndroid Build Coastguard Worker memset(read_ptr, 0, desc_read_length);
977*86b64dcbSAndroid Build Coastguard Worker nb = read(fd, read_ptr, desc_read_length);
978*86b64dcbSAndroid Build Coastguard Worker if (nb < 0) {
979*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "read descriptor failed, errno=%d", errno);
980*86b64dcbSAndroid Build Coastguard Worker if (fd != wrapped_fd)
981*86b64dcbSAndroid Build Coastguard Worker close(fd);
982*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
983*86b64dcbSAndroid Build Coastguard Worker }
984*86b64dcbSAndroid Build Coastguard Worker priv->descriptors_len += (size_t)nb;
985*86b64dcbSAndroid Build Coastguard Worker } while (priv->descriptors_len == alloc_len);
986*86b64dcbSAndroid Build Coastguard Worker
987*86b64dcbSAndroid Build Coastguard Worker if (fd != wrapped_fd)
988*86b64dcbSAndroid Build Coastguard Worker close(fd);
989*86b64dcbSAndroid Build Coastguard Worker
990*86b64dcbSAndroid Build Coastguard Worker if (priv->descriptors_len < LIBUSB_DT_DEVICE_SIZE) {
991*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "short descriptor read (%zu)", priv->descriptors_len);
992*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
993*86b64dcbSAndroid Build Coastguard Worker }
994*86b64dcbSAndroid Build Coastguard Worker
995*86b64dcbSAndroid Build Coastguard Worker r = parse_config_descriptors(dev);
996*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
997*86b64dcbSAndroid Build Coastguard Worker return r;
998*86b64dcbSAndroid Build Coastguard Worker
999*86b64dcbSAndroid Build Coastguard Worker memcpy(&dev->device_descriptor, priv->descriptors, LIBUSB_DT_DEVICE_SIZE);
1000*86b64dcbSAndroid Build Coastguard Worker
1001*86b64dcbSAndroid Build Coastguard Worker if (sysfs_dir) {
1002*86b64dcbSAndroid Build Coastguard Worker /* sysfs descriptors are in bus-endian format */
1003*86b64dcbSAndroid Build Coastguard Worker usbi_localize_device_descriptor(&dev->device_descriptor);
1004*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
1005*86b64dcbSAndroid Build Coastguard Worker }
1006*86b64dcbSAndroid Build Coastguard Worker
1007*86b64dcbSAndroid Build Coastguard Worker /* cache active config */
1008*86b64dcbSAndroid Build Coastguard Worker if (wrapped_fd < 0)
1009*86b64dcbSAndroid Build Coastguard Worker fd = get_usbfs_fd(dev, O_RDWR, 1);
1010*86b64dcbSAndroid Build Coastguard Worker else
1011*86b64dcbSAndroid Build Coastguard Worker fd = wrapped_fd;
1012*86b64dcbSAndroid Build Coastguard Worker if (fd < 0) {
1013*86b64dcbSAndroid Build Coastguard Worker /* cannot send a control message to determine the active
1014*86b64dcbSAndroid Build Coastguard Worker * config. just assume the first one is active. */
1015*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ctx, "Missing rw usbfs access; cannot determine "
1016*86b64dcbSAndroid Build Coastguard Worker "active configuration descriptor");
1017*86b64dcbSAndroid Build Coastguard Worker if (priv->config_descriptors)
1018*86b64dcbSAndroid Build Coastguard Worker priv->active_config = (int)priv->config_descriptors[0].desc->bConfigurationValue;
1019*86b64dcbSAndroid Build Coastguard Worker else
1020*86b64dcbSAndroid Build Coastguard Worker priv->active_config = -1; /* No config dt */
1021*86b64dcbSAndroid Build Coastguard Worker
1022*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
1023*86b64dcbSAndroid Build Coastguard Worker }
1024*86b64dcbSAndroid Build Coastguard Worker
1025*86b64dcbSAndroid Build Coastguard Worker r = usbfs_get_active_config(dev, fd);
1026*86b64dcbSAndroid Build Coastguard Worker if (fd != wrapped_fd)
1027*86b64dcbSAndroid Build Coastguard Worker close(fd);
1028*86b64dcbSAndroid Build Coastguard Worker
1029*86b64dcbSAndroid Build Coastguard Worker return r;
1030*86b64dcbSAndroid Build Coastguard Worker }
1031*86b64dcbSAndroid Build Coastguard Worker
linux_get_parent_info(struct libusb_device * dev,const char * sysfs_dir)1032*86b64dcbSAndroid Build Coastguard Worker static int linux_get_parent_info(struct libusb_device *dev, const char *sysfs_dir)
1033*86b64dcbSAndroid Build Coastguard Worker {
1034*86b64dcbSAndroid Build Coastguard Worker struct libusb_context *ctx = DEVICE_CTX(dev);
1035*86b64dcbSAndroid Build Coastguard Worker struct libusb_device *it;
1036*86b64dcbSAndroid Build Coastguard Worker char *parent_sysfs_dir, *tmp, *end;
1037*86b64dcbSAndroid Build Coastguard Worker int ret, add_parent = 1;
1038*86b64dcbSAndroid Build Coastguard Worker
1039*86b64dcbSAndroid Build Coastguard Worker /* XXX -- can we figure out the topology when using usbfs? */
1040*86b64dcbSAndroid Build Coastguard Worker if (!sysfs_dir || !strncmp(sysfs_dir, "usb", 3)) {
1041*86b64dcbSAndroid Build Coastguard Worker /* either using usbfs or finding the parent of a root hub */
1042*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
1043*86b64dcbSAndroid Build Coastguard Worker }
1044*86b64dcbSAndroid Build Coastguard Worker
1045*86b64dcbSAndroid Build Coastguard Worker parent_sysfs_dir = strdup(sysfs_dir);
1046*86b64dcbSAndroid Build Coastguard Worker if (!parent_sysfs_dir)
1047*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_MEM;
1048*86b64dcbSAndroid Build Coastguard Worker
1049*86b64dcbSAndroid Build Coastguard Worker if ((tmp = strrchr(parent_sysfs_dir, '.')) ||
1050*86b64dcbSAndroid Build Coastguard Worker (tmp = strrchr(parent_sysfs_dir, '-'))) {
1051*86b64dcbSAndroid Build Coastguard Worker const char *start = tmp + 1;
1052*86b64dcbSAndroid Build Coastguard Worker long port_number = strtol(start, &end, 10);
1053*86b64dcbSAndroid Build Coastguard Worker if (port_number < 0 || port_number > INT_MAX || start == end || '\0' != *end) {
1054*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ctx, "Can not parse sysfs_dir: %s, unexpected parent info",
1055*86b64dcbSAndroid Build Coastguard Worker parent_sysfs_dir);
1056*86b64dcbSAndroid Build Coastguard Worker free(parent_sysfs_dir);
1057*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
1058*86b64dcbSAndroid Build Coastguard Worker } else {
1059*86b64dcbSAndroid Build Coastguard Worker dev->port_number = (int)port_number;
1060*86b64dcbSAndroid Build Coastguard Worker }
1061*86b64dcbSAndroid Build Coastguard Worker *tmp = '\0';
1062*86b64dcbSAndroid Build Coastguard Worker } else {
1063*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ctx, "Can not parse sysfs_dir: %s, no parent info",
1064*86b64dcbSAndroid Build Coastguard Worker parent_sysfs_dir);
1065*86b64dcbSAndroid Build Coastguard Worker free(parent_sysfs_dir);
1066*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
1067*86b64dcbSAndroid Build Coastguard Worker }
1068*86b64dcbSAndroid Build Coastguard Worker
1069*86b64dcbSAndroid Build Coastguard Worker /* is the parent a root hub? */
1070*86b64dcbSAndroid Build Coastguard Worker if (!strchr(parent_sysfs_dir, '-')) {
1071*86b64dcbSAndroid Build Coastguard Worker tmp = parent_sysfs_dir;
1072*86b64dcbSAndroid Build Coastguard Worker ret = asprintf(&parent_sysfs_dir, "usb%s", tmp);
1073*86b64dcbSAndroid Build Coastguard Worker free(tmp);
1074*86b64dcbSAndroid Build Coastguard Worker if (ret < 0)
1075*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_MEM;
1076*86b64dcbSAndroid Build Coastguard Worker }
1077*86b64dcbSAndroid Build Coastguard Worker
1078*86b64dcbSAndroid Build Coastguard Worker retry:
1079*86b64dcbSAndroid Build Coastguard Worker /* find the parent in the context */
1080*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_lock(&ctx->usb_devs_lock);
1081*86b64dcbSAndroid Build Coastguard Worker for_each_device(ctx, it) {
1082*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv *priv = usbi_get_device_priv(it);
1083*86b64dcbSAndroid Build Coastguard Worker
1084*86b64dcbSAndroid Build Coastguard Worker if (priv->sysfs_dir) {
1085*86b64dcbSAndroid Build Coastguard Worker if (!strcmp(priv->sysfs_dir, parent_sysfs_dir)) {
1086*86b64dcbSAndroid Build Coastguard Worker dev->parent_dev = libusb_ref_device(it);
1087*86b64dcbSAndroid Build Coastguard Worker break;
1088*86b64dcbSAndroid Build Coastguard Worker }
1089*86b64dcbSAndroid Build Coastguard Worker }
1090*86b64dcbSAndroid Build Coastguard Worker }
1091*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_unlock(&ctx->usb_devs_lock);
1092*86b64dcbSAndroid Build Coastguard Worker
1093*86b64dcbSAndroid Build Coastguard Worker if (!dev->parent_dev && add_parent) {
1094*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "parent_dev %s not enumerated yet, enumerating now",
1095*86b64dcbSAndroid Build Coastguard Worker parent_sysfs_dir);
1096*86b64dcbSAndroid Build Coastguard Worker sysfs_scan_device(ctx, parent_sysfs_dir);
1097*86b64dcbSAndroid Build Coastguard Worker add_parent = 0;
1098*86b64dcbSAndroid Build Coastguard Worker goto retry;
1099*86b64dcbSAndroid Build Coastguard Worker }
1100*86b64dcbSAndroid Build Coastguard Worker
1101*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "dev %p (%s) has parent %p (%s) port %u",
1102*86b64dcbSAndroid Build Coastguard Worker (void *) dev, sysfs_dir, (void *) dev->parent_dev,
1103*86b64dcbSAndroid Build Coastguard Worker parent_sysfs_dir, dev->port_number);
1104*86b64dcbSAndroid Build Coastguard Worker
1105*86b64dcbSAndroid Build Coastguard Worker free(parent_sysfs_dir);
1106*86b64dcbSAndroid Build Coastguard Worker
1107*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
1108*86b64dcbSAndroid Build Coastguard Worker }
1109*86b64dcbSAndroid Build Coastguard Worker
linux_enumerate_device(struct libusb_context * ctx,uint8_t busnum,uint8_t devaddr,const char * sysfs_dir)1110*86b64dcbSAndroid Build Coastguard Worker int linux_enumerate_device(struct libusb_context *ctx,
1111*86b64dcbSAndroid Build Coastguard Worker uint8_t busnum, uint8_t devaddr, const char *sysfs_dir)
1112*86b64dcbSAndroid Build Coastguard Worker {
1113*86b64dcbSAndroid Build Coastguard Worker unsigned long session_id;
1114*86b64dcbSAndroid Build Coastguard Worker struct libusb_device *dev;
1115*86b64dcbSAndroid Build Coastguard Worker int r;
1116*86b64dcbSAndroid Build Coastguard Worker
1117*86b64dcbSAndroid Build Coastguard Worker /* FIXME: session ID is not guaranteed unique as addresses can wrap and
1118*86b64dcbSAndroid Build Coastguard Worker * will be reused. instead we should add a simple sysfs attribute with
1119*86b64dcbSAndroid Build Coastguard Worker * a session ID. */
1120*86b64dcbSAndroid Build Coastguard Worker session_id = busnum << 8 | devaddr;
1121*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "busnum %u devaddr %u session_id %lu", busnum, devaddr, session_id);
1122*86b64dcbSAndroid Build Coastguard Worker
1123*86b64dcbSAndroid Build Coastguard Worker dev = usbi_get_device_by_session_id(ctx, session_id);
1124*86b64dcbSAndroid Build Coastguard Worker if (dev) {
1125*86b64dcbSAndroid Build Coastguard Worker /* device already exists in the context */
1126*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "session_id %lu already exists", session_id);
1127*86b64dcbSAndroid Build Coastguard Worker libusb_unref_device(dev);
1128*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
1129*86b64dcbSAndroid Build Coastguard Worker }
1130*86b64dcbSAndroid Build Coastguard Worker
1131*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "allocating new device for %u/%u (session %lu)",
1132*86b64dcbSAndroid Build Coastguard Worker busnum, devaddr, session_id);
1133*86b64dcbSAndroid Build Coastguard Worker dev = usbi_alloc_device(ctx, session_id);
1134*86b64dcbSAndroid Build Coastguard Worker if (!dev)
1135*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_MEM;
1136*86b64dcbSAndroid Build Coastguard Worker
1137*86b64dcbSAndroid Build Coastguard Worker r = initialize_device(dev, busnum, devaddr, sysfs_dir, -1);
1138*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
1139*86b64dcbSAndroid Build Coastguard Worker goto out;
1140*86b64dcbSAndroid Build Coastguard Worker r = usbi_sanitize_device(dev);
1141*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
1142*86b64dcbSAndroid Build Coastguard Worker goto out;
1143*86b64dcbSAndroid Build Coastguard Worker
1144*86b64dcbSAndroid Build Coastguard Worker r = linux_get_parent_info(dev, sysfs_dir);
1145*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
1146*86b64dcbSAndroid Build Coastguard Worker goto out;
1147*86b64dcbSAndroid Build Coastguard Worker out:
1148*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
1149*86b64dcbSAndroid Build Coastguard Worker libusb_unref_device(dev);
1150*86b64dcbSAndroid Build Coastguard Worker else
1151*86b64dcbSAndroid Build Coastguard Worker usbi_connect_device(dev);
1152*86b64dcbSAndroid Build Coastguard Worker
1153*86b64dcbSAndroid Build Coastguard Worker return r;
1154*86b64dcbSAndroid Build Coastguard Worker }
1155*86b64dcbSAndroid Build Coastguard Worker
linux_hotplug_enumerate(uint8_t busnum,uint8_t devaddr,const char * sys_name)1156*86b64dcbSAndroid Build Coastguard Worker void linux_hotplug_enumerate(uint8_t busnum, uint8_t devaddr, const char *sys_name)
1157*86b64dcbSAndroid Build Coastguard Worker {
1158*86b64dcbSAndroid Build Coastguard Worker struct libusb_context *ctx;
1159*86b64dcbSAndroid Build Coastguard Worker
1160*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_static_lock(&active_contexts_lock);
1161*86b64dcbSAndroid Build Coastguard Worker for_each_context(ctx) {
1162*86b64dcbSAndroid Build Coastguard Worker linux_enumerate_device(ctx, busnum, devaddr, sys_name);
1163*86b64dcbSAndroid Build Coastguard Worker }
1164*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_static_unlock(&active_contexts_lock);
1165*86b64dcbSAndroid Build Coastguard Worker }
1166*86b64dcbSAndroid Build Coastguard Worker
linux_device_disconnected(uint8_t busnum,uint8_t devaddr)1167*86b64dcbSAndroid Build Coastguard Worker void linux_device_disconnected(uint8_t busnum, uint8_t devaddr)
1168*86b64dcbSAndroid Build Coastguard Worker {
1169*86b64dcbSAndroid Build Coastguard Worker struct libusb_context *ctx;
1170*86b64dcbSAndroid Build Coastguard Worker struct libusb_device *dev;
1171*86b64dcbSAndroid Build Coastguard Worker unsigned long session_id = busnum << 8 | devaddr;
1172*86b64dcbSAndroid Build Coastguard Worker
1173*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_static_lock(&active_contexts_lock);
1174*86b64dcbSAndroid Build Coastguard Worker for_each_context(ctx) {
1175*86b64dcbSAndroid Build Coastguard Worker dev = usbi_get_device_by_session_id(ctx, session_id);
1176*86b64dcbSAndroid Build Coastguard Worker if (dev) {
1177*86b64dcbSAndroid Build Coastguard Worker usbi_disconnect_device(dev);
1178*86b64dcbSAndroid Build Coastguard Worker libusb_unref_device(dev);
1179*86b64dcbSAndroid Build Coastguard Worker } else {
1180*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "device not found for session %lx", session_id);
1181*86b64dcbSAndroid Build Coastguard Worker }
1182*86b64dcbSAndroid Build Coastguard Worker }
1183*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_static_unlock(&active_contexts_lock);
1184*86b64dcbSAndroid Build Coastguard Worker }
1185*86b64dcbSAndroid Build Coastguard Worker
1186*86b64dcbSAndroid Build Coastguard Worker #if !defined(HAVE_LIBUDEV)
parse_u8(const char * str,uint8_t * val_p)1187*86b64dcbSAndroid Build Coastguard Worker static int parse_u8(const char *str, uint8_t *val_p)
1188*86b64dcbSAndroid Build Coastguard Worker {
1189*86b64dcbSAndroid Build Coastguard Worker char *endptr;
1190*86b64dcbSAndroid Build Coastguard Worker long num;
1191*86b64dcbSAndroid Build Coastguard Worker
1192*86b64dcbSAndroid Build Coastguard Worker errno = 0;
1193*86b64dcbSAndroid Build Coastguard Worker num = strtol(str, &endptr, 10);
1194*86b64dcbSAndroid Build Coastguard Worker if (num < 0 || num > UINT8_MAX || errno)
1195*86b64dcbSAndroid Build Coastguard Worker return 0;
1196*86b64dcbSAndroid Build Coastguard Worker if (endptr == str || *endptr != '\0')
1197*86b64dcbSAndroid Build Coastguard Worker return 0;
1198*86b64dcbSAndroid Build Coastguard Worker
1199*86b64dcbSAndroid Build Coastguard Worker *val_p = (uint8_t)num;
1200*86b64dcbSAndroid Build Coastguard Worker return 1;
1201*86b64dcbSAndroid Build Coastguard Worker }
1202*86b64dcbSAndroid Build Coastguard Worker
1203*86b64dcbSAndroid Build Coastguard Worker /* open a bus directory and adds all discovered devices to the context */
usbfs_scan_busdir(struct libusb_context * ctx,uint8_t busnum)1204*86b64dcbSAndroid Build Coastguard Worker static int usbfs_scan_busdir(struct libusb_context *ctx, uint8_t busnum)
1205*86b64dcbSAndroid Build Coastguard Worker {
1206*86b64dcbSAndroid Build Coastguard Worker DIR *dir;
1207*86b64dcbSAndroid Build Coastguard Worker char dirpath[20];
1208*86b64dcbSAndroid Build Coastguard Worker struct dirent *entry;
1209*86b64dcbSAndroid Build Coastguard Worker int r = LIBUSB_ERROR_IO;
1210*86b64dcbSAndroid Build Coastguard Worker
1211*86b64dcbSAndroid Build Coastguard Worker snprintf(dirpath, sizeof(dirpath), USB_DEVTMPFS_PATH "/%03u", busnum);
1212*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "%s", dirpath);
1213*86b64dcbSAndroid Build Coastguard Worker dir = opendir(dirpath);
1214*86b64dcbSAndroid Build Coastguard Worker if (!dir) {
1215*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "opendir '%s' failed, errno=%d", dirpath, errno);
1216*86b64dcbSAndroid Build Coastguard Worker /* FIXME: should handle valid race conditions like hub unplugged
1217*86b64dcbSAndroid Build Coastguard Worker * during directory iteration - this is not an error */
1218*86b64dcbSAndroid Build Coastguard Worker return r;
1219*86b64dcbSAndroid Build Coastguard Worker }
1220*86b64dcbSAndroid Build Coastguard Worker
1221*86b64dcbSAndroid Build Coastguard Worker while ((entry = readdir(dir))) {
1222*86b64dcbSAndroid Build Coastguard Worker uint8_t devaddr;
1223*86b64dcbSAndroid Build Coastguard Worker
1224*86b64dcbSAndroid Build Coastguard Worker if (entry->d_name[0] == '.')
1225*86b64dcbSAndroid Build Coastguard Worker continue;
1226*86b64dcbSAndroid Build Coastguard Worker
1227*86b64dcbSAndroid Build Coastguard Worker if (!parse_u8(entry->d_name, &devaddr)) {
1228*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "unknown dir entry %s", entry->d_name);
1229*86b64dcbSAndroid Build Coastguard Worker continue;
1230*86b64dcbSAndroid Build Coastguard Worker }
1231*86b64dcbSAndroid Build Coastguard Worker
1232*86b64dcbSAndroid Build Coastguard Worker if (linux_enumerate_device(ctx, busnum, devaddr, NULL)) {
1233*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "failed to enumerate dir entry %s", entry->d_name);
1234*86b64dcbSAndroid Build Coastguard Worker continue;
1235*86b64dcbSAndroid Build Coastguard Worker }
1236*86b64dcbSAndroid Build Coastguard Worker
1237*86b64dcbSAndroid Build Coastguard Worker r = 0;
1238*86b64dcbSAndroid Build Coastguard Worker }
1239*86b64dcbSAndroid Build Coastguard Worker
1240*86b64dcbSAndroid Build Coastguard Worker closedir(dir);
1241*86b64dcbSAndroid Build Coastguard Worker return r;
1242*86b64dcbSAndroid Build Coastguard Worker }
1243*86b64dcbSAndroid Build Coastguard Worker
usbfs_get_device_list(struct libusb_context * ctx)1244*86b64dcbSAndroid Build Coastguard Worker static int usbfs_get_device_list(struct libusb_context *ctx)
1245*86b64dcbSAndroid Build Coastguard Worker {
1246*86b64dcbSAndroid Build Coastguard Worker struct dirent *entry;
1247*86b64dcbSAndroid Build Coastguard Worker DIR *buses;
1248*86b64dcbSAndroid Build Coastguard Worker uint8_t busnum, devaddr;
1249*86b64dcbSAndroid Build Coastguard Worker int r = 0;
1250*86b64dcbSAndroid Build Coastguard Worker
1251*86b64dcbSAndroid Build Coastguard Worker if (usbdev_names)
1252*86b64dcbSAndroid Build Coastguard Worker buses = opendir(USBDEV_PATH);
1253*86b64dcbSAndroid Build Coastguard Worker else
1254*86b64dcbSAndroid Build Coastguard Worker buses = opendir(USB_DEVTMPFS_PATH);
1255*86b64dcbSAndroid Build Coastguard Worker
1256*86b64dcbSAndroid Build Coastguard Worker if (!buses) {
1257*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "opendir buses failed, errno=%d", errno);
1258*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
1259*86b64dcbSAndroid Build Coastguard Worker }
1260*86b64dcbSAndroid Build Coastguard Worker
1261*86b64dcbSAndroid Build Coastguard Worker while ((entry = readdir(buses))) {
1262*86b64dcbSAndroid Build Coastguard Worker if (entry->d_name[0] == '.')
1263*86b64dcbSAndroid Build Coastguard Worker continue;
1264*86b64dcbSAndroid Build Coastguard Worker
1265*86b64dcbSAndroid Build Coastguard Worker if (usbdev_names) {
1266*86b64dcbSAndroid Build Coastguard Worker if (!is_usbdev_entry(entry->d_name, &busnum, &devaddr))
1267*86b64dcbSAndroid Build Coastguard Worker continue;
1268*86b64dcbSAndroid Build Coastguard Worker
1269*86b64dcbSAndroid Build Coastguard Worker r = linux_enumerate_device(ctx, busnum, devaddr, NULL);
1270*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1271*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "failed to enumerate dir entry %s", entry->d_name);
1272*86b64dcbSAndroid Build Coastguard Worker continue;
1273*86b64dcbSAndroid Build Coastguard Worker }
1274*86b64dcbSAndroid Build Coastguard Worker } else {
1275*86b64dcbSAndroid Build Coastguard Worker if (!parse_u8(entry->d_name, &busnum)) {
1276*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "unknown dir entry %s", entry->d_name);
1277*86b64dcbSAndroid Build Coastguard Worker continue;
1278*86b64dcbSAndroid Build Coastguard Worker }
1279*86b64dcbSAndroid Build Coastguard Worker
1280*86b64dcbSAndroid Build Coastguard Worker r = usbfs_scan_busdir(ctx, busnum);
1281*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
1282*86b64dcbSAndroid Build Coastguard Worker break;
1283*86b64dcbSAndroid Build Coastguard Worker }
1284*86b64dcbSAndroid Build Coastguard Worker }
1285*86b64dcbSAndroid Build Coastguard Worker
1286*86b64dcbSAndroid Build Coastguard Worker closedir(buses);
1287*86b64dcbSAndroid Build Coastguard Worker return r;
1288*86b64dcbSAndroid Build Coastguard Worker
1289*86b64dcbSAndroid Build Coastguard Worker }
1290*86b64dcbSAndroid Build Coastguard Worker
sysfs_get_device_list(struct libusb_context * ctx)1291*86b64dcbSAndroid Build Coastguard Worker static int sysfs_get_device_list(struct libusb_context *ctx)
1292*86b64dcbSAndroid Build Coastguard Worker {
1293*86b64dcbSAndroid Build Coastguard Worker DIR *devices = opendir(SYSFS_DEVICE_PATH);
1294*86b64dcbSAndroid Build Coastguard Worker struct dirent *entry;
1295*86b64dcbSAndroid Build Coastguard Worker int num_devices = 0;
1296*86b64dcbSAndroid Build Coastguard Worker int num_enumerated = 0;
1297*86b64dcbSAndroid Build Coastguard Worker
1298*86b64dcbSAndroid Build Coastguard Worker if (!devices) {
1299*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "opendir devices failed, errno=%d", errno);
1300*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
1301*86b64dcbSAndroid Build Coastguard Worker }
1302*86b64dcbSAndroid Build Coastguard Worker
1303*86b64dcbSAndroid Build Coastguard Worker while ((entry = readdir(devices))) {
1304*86b64dcbSAndroid Build Coastguard Worker if ((!isdigit(entry->d_name[0]) && strncmp(entry->d_name, "usb", 3))
1305*86b64dcbSAndroid Build Coastguard Worker || strchr(entry->d_name, ':'))
1306*86b64dcbSAndroid Build Coastguard Worker continue;
1307*86b64dcbSAndroid Build Coastguard Worker
1308*86b64dcbSAndroid Build Coastguard Worker num_devices++;
1309*86b64dcbSAndroid Build Coastguard Worker
1310*86b64dcbSAndroid Build Coastguard Worker if (sysfs_scan_device(ctx, entry->d_name)) {
1311*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "failed to enumerate dir entry %s", entry->d_name);
1312*86b64dcbSAndroid Build Coastguard Worker continue;
1313*86b64dcbSAndroid Build Coastguard Worker }
1314*86b64dcbSAndroid Build Coastguard Worker
1315*86b64dcbSAndroid Build Coastguard Worker num_enumerated++;
1316*86b64dcbSAndroid Build Coastguard Worker }
1317*86b64dcbSAndroid Build Coastguard Worker
1318*86b64dcbSAndroid Build Coastguard Worker closedir(devices);
1319*86b64dcbSAndroid Build Coastguard Worker
1320*86b64dcbSAndroid Build Coastguard Worker /* successful if at least one device was enumerated or no devices were found */
1321*86b64dcbSAndroid Build Coastguard Worker if (num_enumerated || !num_devices)
1322*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
1323*86b64dcbSAndroid Build Coastguard Worker else
1324*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
1325*86b64dcbSAndroid Build Coastguard Worker }
1326*86b64dcbSAndroid Build Coastguard Worker
linux_default_scan_devices(struct libusb_context * ctx)1327*86b64dcbSAndroid Build Coastguard Worker static int linux_default_scan_devices(struct libusb_context *ctx)
1328*86b64dcbSAndroid Build Coastguard Worker {
1329*86b64dcbSAndroid Build Coastguard Worker /* we can retrieve device list and descriptors from sysfs or usbfs.
1330*86b64dcbSAndroid Build Coastguard Worker * sysfs is preferable, because if we use usbfs we end up resuming
1331*86b64dcbSAndroid Build Coastguard Worker * any autosuspended USB devices. however, sysfs is not available
1332*86b64dcbSAndroid Build Coastguard Worker * everywhere, so we need a usbfs fallback too.
1333*86b64dcbSAndroid Build Coastguard Worker */
1334*86b64dcbSAndroid Build Coastguard Worker if (sysfs_available)
1335*86b64dcbSAndroid Build Coastguard Worker return sysfs_get_device_list(ctx);
1336*86b64dcbSAndroid Build Coastguard Worker else
1337*86b64dcbSAndroid Build Coastguard Worker return usbfs_get_device_list(ctx);
1338*86b64dcbSAndroid Build Coastguard Worker }
1339*86b64dcbSAndroid Build Coastguard Worker #endif
1340*86b64dcbSAndroid Build Coastguard Worker
initialize_handle(struct libusb_device_handle * handle,int fd)1341*86b64dcbSAndroid Build Coastguard Worker static int initialize_handle(struct libusb_device_handle *handle, int fd)
1342*86b64dcbSAndroid Build Coastguard Worker {
1343*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1344*86b64dcbSAndroid Build Coastguard Worker int r;
1345*86b64dcbSAndroid Build Coastguard Worker
1346*86b64dcbSAndroid Build Coastguard Worker hpriv->fd = fd;
1347*86b64dcbSAndroid Build Coastguard Worker
1348*86b64dcbSAndroid Build Coastguard Worker r = ioctl(fd, IOCTL_USBFS_GET_CAPABILITIES, &hpriv->caps);
1349*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1350*86b64dcbSAndroid Build Coastguard Worker if (errno == ENOTTY)
1351*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(HANDLE_CTX(handle), "getcap not available");
1352*86b64dcbSAndroid Build Coastguard Worker else
1353*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "getcap failed, errno=%d", errno);
1354*86b64dcbSAndroid Build Coastguard Worker hpriv->caps = USBFS_CAP_BULK_CONTINUATION;
1355*86b64dcbSAndroid Build Coastguard Worker }
1356*86b64dcbSAndroid Build Coastguard Worker
1357*86b64dcbSAndroid Build Coastguard Worker return usbi_add_event_source(HANDLE_CTX(handle), hpriv->fd, POLLOUT);
1358*86b64dcbSAndroid Build Coastguard Worker }
1359*86b64dcbSAndroid Build Coastguard Worker
op_wrap_sys_device(struct libusb_context * ctx,struct libusb_device_handle * handle,intptr_t sys_dev)1360*86b64dcbSAndroid Build Coastguard Worker static int op_wrap_sys_device(struct libusb_context *ctx,
1361*86b64dcbSAndroid Build Coastguard Worker struct libusb_device_handle *handle, intptr_t sys_dev)
1362*86b64dcbSAndroid Build Coastguard Worker {
1363*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1364*86b64dcbSAndroid Build Coastguard Worker int fd = (int)sys_dev;
1365*86b64dcbSAndroid Build Coastguard Worker uint8_t busnum, devaddr;
1366*86b64dcbSAndroid Build Coastguard Worker struct usbfs_connectinfo ci;
1367*86b64dcbSAndroid Build Coastguard Worker struct libusb_device *dev;
1368*86b64dcbSAndroid Build Coastguard Worker int r;
1369*86b64dcbSAndroid Build Coastguard Worker
1370*86b64dcbSAndroid Build Coastguard Worker r = linux_get_device_address(ctx, 1, &busnum, &devaddr, NULL, NULL, fd);
1371*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1372*86b64dcbSAndroid Build Coastguard Worker r = ioctl(fd, IOCTL_USBFS_CONNECTINFO, &ci);
1373*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1374*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "connectinfo failed, errno=%d", errno);
1375*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
1376*86b64dcbSAndroid Build Coastguard Worker }
1377*86b64dcbSAndroid Build Coastguard Worker /* There is no ioctl to get the bus number. We choose 0 here
1378*86b64dcbSAndroid Build Coastguard Worker * as linux starts numbering buses from 1. */
1379*86b64dcbSAndroid Build Coastguard Worker busnum = 0;
1380*86b64dcbSAndroid Build Coastguard Worker devaddr = ci.devnum;
1381*86b64dcbSAndroid Build Coastguard Worker }
1382*86b64dcbSAndroid Build Coastguard Worker
1383*86b64dcbSAndroid Build Coastguard Worker /* Session id is unused as we do not add the device to the list of
1384*86b64dcbSAndroid Build Coastguard Worker * connected devices. */
1385*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ctx, "allocating new device for fd %d", fd);
1386*86b64dcbSAndroid Build Coastguard Worker dev = usbi_alloc_device(ctx, 0);
1387*86b64dcbSAndroid Build Coastguard Worker if (!dev)
1388*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_MEM;
1389*86b64dcbSAndroid Build Coastguard Worker
1390*86b64dcbSAndroid Build Coastguard Worker r = initialize_device(dev, busnum, devaddr, NULL, fd);
1391*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
1392*86b64dcbSAndroid Build Coastguard Worker goto out;
1393*86b64dcbSAndroid Build Coastguard Worker r = usbi_sanitize_device(dev);
1394*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
1395*86b64dcbSAndroid Build Coastguard Worker goto out;
1396*86b64dcbSAndroid Build Coastguard Worker /* Consider the device as connected, but do not add it to the managed
1397*86b64dcbSAndroid Build Coastguard Worker * device list. */
1398*86b64dcbSAndroid Build Coastguard Worker usbi_atomic_store(&dev->attached, 1);
1399*86b64dcbSAndroid Build Coastguard Worker handle->dev = dev;
1400*86b64dcbSAndroid Build Coastguard Worker
1401*86b64dcbSAndroid Build Coastguard Worker r = initialize_handle(handle, fd);
1402*86b64dcbSAndroid Build Coastguard Worker hpriv->fd_keep = 1;
1403*86b64dcbSAndroid Build Coastguard Worker
1404*86b64dcbSAndroid Build Coastguard Worker out:
1405*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
1406*86b64dcbSAndroid Build Coastguard Worker libusb_unref_device(dev);
1407*86b64dcbSAndroid Build Coastguard Worker return r;
1408*86b64dcbSAndroid Build Coastguard Worker }
1409*86b64dcbSAndroid Build Coastguard Worker
op_open(struct libusb_device_handle * handle)1410*86b64dcbSAndroid Build Coastguard Worker static int op_open(struct libusb_device_handle *handle)
1411*86b64dcbSAndroid Build Coastguard Worker {
1412*86b64dcbSAndroid Build Coastguard Worker int fd, r;
1413*86b64dcbSAndroid Build Coastguard Worker
1414*86b64dcbSAndroid Build Coastguard Worker fd = get_usbfs_fd(handle->dev, O_RDWR, 0);
1415*86b64dcbSAndroid Build Coastguard Worker if (fd < 0) {
1416*86b64dcbSAndroid Build Coastguard Worker if (fd == LIBUSB_ERROR_NO_DEVICE) {
1417*86b64dcbSAndroid Build Coastguard Worker /* device will still be marked as attached if hotplug monitor thread
1418*86b64dcbSAndroid Build Coastguard Worker * hasn't processed remove event yet */
1419*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_static_lock(&linux_hotplug_lock);
1420*86b64dcbSAndroid Build Coastguard Worker if (usbi_atomic_load(&handle->dev->attached)) {
1421*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(HANDLE_CTX(handle), "open failed with no device, but device still attached");
1422*86b64dcbSAndroid Build Coastguard Worker linux_device_disconnected(handle->dev->bus_number,
1423*86b64dcbSAndroid Build Coastguard Worker handle->dev->device_address);
1424*86b64dcbSAndroid Build Coastguard Worker }
1425*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_static_unlock(&linux_hotplug_lock);
1426*86b64dcbSAndroid Build Coastguard Worker }
1427*86b64dcbSAndroid Build Coastguard Worker return fd;
1428*86b64dcbSAndroid Build Coastguard Worker }
1429*86b64dcbSAndroid Build Coastguard Worker
1430*86b64dcbSAndroid Build Coastguard Worker r = initialize_handle(handle, fd);
1431*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
1432*86b64dcbSAndroid Build Coastguard Worker close(fd);
1433*86b64dcbSAndroid Build Coastguard Worker
1434*86b64dcbSAndroid Build Coastguard Worker return r;
1435*86b64dcbSAndroid Build Coastguard Worker }
1436*86b64dcbSAndroid Build Coastguard Worker
op_close(struct libusb_device_handle * dev_handle)1437*86b64dcbSAndroid Build Coastguard Worker static void op_close(struct libusb_device_handle *dev_handle)
1438*86b64dcbSAndroid Build Coastguard Worker {
1439*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(dev_handle);
1440*86b64dcbSAndroid Build Coastguard Worker
1441*86b64dcbSAndroid Build Coastguard Worker /* fd may have already been removed by POLLERR condition in op_handle_events() */
1442*86b64dcbSAndroid Build Coastguard Worker if (!hpriv->fd_removed)
1443*86b64dcbSAndroid Build Coastguard Worker usbi_remove_event_source(HANDLE_CTX(dev_handle), hpriv->fd);
1444*86b64dcbSAndroid Build Coastguard Worker if (!hpriv->fd_keep)
1445*86b64dcbSAndroid Build Coastguard Worker close(hpriv->fd);
1446*86b64dcbSAndroid Build Coastguard Worker }
1447*86b64dcbSAndroid Build Coastguard Worker
op_get_configuration(struct libusb_device_handle * handle,uint8_t * config)1448*86b64dcbSAndroid Build Coastguard Worker static int op_get_configuration(struct libusb_device_handle *handle,
1449*86b64dcbSAndroid Build Coastguard Worker uint8_t *config)
1450*86b64dcbSAndroid Build Coastguard Worker {
1451*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv *priv = usbi_get_device_priv(handle->dev);
1452*86b64dcbSAndroid Build Coastguard Worker int active_config = -1; /* to please compiler */
1453*86b64dcbSAndroid Build Coastguard Worker int r;
1454*86b64dcbSAndroid Build Coastguard Worker
1455*86b64dcbSAndroid Build Coastguard Worker if (priv->sysfs_dir) {
1456*86b64dcbSAndroid Build Coastguard Worker r = sysfs_get_active_config(handle->dev, &active_config);
1457*86b64dcbSAndroid Build Coastguard Worker } else {
1458*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1459*86b64dcbSAndroid Build Coastguard Worker
1460*86b64dcbSAndroid Build Coastguard Worker r = usbfs_get_active_config(handle->dev, hpriv->fd);
1461*86b64dcbSAndroid Build Coastguard Worker if (r == LIBUSB_SUCCESS)
1462*86b64dcbSAndroid Build Coastguard Worker active_config = priv->active_config;
1463*86b64dcbSAndroid Build Coastguard Worker }
1464*86b64dcbSAndroid Build Coastguard Worker if (r < 0)
1465*86b64dcbSAndroid Build Coastguard Worker return r;
1466*86b64dcbSAndroid Build Coastguard Worker
1467*86b64dcbSAndroid Build Coastguard Worker if (active_config == -1) {
1468*86b64dcbSAndroid Build Coastguard Worker usbi_warn(HANDLE_CTX(handle), "device unconfigured");
1469*86b64dcbSAndroid Build Coastguard Worker active_config = 0;
1470*86b64dcbSAndroid Build Coastguard Worker }
1471*86b64dcbSAndroid Build Coastguard Worker
1472*86b64dcbSAndroid Build Coastguard Worker *config = (uint8_t)active_config;
1473*86b64dcbSAndroid Build Coastguard Worker
1474*86b64dcbSAndroid Build Coastguard Worker return 0;
1475*86b64dcbSAndroid Build Coastguard Worker }
1476*86b64dcbSAndroid Build Coastguard Worker
op_set_configuration(struct libusb_device_handle * handle,int config)1477*86b64dcbSAndroid Build Coastguard Worker static int op_set_configuration(struct libusb_device_handle *handle, int config)
1478*86b64dcbSAndroid Build Coastguard Worker {
1479*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv *priv = usbi_get_device_priv(handle->dev);
1480*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1481*86b64dcbSAndroid Build Coastguard Worker int fd = hpriv->fd;
1482*86b64dcbSAndroid Build Coastguard Worker int r = ioctl(fd, IOCTL_USBFS_SETCONFIGURATION, &config);
1483*86b64dcbSAndroid Build Coastguard Worker
1484*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1485*86b64dcbSAndroid Build Coastguard Worker if (errno == EINVAL)
1486*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
1487*86b64dcbSAndroid Build Coastguard Worker else if (errno == EBUSY)
1488*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_BUSY;
1489*86b64dcbSAndroid Build Coastguard Worker else if (errno == ENODEV)
1490*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
1491*86b64dcbSAndroid Build Coastguard Worker
1492*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "set configuration failed, errno=%d", errno);
1493*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
1494*86b64dcbSAndroid Build Coastguard Worker }
1495*86b64dcbSAndroid Build Coastguard Worker
1496*86b64dcbSAndroid Build Coastguard Worker /* if necessary, update our cached active config descriptor */
1497*86b64dcbSAndroid Build Coastguard Worker if (!priv->sysfs_dir) {
1498*86b64dcbSAndroid Build Coastguard Worker if (config == 0 && !dev_has_config0(handle->dev))
1499*86b64dcbSAndroid Build Coastguard Worker config = -1;
1500*86b64dcbSAndroid Build Coastguard Worker
1501*86b64dcbSAndroid Build Coastguard Worker priv->active_config = config;
1502*86b64dcbSAndroid Build Coastguard Worker }
1503*86b64dcbSAndroid Build Coastguard Worker
1504*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
1505*86b64dcbSAndroid Build Coastguard Worker }
1506*86b64dcbSAndroid Build Coastguard Worker
claim_interface(struct libusb_device_handle * handle,unsigned int iface)1507*86b64dcbSAndroid Build Coastguard Worker static int claim_interface(struct libusb_device_handle *handle, unsigned int iface)
1508*86b64dcbSAndroid Build Coastguard Worker {
1509*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1510*86b64dcbSAndroid Build Coastguard Worker int fd = hpriv->fd;
1511*86b64dcbSAndroid Build Coastguard Worker int r = ioctl(fd, IOCTL_USBFS_CLAIMINTERFACE, &iface);
1512*86b64dcbSAndroid Build Coastguard Worker
1513*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1514*86b64dcbSAndroid Build Coastguard Worker if (errno == ENOENT)
1515*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
1516*86b64dcbSAndroid Build Coastguard Worker else if (errno == EBUSY)
1517*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_BUSY;
1518*86b64dcbSAndroid Build Coastguard Worker else if (errno == ENODEV)
1519*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
1520*86b64dcbSAndroid Build Coastguard Worker
1521*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "claim interface failed, errno=%d", errno);
1522*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
1523*86b64dcbSAndroid Build Coastguard Worker }
1524*86b64dcbSAndroid Build Coastguard Worker return 0;
1525*86b64dcbSAndroid Build Coastguard Worker }
1526*86b64dcbSAndroid Build Coastguard Worker
release_interface(struct libusb_device_handle * handle,unsigned int iface)1527*86b64dcbSAndroid Build Coastguard Worker static int release_interface(struct libusb_device_handle *handle, unsigned int iface)
1528*86b64dcbSAndroid Build Coastguard Worker {
1529*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1530*86b64dcbSAndroid Build Coastguard Worker int fd = hpriv->fd;
1531*86b64dcbSAndroid Build Coastguard Worker int r = ioctl(fd, IOCTL_USBFS_RELEASEINTERFACE, &iface);
1532*86b64dcbSAndroid Build Coastguard Worker
1533*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1534*86b64dcbSAndroid Build Coastguard Worker if (errno == ENODEV)
1535*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
1536*86b64dcbSAndroid Build Coastguard Worker
1537*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "release interface failed, errno=%d", errno);
1538*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
1539*86b64dcbSAndroid Build Coastguard Worker }
1540*86b64dcbSAndroid Build Coastguard Worker return 0;
1541*86b64dcbSAndroid Build Coastguard Worker }
1542*86b64dcbSAndroid Build Coastguard Worker
op_set_interface(struct libusb_device_handle * handle,uint8_t interface,uint8_t altsetting)1543*86b64dcbSAndroid Build Coastguard Worker static int op_set_interface(struct libusb_device_handle *handle, uint8_t interface,
1544*86b64dcbSAndroid Build Coastguard Worker uint8_t altsetting)
1545*86b64dcbSAndroid Build Coastguard Worker {
1546*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1547*86b64dcbSAndroid Build Coastguard Worker int fd = hpriv->fd;
1548*86b64dcbSAndroid Build Coastguard Worker struct usbfs_setinterface setintf;
1549*86b64dcbSAndroid Build Coastguard Worker int r;
1550*86b64dcbSAndroid Build Coastguard Worker
1551*86b64dcbSAndroid Build Coastguard Worker setintf.interface = interface;
1552*86b64dcbSAndroid Build Coastguard Worker setintf.altsetting = altsetting;
1553*86b64dcbSAndroid Build Coastguard Worker r = ioctl(fd, IOCTL_USBFS_SETINTERFACE, &setintf);
1554*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1555*86b64dcbSAndroid Build Coastguard Worker if (errno == EINVAL)
1556*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
1557*86b64dcbSAndroid Build Coastguard Worker else if (errno == ENODEV)
1558*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
1559*86b64dcbSAndroid Build Coastguard Worker
1560*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "set interface failed, errno=%d", errno);
1561*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
1562*86b64dcbSAndroid Build Coastguard Worker }
1563*86b64dcbSAndroid Build Coastguard Worker
1564*86b64dcbSAndroid Build Coastguard Worker return 0;
1565*86b64dcbSAndroid Build Coastguard Worker }
1566*86b64dcbSAndroid Build Coastguard Worker
op_clear_halt(struct libusb_device_handle * handle,unsigned char endpoint)1567*86b64dcbSAndroid Build Coastguard Worker static int op_clear_halt(struct libusb_device_handle *handle,
1568*86b64dcbSAndroid Build Coastguard Worker unsigned char endpoint)
1569*86b64dcbSAndroid Build Coastguard Worker {
1570*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1571*86b64dcbSAndroid Build Coastguard Worker int fd = hpriv->fd;
1572*86b64dcbSAndroid Build Coastguard Worker unsigned int _endpoint = endpoint;
1573*86b64dcbSAndroid Build Coastguard Worker int r = ioctl(fd, IOCTL_USBFS_CLEAR_HALT, &_endpoint);
1574*86b64dcbSAndroid Build Coastguard Worker
1575*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1576*86b64dcbSAndroid Build Coastguard Worker if (errno == ENOENT)
1577*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
1578*86b64dcbSAndroid Build Coastguard Worker else if (errno == ENODEV)
1579*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
1580*86b64dcbSAndroid Build Coastguard Worker
1581*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "clear halt failed, errno=%d", errno);
1582*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
1583*86b64dcbSAndroid Build Coastguard Worker }
1584*86b64dcbSAndroid Build Coastguard Worker
1585*86b64dcbSAndroid Build Coastguard Worker return 0;
1586*86b64dcbSAndroid Build Coastguard Worker }
1587*86b64dcbSAndroid Build Coastguard Worker
op_reset_device(struct libusb_device_handle * handle)1588*86b64dcbSAndroid Build Coastguard Worker static int op_reset_device(struct libusb_device_handle *handle)
1589*86b64dcbSAndroid Build Coastguard Worker {
1590*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1591*86b64dcbSAndroid Build Coastguard Worker int fd = hpriv->fd;
1592*86b64dcbSAndroid Build Coastguard Worker int r, ret = 0;
1593*86b64dcbSAndroid Build Coastguard Worker uint8_t i;
1594*86b64dcbSAndroid Build Coastguard Worker
1595*86b64dcbSAndroid Build Coastguard Worker /* Doing a device reset will cause the usbfs driver to get unbound
1596*86b64dcbSAndroid Build Coastguard Worker * from any interfaces it is bound to. By voluntarily unbinding
1597*86b64dcbSAndroid Build Coastguard Worker * the usbfs driver ourself, we stop the kernel from rebinding
1598*86b64dcbSAndroid Build Coastguard Worker * the interface after reset (which would end up with the interface
1599*86b64dcbSAndroid Build Coastguard Worker * getting bound to the in kernel driver if any). */
1600*86b64dcbSAndroid Build Coastguard Worker for (i = 0; i < USB_MAXINTERFACES; i++) {
1601*86b64dcbSAndroid Build Coastguard Worker if (handle->claimed_interfaces & (1UL << i))
1602*86b64dcbSAndroid Build Coastguard Worker release_interface(handle, i);
1603*86b64dcbSAndroid Build Coastguard Worker }
1604*86b64dcbSAndroid Build Coastguard Worker
1605*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_lock(&handle->lock);
1606*86b64dcbSAndroid Build Coastguard Worker r = ioctl(fd, IOCTL_USBFS_RESET, NULL);
1607*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1608*86b64dcbSAndroid Build Coastguard Worker if (errno == ENODEV) {
1609*86b64dcbSAndroid Build Coastguard Worker ret = LIBUSB_ERROR_NOT_FOUND;
1610*86b64dcbSAndroid Build Coastguard Worker goto out;
1611*86b64dcbSAndroid Build Coastguard Worker }
1612*86b64dcbSAndroid Build Coastguard Worker
1613*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "reset failed, errno=%d", errno);
1614*86b64dcbSAndroid Build Coastguard Worker ret = LIBUSB_ERROR_OTHER;
1615*86b64dcbSAndroid Build Coastguard Worker goto out;
1616*86b64dcbSAndroid Build Coastguard Worker }
1617*86b64dcbSAndroid Build Coastguard Worker
1618*86b64dcbSAndroid Build Coastguard Worker /* And re-claim any interfaces which were claimed before the reset */
1619*86b64dcbSAndroid Build Coastguard Worker for (i = 0; i < USB_MAXINTERFACES; i++) {
1620*86b64dcbSAndroid Build Coastguard Worker if (!(handle->claimed_interfaces & (1UL << i)))
1621*86b64dcbSAndroid Build Coastguard Worker continue;
1622*86b64dcbSAndroid Build Coastguard Worker /*
1623*86b64dcbSAndroid Build Coastguard Worker * A driver may have completed modprobing during
1624*86b64dcbSAndroid Build Coastguard Worker * IOCTL_USBFS_RESET, and bound itself as soon as
1625*86b64dcbSAndroid Build Coastguard Worker * IOCTL_USBFS_RESET released the device lock
1626*86b64dcbSAndroid Build Coastguard Worker */
1627*86b64dcbSAndroid Build Coastguard Worker r = detach_kernel_driver_and_claim(handle, i);
1628*86b64dcbSAndroid Build Coastguard Worker if (r) {
1629*86b64dcbSAndroid Build Coastguard Worker usbi_warn(HANDLE_CTX(handle), "failed to re-claim interface %u after reset: %s",
1630*86b64dcbSAndroid Build Coastguard Worker i, libusb_error_name(r));
1631*86b64dcbSAndroid Build Coastguard Worker handle->claimed_interfaces &= ~(1UL << i);
1632*86b64dcbSAndroid Build Coastguard Worker ret = LIBUSB_ERROR_NOT_FOUND;
1633*86b64dcbSAndroid Build Coastguard Worker }
1634*86b64dcbSAndroid Build Coastguard Worker }
1635*86b64dcbSAndroid Build Coastguard Worker out:
1636*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_unlock(&handle->lock);
1637*86b64dcbSAndroid Build Coastguard Worker return ret;
1638*86b64dcbSAndroid Build Coastguard Worker }
1639*86b64dcbSAndroid Build Coastguard Worker
do_streams_ioctl(struct libusb_device_handle * handle,unsigned long req,uint32_t num_streams,unsigned char * endpoints,int num_endpoints)1640*86b64dcbSAndroid Build Coastguard Worker static int do_streams_ioctl(struct libusb_device_handle *handle,
1641*86b64dcbSAndroid Build Coastguard Worker unsigned long req, uint32_t num_streams, unsigned char *endpoints,
1642*86b64dcbSAndroid Build Coastguard Worker int num_endpoints)
1643*86b64dcbSAndroid Build Coastguard Worker {
1644*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1645*86b64dcbSAndroid Build Coastguard Worker int r, fd = hpriv->fd;
1646*86b64dcbSAndroid Build Coastguard Worker struct usbfs_streams *streams;
1647*86b64dcbSAndroid Build Coastguard Worker
1648*86b64dcbSAndroid Build Coastguard Worker if (num_endpoints > 30) /* Max 15 in + 15 out eps */
1649*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_INVALID_PARAM;
1650*86b64dcbSAndroid Build Coastguard Worker
1651*86b64dcbSAndroid Build Coastguard Worker streams = malloc(sizeof(*streams) + num_endpoints);
1652*86b64dcbSAndroid Build Coastguard Worker if (!streams)
1653*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_MEM;
1654*86b64dcbSAndroid Build Coastguard Worker
1655*86b64dcbSAndroid Build Coastguard Worker streams->num_streams = num_streams;
1656*86b64dcbSAndroid Build Coastguard Worker streams->num_eps = num_endpoints;
1657*86b64dcbSAndroid Build Coastguard Worker memcpy(streams->eps, endpoints, num_endpoints);
1658*86b64dcbSAndroid Build Coastguard Worker
1659*86b64dcbSAndroid Build Coastguard Worker r = ioctl(fd, req, streams);
1660*86b64dcbSAndroid Build Coastguard Worker
1661*86b64dcbSAndroid Build Coastguard Worker free(streams);
1662*86b64dcbSAndroid Build Coastguard Worker
1663*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1664*86b64dcbSAndroid Build Coastguard Worker if (errno == ENOTTY)
1665*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_SUPPORTED;
1666*86b64dcbSAndroid Build Coastguard Worker else if (errno == EINVAL)
1667*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_INVALID_PARAM;
1668*86b64dcbSAndroid Build Coastguard Worker else if (errno == ENODEV)
1669*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
1670*86b64dcbSAndroid Build Coastguard Worker
1671*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "streams-ioctl failed, errno=%d", errno);
1672*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
1673*86b64dcbSAndroid Build Coastguard Worker }
1674*86b64dcbSAndroid Build Coastguard Worker return r;
1675*86b64dcbSAndroid Build Coastguard Worker }
1676*86b64dcbSAndroid Build Coastguard Worker
op_alloc_streams(struct libusb_device_handle * handle,uint32_t num_streams,unsigned char * endpoints,int num_endpoints)1677*86b64dcbSAndroid Build Coastguard Worker static int op_alloc_streams(struct libusb_device_handle *handle,
1678*86b64dcbSAndroid Build Coastguard Worker uint32_t num_streams, unsigned char *endpoints, int num_endpoints)
1679*86b64dcbSAndroid Build Coastguard Worker {
1680*86b64dcbSAndroid Build Coastguard Worker return do_streams_ioctl(handle, IOCTL_USBFS_ALLOC_STREAMS,
1681*86b64dcbSAndroid Build Coastguard Worker num_streams, endpoints, num_endpoints);
1682*86b64dcbSAndroid Build Coastguard Worker }
1683*86b64dcbSAndroid Build Coastguard Worker
op_free_streams(struct libusb_device_handle * handle,unsigned char * endpoints,int num_endpoints)1684*86b64dcbSAndroid Build Coastguard Worker static int op_free_streams(struct libusb_device_handle *handle,
1685*86b64dcbSAndroid Build Coastguard Worker unsigned char *endpoints, int num_endpoints)
1686*86b64dcbSAndroid Build Coastguard Worker {
1687*86b64dcbSAndroid Build Coastguard Worker return do_streams_ioctl(handle, IOCTL_USBFS_FREE_STREAMS, 0,
1688*86b64dcbSAndroid Build Coastguard Worker endpoints, num_endpoints);
1689*86b64dcbSAndroid Build Coastguard Worker }
1690*86b64dcbSAndroid Build Coastguard Worker
op_dev_mem_alloc(struct libusb_device_handle * handle,size_t len)1691*86b64dcbSAndroid Build Coastguard Worker static void *op_dev_mem_alloc(struct libusb_device_handle *handle, size_t len)
1692*86b64dcbSAndroid Build Coastguard Worker {
1693*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1694*86b64dcbSAndroid Build Coastguard Worker void *buffer;
1695*86b64dcbSAndroid Build Coastguard Worker
1696*86b64dcbSAndroid Build Coastguard Worker buffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, hpriv->fd, 0);
1697*86b64dcbSAndroid Build Coastguard Worker if (buffer == MAP_FAILED) {
1698*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "alloc dev mem failed, errno=%d", errno);
1699*86b64dcbSAndroid Build Coastguard Worker return NULL;
1700*86b64dcbSAndroid Build Coastguard Worker }
1701*86b64dcbSAndroid Build Coastguard Worker return buffer;
1702*86b64dcbSAndroid Build Coastguard Worker }
1703*86b64dcbSAndroid Build Coastguard Worker
op_dev_mem_free(struct libusb_device_handle * handle,void * buffer,size_t len)1704*86b64dcbSAndroid Build Coastguard Worker static int op_dev_mem_free(struct libusb_device_handle *handle, void *buffer,
1705*86b64dcbSAndroid Build Coastguard Worker size_t len)
1706*86b64dcbSAndroid Build Coastguard Worker {
1707*86b64dcbSAndroid Build Coastguard Worker if (munmap(buffer, len) != 0) {
1708*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "free dev mem failed, errno=%d", errno);
1709*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
1710*86b64dcbSAndroid Build Coastguard Worker } else {
1711*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_SUCCESS;
1712*86b64dcbSAndroid Build Coastguard Worker }
1713*86b64dcbSAndroid Build Coastguard Worker }
1714*86b64dcbSAndroid Build Coastguard Worker
op_kernel_driver_active(struct libusb_device_handle * handle,uint8_t interface)1715*86b64dcbSAndroid Build Coastguard Worker static int op_kernel_driver_active(struct libusb_device_handle *handle,
1716*86b64dcbSAndroid Build Coastguard Worker uint8_t interface)
1717*86b64dcbSAndroid Build Coastguard Worker {
1718*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1719*86b64dcbSAndroid Build Coastguard Worker int fd = hpriv->fd;
1720*86b64dcbSAndroid Build Coastguard Worker struct usbfs_getdriver getdrv;
1721*86b64dcbSAndroid Build Coastguard Worker int r;
1722*86b64dcbSAndroid Build Coastguard Worker
1723*86b64dcbSAndroid Build Coastguard Worker getdrv.interface = interface;
1724*86b64dcbSAndroid Build Coastguard Worker r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv);
1725*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1726*86b64dcbSAndroid Build Coastguard Worker if (errno == ENODATA)
1727*86b64dcbSAndroid Build Coastguard Worker return 0;
1728*86b64dcbSAndroid Build Coastguard Worker else if (errno == ENODEV)
1729*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
1730*86b64dcbSAndroid Build Coastguard Worker
1731*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "get driver failed, errno=%d", errno);
1732*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
1733*86b64dcbSAndroid Build Coastguard Worker }
1734*86b64dcbSAndroid Build Coastguard Worker
1735*86b64dcbSAndroid Build Coastguard Worker return strcmp(getdrv.driver, "usbfs") != 0;
1736*86b64dcbSAndroid Build Coastguard Worker }
1737*86b64dcbSAndroid Build Coastguard Worker
op_detach_kernel_driver(struct libusb_device_handle * handle,uint8_t interface)1738*86b64dcbSAndroid Build Coastguard Worker static int op_detach_kernel_driver(struct libusb_device_handle *handle,
1739*86b64dcbSAndroid Build Coastguard Worker uint8_t interface)
1740*86b64dcbSAndroid Build Coastguard Worker {
1741*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1742*86b64dcbSAndroid Build Coastguard Worker int fd = hpriv->fd;
1743*86b64dcbSAndroid Build Coastguard Worker struct usbfs_ioctl command;
1744*86b64dcbSAndroid Build Coastguard Worker struct usbfs_getdriver getdrv;
1745*86b64dcbSAndroid Build Coastguard Worker int r;
1746*86b64dcbSAndroid Build Coastguard Worker
1747*86b64dcbSAndroid Build Coastguard Worker command.ifno = interface;
1748*86b64dcbSAndroid Build Coastguard Worker command.ioctl_code = IOCTL_USBFS_DISCONNECT;
1749*86b64dcbSAndroid Build Coastguard Worker command.data = NULL;
1750*86b64dcbSAndroid Build Coastguard Worker
1751*86b64dcbSAndroid Build Coastguard Worker getdrv.interface = interface;
1752*86b64dcbSAndroid Build Coastguard Worker r = ioctl(fd, IOCTL_USBFS_GETDRIVER, &getdrv);
1753*86b64dcbSAndroid Build Coastguard Worker if (r == 0 && !strcmp(getdrv.driver, "usbfs"))
1754*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
1755*86b64dcbSAndroid Build Coastguard Worker
1756*86b64dcbSAndroid Build Coastguard Worker r = ioctl(fd, IOCTL_USBFS_IOCTL, &command);
1757*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1758*86b64dcbSAndroid Build Coastguard Worker if (errno == ENODATA)
1759*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
1760*86b64dcbSAndroid Build Coastguard Worker else if (errno == EINVAL)
1761*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_INVALID_PARAM;
1762*86b64dcbSAndroid Build Coastguard Worker else if (errno == ENODEV)
1763*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
1764*86b64dcbSAndroid Build Coastguard Worker
1765*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "detach failed, errno=%d", errno);
1766*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
1767*86b64dcbSAndroid Build Coastguard Worker }
1768*86b64dcbSAndroid Build Coastguard Worker
1769*86b64dcbSAndroid Build Coastguard Worker return 0;
1770*86b64dcbSAndroid Build Coastguard Worker }
1771*86b64dcbSAndroid Build Coastguard Worker
op_attach_kernel_driver(struct libusb_device_handle * handle,uint8_t interface)1772*86b64dcbSAndroid Build Coastguard Worker static int op_attach_kernel_driver(struct libusb_device_handle *handle,
1773*86b64dcbSAndroid Build Coastguard Worker uint8_t interface)
1774*86b64dcbSAndroid Build Coastguard Worker {
1775*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1776*86b64dcbSAndroid Build Coastguard Worker int fd = hpriv->fd;
1777*86b64dcbSAndroid Build Coastguard Worker struct usbfs_ioctl command;
1778*86b64dcbSAndroid Build Coastguard Worker int r;
1779*86b64dcbSAndroid Build Coastguard Worker
1780*86b64dcbSAndroid Build Coastguard Worker command.ifno = interface;
1781*86b64dcbSAndroid Build Coastguard Worker command.ioctl_code = IOCTL_USBFS_CONNECT;
1782*86b64dcbSAndroid Build Coastguard Worker command.data = NULL;
1783*86b64dcbSAndroid Build Coastguard Worker
1784*86b64dcbSAndroid Build Coastguard Worker r = ioctl(fd, IOCTL_USBFS_IOCTL, &command);
1785*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
1786*86b64dcbSAndroid Build Coastguard Worker if (errno == ENODATA)
1787*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
1788*86b64dcbSAndroid Build Coastguard Worker else if (errno == EINVAL)
1789*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_INVALID_PARAM;
1790*86b64dcbSAndroid Build Coastguard Worker else if (errno == ENODEV)
1791*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
1792*86b64dcbSAndroid Build Coastguard Worker else if (errno == EBUSY)
1793*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_BUSY;
1794*86b64dcbSAndroid Build Coastguard Worker
1795*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "attach failed, errno=%d", errno);
1796*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
1797*86b64dcbSAndroid Build Coastguard Worker } else if (r == 0) {
1798*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
1799*86b64dcbSAndroid Build Coastguard Worker }
1800*86b64dcbSAndroid Build Coastguard Worker
1801*86b64dcbSAndroid Build Coastguard Worker return 0;
1802*86b64dcbSAndroid Build Coastguard Worker }
1803*86b64dcbSAndroid Build Coastguard Worker
detach_kernel_driver_and_claim(struct libusb_device_handle * handle,uint8_t interface)1804*86b64dcbSAndroid Build Coastguard Worker static int detach_kernel_driver_and_claim(struct libusb_device_handle *handle,
1805*86b64dcbSAndroid Build Coastguard Worker uint8_t interface)
1806*86b64dcbSAndroid Build Coastguard Worker {
1807*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
1808*86b64dcbSAndroid Build Coastguard Worker struct usbfs_disconnect_claim dc;
1809*86b64dcbSAndroid Build Coastguard Worker int r, fd = hpriv->fd;
1810*86b64dcbSAndroid Build Coastguard Worker
1811*86b64dcbSAndroid Build Coastguard Worker dc.interface = interface;
1812*86b64dcbSAndroid Build Coastguard Worker strcpy(dc.driver, "usbfs");
1813*86b64dcbSAndroid Build Coastguard Worker dc.flags = USBFS_DISCONNECT_CLAIM_EXCEPT_DRIVER;
1814*86b64dcbSAndroid Build Coastguard Worker r = ioctl(fd, IOCTL_USBFS_DISCONNECT_CLAIM, &dc);
1815*86b64dcbSAndroid Build Coastguard Worker if (r == 0)
1816*86b64dcbSAndroid Build Coastguard Worker return 0;
1817*86b64dcbSAndroid Build Coastguard Worker switch (errno) {
1818*86b64dcbSAndroid Build Coastguard Worker case ENOTTY:
1819*86b64dcbSAndroid Build Coastguard Worker break;
1820*86b64dcbSAndroid Build Coastguard Worker case EBUSY:
1821*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_BUSY;
1822*86b64dcbSAndroid Build Coastguard Worker case EINVAL:
1823*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_INVALID_PARAM;
1824*86b64dcbSAndroid Build Coastguard Worker case ENODEV:
1825*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
1826*86b64dcbSAndroid Build Coastguard Worker default:
1827*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "disconnect-and-claim failed, errno=%d", errno);
1828*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
1829*86b64dcbSAndroid Build Coastguard Worker }
1830*86b64dcbSAndroid Build Coastguard Worker
1831*86b64dcbSAndroid Build Coastguard Worker /* Fallback code for kernels which don't support the
1832*86b64dcbSAndroid Build Coastguard Worker disconnect-and-claim ioctl */
1833*86b64dcbSAndroid Build Coastguard Worker r = op_detach_kernel_driver(handle, interface);
1834*86b64dcbSAndroid Build Coastguard Worker if (r != 0 && r != LIBUSB_ERROR_NOT_FOUND)
1835*86b64dcbSAndroid Build Coastguard Worker return r;
1836*86b64dcbSAndroid Build Coastguard Worker
1837*86b64dcbSAndroid Build Coastguard Worker return claim_interface(handle, interface);
1838*86b64dcbSAndroid Build Coastguard Worker }
1839*86b64dcbSAndroid Build Coastguard Worker
op_claim_interface(struct libusb_device_handle * handle,uint8_t interface)1840*86b64dcbSAndroid Build Coastguard Worker static int op_claim_interface(struct libusb_device_handle *handle, uint8_t interface)
1841*86b64dcbSAndroid Build Coastguard Worker {
1842*86b64dcbSAndroid Build Coastguard Worker if (handle->auto_detach_kernel_driver)
1843*86b64dcbSAndroid Build Coastguard Worker return detach_kernel_driver_and_claim(handle, interface);
1844*86b64dcbSAndroid Build Coastguard Worker else
1845*86b64dcbSAndroid Build Coastguard Worker return claim_interface(handle, interface);
1846*86b64dcbSAndroid Build Coastguard Worker }
1847*86b64dcbSAndroid Build Coastguard Worker
op_release_interface(struct libusb_device_handle * handle,uint8_t interface)1848*86b64dcbSAndroid Build Coastguard Worker static int op_release_interface(struct libusb_device_handle *handle, uint8_t interface)
1849*86b64dcbSAndroid Build Coastguard Worker {
1850*86b64dcbSAndroid Build Coastguard Worker int r;
1851*86b64dcbSAndroid Build Coastguard Worker
1852*86b64dcbSAndroid Build Coastguard Worker r = release_interface(handle, interface);
1853*86b64dcbSAndroid Build Coastguard Worker if (r)
1854*86b64dcbSAndroid Build Coastguard Worker return r;
1855*86b64dcbSAndroid Build Coastguard Worker
1856*86b64dcbSAndroid Build Coastguard Worker if (handle->auto_detach_kernel_driver)
1857*86b64dcbSAndroid Build Coastguard Worker op_attach_kernel_driver(handle, interface);
1858*86b64dcbSAndroid Build Coastguard Worker
1859*86b64dcbSAndroid Build Coastguard Worker return 0;
1860*86b64dcbSAndroid Build Coastguard Worker }
1861*86b64dcbSAndroid Build Coastguard Worker
op_destroy_device(struct libusb_device * dev)1862*86b64dcbSAndroid Build Coastguard Worker static void op_destroy_device(struct libusb_device *dev)
1863*86b64dcbSAndroid Build Coastguard Worker {
1864*86b64dcbSAndroid Build Coastguard Worker struct linux_device_priv *priv = usbi_get_device_priv(dev);
1865*86b64dcbSAndroid Build Coastguard Worker
1866*86b64dcbSAndroid Build Coastguard Worker free(priv->config_descriptors);
1867*86b64dcbSAndroid Build Coastguard Worker free(priv->descriptors);
1868*86b64dcbSAndroid Build Coastguard Worker free(priv->sysfs_dir);
1869*86b64dcbSAndroid Build Coastguard Worker }
1870*86b64dcbSAndroid Build Coastguard Worker
1871*86b64dcbSAndroid Build Coastguard Worker /* URBs are discarded in reverse order of submission to avoid races. */
discard_urbs(struct usbi_transfer * itransfer,int first,int last_plus_one)1872*86b64dcbSAndroid Build Coastguard Worker static int discard_urbs(struct usbi_transfer *itransfer, int first, int last_plus_one)
1873*86b64dcbSAndroid Build Coastguard Worker {
1874*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer =
1875*86b64dcbSAndroid Build Coastguard Worker USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1876*86b64dcbSAndroid Build Coastguard Worker struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
1877*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv =
1878*86b64dcbSAndroid Build Coastguard Worker usbi_get_device_handle_priv(transfer->dev_handle);
1879*86b64dcbSAndroid Build Coastguard Worker int i, ret = 0;
1880*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb *urb;
1881*86b64dcbSAndroid Build Coastguard Worker
1882*86b64dcbSAndroid Build Coastguard Worker for (i = last_plus_one - 1; i >= first; i--) {
1883*86b64dcbSAndroid Build Coastguard Worker if (transfer->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS)
1884*86b64dcbSAndroid Build Coastguard Worker urb = tpriv->iso_urbs[i];
1885*86b64dcbSAndroid Build Coastguard Worker else
1886*86b64dcbSAndroid Build Coastguard Worker urb = &tpriv->urbs[i];
1887*86b64dcbSAndroid Build Coastguard Worker
1888*86b64dcbSAndroid Build Coastguard Worker if (ioctl(hpriv->fd, IOCTL_USBFS_DISCARDURB, urb) == 0)
1889*86b64dcbSAndroid Build Coastguard Worker continue;
1890*86b64dcbSAndroid Build Coastguard Worker
1891*86b64dcbSAndroid Build Coastguard Worker if (errno == EINVAL) {
1892*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "URB not found --> assuming ready to be reaped");
1893*86b64dcbSAndroid Build Coastguard Worker if (i == (last_plus_one - 1))
1894*86b64dcbSAndroid Build Coastguard Worker ret = LIBUSB_ERROR_NOT_FOUND;
1895*86b64dcbSAndroid Build Coastguard Worker } else if (errno == ENODEV) {
1896*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "Device not found for URB --> assuming ready to be reaped");
1897*86b64dcbSAndroid Build Coastguard Worker ret = LIBUSB_ERROR_NO_DEVICE;
1898*86b64dcbSAndroid Build Coastguard Worker } else {
1899*86b64dcbSAndroid Build Coastguard Worker usbi_warn(TRANSFER_CTX(transfer), "unrecognised discard errno %d", errno);
1900*86b64dcbSAndroid Build Coastguard Worker ret = LIBUSB_ERROR_OTHER;
1901*86b64dcbSAndroid Build Coastguard Worker }
1902*86b64dcbSAndroid Build Coastguard Worker }
1903*86b64dcbSAndroid Build Coastguard Worker return ret;
1904*86b64dcbSAndroid Build Coastguard Worker }
1905*86b64dcbSAndroid Build Coastguard Worker
free_iso_urbs(struct linux_transfer_priv * tpriv)1906*86b64dcbSAndroid Build Coastguard Worker static void free_iso_urbs(struct linux_transfer_priv *tpriv)
1907*86b64dcbSAndroid Build Coastguard Worker {
1908*86b64dcbSAndroid Build Coastguard Worker int i;
1909*86b64dcbSAndroid Build Coastguard Worker
1910*86b64dcbSAndroid Build Coastguard Worker for (i = 0; i < tpriv->num_urbs; i++) {
1911*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb *urb = tpriv->iso_urbs[i];
1912*86b64dcbSAndroid Build Coastguard Worker
1913*86b64dcbSAndroid Build Coastguard Worker if (!urb)
1914*86b64dcbSAndroid Build Coastguard Worker break;
1915*86b64dcbSAndroid Build Coastguard Worker free(urb);
1916*86b64dcbSAndroid Build Coastguard Worker }
1917*86b64dcbSAndroid Build Coastguard Worker
1918*86b64dcbSAndroid Build Coastguard Worker free(tpriv->iso_urbs);
1919*86b64dcbSAndroid Build Coastguard Worker tpriv->iso_urbs = NULL;
1920*86b64dcbSAndroid Build Coastguard Worker }
1921*86b64dcbSAndroid Build Coastguard Worker
submit_bulk_transfer(struct usbi_transfer * itransfer)1922*86b64dcbSAndroid Build Coastguard Worker static int submit_bulk_transfer(struct usbi_transfer *itransfer)
1923*86b64dcbSAndroid Build Coastguard Worker {
1924*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer =
1925*86b64dcbSAndroid Build Coastguard Worker USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
1926*86b64dcbSAndroid Build Coastguard Worker struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
1927*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv =
1928*86b64dcbSAndroid Build Coastguard Worker usbi_get_device_handle_priv(transfer->dev_handle);
1929*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb *urbs;
1930*86b64dcbSAndroid Build Coastguard Worker int is_out = IS_XFEROUT(transfer);
1931*86b64dcbSAndroid Build Coastguard Worker int bulk_buffer_len, use_bulk_continuation;
1932*86b64dcbSAndroid Build Coastguard Worker int num_urbs;
1933*86b64dcbSAndroid Build Coastguard Worker int last_urb_partial = 0;
1934*86b64dcbSAndroid Build Coastguard Worker int r;
1935*86b64dcbSAndroid Build Coastguard Worker int i;
1936*86b64dcbSAndroid Build Coastguard Worker
1937*86b64dcbSAndroid Build Coastguard Worker /*
1938*86b64dcbSAndroid Build Coastguard Worker * Older versions of usbfs place a 16kb limit on bulk URBs. We work
1939*86b64dcbSAndroid Build Coastguard Worker * around this by splitting large transfers into 16k blocks, and then
1940*86b64dcbSAndroid Build Coastguard Worker * submit all urbs at once. it would be simpler to submit one urb at
1941*86b64dcbSAndroid Build Coastguard Worker * a time, but there is a big performance gain doing it this way.
1942*86b64dcbSAndroid Build Coastguard Worker *
1943*86b64dcbSAndroid Build Coastguard Worker * Newer versions lift the 16k limit (USBFS_CAP_NO_PACKET_SIZE_LIM),
1944*86b64dcbSAndroid Build Coastguard Worker * using arbitrary large transfers can still be a bad idea though, as
1945*86b64dcbSAndroid Build Coastguard Worker * the kernel needs to allocate physical contiguous memory for this,
1946*86b64dcbSAndroid Build Coastguard Worker * which may fail for large buffers.
1947*86b64dcbSAndroid Build Coastguard Worker *
1948*86b64dcbSAndroid Build Coastguard Worker * The kernel solves this problem by splitting the transfer into
1949*86b64dcbSAndroid Build Coastguard Worker * blocks itself when the host-controller is scatter-gather capable
1950*86b64dcbSAndroid Build Coastguard Worker * (USBFS_CAP_BULK_SCATTER_GATHER), which most controllers are.
1951*86b64dcbSAndroid Build Coastguard Worker *
1952*86b64dcbSAndroid Build Coastguard Worker * Last, there is the issue of short-transfers when splitting, for
1953*86b64dcbSAndroid Build Coastguard Worker * short split-transfers to work reliable USBFS_CAP_BULK_CONTINUATION
1954*86b64dcbSAndroid Build Coastguard Worker * is needed, but this is not always available.
1955*86b64dcbSAndroid Build Coastguard Worker */
1956*86b64dcbSAndroid Build Coastguard Worker if (hpriv->caps & USBFS_CAP_BULK_SCATTER_GATHER) {
1957*86b64dcbSAndroid Build Coastguard Worker /* Good! Just submit everything in one go */
1958*86b64dcbSAndroid Build Coastguard Worker bulk_buffer_len = transfer->length ? transfer->length : 1;
1959*86b64dcbSAndroid Build Coastguard Worker use_bulk_continuation = 0;
1960*86b64dcbSAndroid Build Coastguard Worker } else if (hpriv->caps & USBFS_CAP_BULK_CONTINUATION) {
1961*86b64dcbSAndroid Build Coastguard Worker /* Split the transfers and use bulk-continuation to
1962*86b64dcbSAndroid Build Coastguard Worker avoid issues with short-transfers */
1963*86b64dcbSAndroid Build Coastguard Worker bulk_buffer_len = MAX_BULK_BUFFER_LENGTH;
1964*86b64dcbSAndroid Build Coastguard Worker use_bulk_continuation = 1;
1965*86b64dcbSAndroid Build Coastguard Worker } else if (hpriv->caps & USBFS_CAP_NO_PACKET_SIZE_LIM) {
1966*86b64dcbSAndroid Build Coastguard Worker /* Don't split, assume the kernel can alloc the buffer
1967*86b64dcbSAndroid Build Coastguard Worker (otherwise the submit will fail with -ENOMEM) */
1968*86b64dcbSAndroid Build Coastguard Worker bulk_buffer_len = transfer->length ? transfer->length : 1;
1969*86b64dcbSAndroid Build Coastguard Worker use_bulk_continuation = 0;
1970*86b64dcbSAndroid Build Coastguard Worker } else {
1971*86b64dcbSAndroid Build Coastguard Worker /* Bad, splitting without bulk-continuation, short transfers
1972*86b64dcbSAndroid Build Coastguard Worker which end before the last urb will not work reliable! */
1973*86b64dcbSAndroid Build Coastguard Worker /* Note we don't warn here as this is "normal" on kernels <
1974*86b64dcbSAndroid Build Coastguard Worker 2.6.32 and not a problem for most applications */
1975*86b64dcbSAndroid Build Coastguard Worker bulk_buffer_len = MAX_BULK_BUFFER_LENGTH;
1976*86b64dcbSAndroid Build Coastguard Worker use_bulk_continuation = 0;
1977*86b64dcbSAndroid Build Coastguard Worker }
1978*86b64dcbSAndroid Build Coastguard Worker
1979*86b64dcbSAndroid Build Coastguard Worker num_urbs = transfer->length / bulk_buffer_len;
1980*86b64dcbSAndroid Build Coastguard Worker
1981*86b64dcbSAndroid Build Coastguard Worker if (transfer->length == 0) {
1982*86b64dcbSAndroid Build Coastguard Worker num_urbs = 1;
1983*86b64dcbSAndroid Build Coastguard Worker } else if ((transfer->length % bulk_buffer_len) > 0) {
1984*86b64dcbSAndroid Build Coastguard Worker last_urb_partial = 1;
1985*86b64dcbSAndroid Build Coastguard Worker num_urbs++;
1986*86b64dcbSAndroid Build Coastguard Worker }
1987*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "need %d urbs for new transfer with length %d", num_urbs, transfer->length);
1988*86b64dcbSAndroid Build Coastguard Worker urbs = calloc(num_urbs, sizeof(*urbs));
1989*86b64dcbSAndroid Build Coastguard Worker if (!urbs)
1990*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_MEM;
1991*86b64dcbSAndroid Build Coastguard Worker tpriv->urbs = urbs;
1992*86b64dcbSAndroid Build Coastguard Worker tpriv->num_urbs = num_urbs;
1993*86b64dcbSAndroid Build Coastguard Worker tpriv->num_retired = 0;
1994*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_action = NORMAL;
1995*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_status = LIBUSB_TRANSFER_COMPLETED;
1996*86b64dcbSAndroid Build Coastguard Worker
1997*86b64dcbSAndroid Build Coastguard Worker for (i = 0; i < num_urbs; i++) {
1998*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb *urb = &urbs[i];
1999*86b64dcbSAndroid Build Coastguard Worker
2000*86b64dcbSAndroid Build Coastguard Worker urb->usercontext = itransfer;
2001*86b64dcbSAndroid Build Coastguard Worker switch (transfer->type) {
2002*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_BULK:
2003*86b64dcbSAndroid Build Coastguard Worker urb->type = USBFS_URB_TYPE_BULK;
2004*86b64dcbSAndroid Build Coastguard Worker urb->stream_id = 0;
2005*86b64dcbSAndroid Build Coastguard Worker break;
2006*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2007*86b64dcbSAndroid Build Coastguard Worker urb->type = USBFS_URB_TYPE_BULK;
2008*86b64dcbSAndroid Build Coastguard Worker urb->stream_id = itransfer->stream_id;
2009*86b64dcbSAndroid Build Coastguard Worker break;
2010*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_INTERRUPT:
2011*86b64dcbSAndroid Build Coastguard Worker urb->type = USBFS_URB_TYPE_INTERRUPT;
2012*86b64dcbSAndroid Build Coastguard Worker break;
2013*86b64dcbSAndroid Build Coastguard Worker }
2014*86b64dcbSAndroid Build Coastguard Worker urb->endpoint = transfer->endpoint;
2015*86b64dcbSAndroid Build Coastguard Worker urb->buffer = transfer->buffer + (i * bulk_buffer_len);
2016*86b64dcbSAndroid Build Coastguard Worker
2017*86b64dcbSAndroid Build Coastguard Worker /* don't set the short not ok flag for the last URB */
2018*86b64dcbSAndroid Build Coastguard Worker if (use_bulk_continuation && !is_out && (i < num_urbs - 1))
2019*86b64dcbSAndroid Build Coastguard Worker urb->flags = USBFS_URB_SHORT_NOT_OK;
2020*86b64dcbSAndroid Build Coastguard Worker
2021*86b64dcbSAndroid Build Coastguard Worker if (i == num_urbs - 1 && last_urb_partial)
2022*86b64dcbSAndroid Build Coastguard Worker urb->buffer_length = transfer->length % bulk_buffer_len;
2023*86b64dcbSAndroid Build Coastguard Worker else if (transfer->length == 0)
2024*86b64dcbSAndroid Build Coastguard Worker urb->buffer_length = 0;
2025*86b64dcbSAndroid Build Coastguard Worker else
2026*86b64dcbSAndroid Build Coastguard Worker urb->buffer_length = bulk_buffer_len;
2027*86b64dcbSAndroid Build Coastguard Worker
2028*86b64dcbSAndroid Build Coastguard Worker if (i > 0 && use_bulk_continuation)
2029*86b64dcbSAndroid Build Coastguard Worker urb->flags |= USBFS_URB_BULK_CONTINUATION;
2030*86b64dcbSAndroid Build Coastguard Worker
2031*86b64dcbSAndroid Build Coastguard Worker /* we have already checked that the flag is supported */
2032*86b64dcbSAndroid Build Coastguard Worker if (is_out && i == num_urbs - 1 &&
2033*86b64dcbSAndroid Build Coastguard Worker (transfer->flags & LIBUSB_TRANSFER_ADD_ZERO_PACKET))
2034*86b64dcbSAndroid Build Coastguard Worker urb->flags |= USBFS_URB_ZERO_PACKET;
2035*86b64dcbSAndroid Build Coastguard Worker
2036*86b64dcbSAndroid Build Coastguard Worker r = ioctl(hpriv->fd, IOCTL_USBFS_SUBMITURB, urb);
2037*86b64dcbSAndroid Build Coastguard Worker if (r == 0)
2038*86b64dcbSAndroid Build Coastguard Worker continue;
2039*86b64dcbSAndroid Build Coastguard Worker
2040*86b64dcbSAndroid Build Coastguard Worker if (errno == ENODEV) {
2041*86b64dcbSAndroid Build Coastguard Worker r = LIBUSB_ERROR_NO_DEVICE;
2042*86b64dcbSAndroid Build Coastguard Worker } else if (errno == ENOMEM) {
2043*86b64dcbSAndroid Build Coastguard Worker r = LIBUSB_ERROR_NO_MEM;
2044*86b64dcbSAndroid Build Coastguard Worker } else {
2045*86b64dcbSAndroid Build Coastguard Worker usbi_err(TRANSFER_CTX(transfer), "submiturb failed, errno=%d", errno);
2046*86b64dcbSAndroid Build Coastguard Worker r = LIBUSB_ERROR_IO;
2047*86b64dcbSAndroid Build Coastguard Worker }
2048*86b64dcbSAndroid Build Coastguard Worker
2049*86b64dcbSAndroid Build Coastguard Worker /* if the first URB submission fails, we can simply free up and
2050*86b64dcbSAndroid Build Coastguard Worker * return failure immediately. */
2051*86b64dcbSAndroid Build Coastguard Worker if (i == 0) {
2052*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "first URB failed, easy peasy");
2053*86b64dcbSAndroid Build Coastguard Worker free(urbs);
2054*86b64dcbSAndroid Build Coastguard Worker tpriv->urbs = NULL;
2055*86b64dcbSAndroid Build Coastguard Worker return r;
2056*86b64dcbSAndroid Build Coastguard Worker }
2057*86b64dcbSAndroid Build Coastguard Worker
2058*86b64dcbSAndroid Build Coastguard Worker /* if it's not the first URB that failed, the situation is a bit
2059*86b64dcbSAndroid Build Coastguard Worker * tricky. we may need to discard all previous URBs. there are
2060*86b64dcbSAndroid Build Coastguard Worker * complications:
2061*86b64dcbSAndroid Build Coastguard Worker * - discarding is asynchronous - discarded urbs will be reaped
2062*86b64dcbSAndroid Build Coastguard Worker * later. the user must not have freed the transfer when the
2063*86b64dcbSAndroid Build Coastguard Worker * discarded URBs are reaped, otherwise libusb will be using
2064*86b64dcbSAndroid Build Coastguard Worker * freed memory.
2065*86b64dcbSAndroid Build Coastguard Worker * - the earlier URBs may have completed successfully and we do
2066*86b64dcbSAndroid Build Coastguard Worker * not want to throw away any data.
2067*86b64dcbSAndroid Build Coastguard Worker * - this URB failing may be no error; EREMOTEIO means that
2068*86b64dcbSAndroid Build Coastguard Worker * this transfer simply didn't need all the URBs we submitted
2069*86b64dcbSAndroid Build Coastguard Worker * so, we report that the transfer was submitted successfully and
2070*86b64dcbSAndroid Build Coastguard Worker * in case of error we discard all previous URBs. later when
2071*86b64dcbSAndroid Build Coastguard Worker * the final reap completes we can report error to the user,
2072*86b64dcbSAndroid Build Coastguard Worker * or success if an earlier URB was completed successfully.
2073*86b64dcbSAndroid Build Coastguard Worker */
2074*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_action = errno == EREMOTEIO ? COMPLETED_EARLY : SUBMIT_FAILED;
2075*86b64dcbSAndroid Build Coastguard Worker
2076*86b64dcbSAndroid Build Coastguard Worker /* The URBs we haven't submitted yet we count as already
2077*86b64dcbSAndroid Build Coastguard Worker * retired. */
2078*86b64dcbSAndroid Build Coastguard Worker tpriv->num_retired += num_urbs - i;
2079*86b64dcbSAndroid Build Coastguard Worker
2080*86b64dcbSAndroid Build Coastguard Worker /* If we completed short then don't try to discard. */
2081*86b64dcbSAndroid Build Coastguard Worker if (tpriv->reap_action == COMPLETED_EARLY)
2082*86b64dcbSAndroid Build Coastguard Worker return 0;
2083*86b64dcbSAndroid Build Coastguard Worker
2084*86b64dcbSAndroid Build Coastguard Worker discard_urbs(itransfer, 0, i);
2085*86b64dcbSAndroid Build Coastguard Worker
2086*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "reporting successful submission but waiting for %d "
2087*86b64dcbSAndroid Build Coastguard Worker "discards before reporting error", i);
2088*86b64dcbSAndroid Build Coastguard Worker return 0;
2089*86b64dcbSAndroid Build Coastguard Worker }
2090*86b64dcbSAndroid Build Coastguard Worker
2091*86b64dcbSAndroid Build Coastguard Worker return 0;
2092*86b64dcbSAndroid Build Coastguard Worker }
2093*86b64dcbSAndroid Build Coastguard Worker
submit_iso_transfer(struct usbi_transfer * itransfer)2094*86b64dcbSAndroid Build Coastguard Worker static int submit_iso_transfer(struct usbi_transfer *itransfer)
2095*86b64dcbSAndroid Build Coastguard Worker {
2096*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer =
2097*86b64dcbSAndroid Build Coastguard Worker USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2098*86b64dcbSAndroid Build Coastguard Worker struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
2099*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv =
2100*86b64dcbSAndroid Build Coastguard Worker usbi_get_device_handle_priv(transfer->dev_handle);
2101*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb **urbs;
2102*86b64dcbSAndroid Build Coastguard Worker int num_packets = transfer->num_iso_packets;
2103*86b64dcbSAndroid Build Coastguard Worker int num_packets_remaining;
2104*86b64dcbSAndroid Build Coastguard Worker int i, j;
2105*86b64dcbSAndroid Build Coastguard Worker int num_urbs;
2106*86b64dcbSAndroid Build Coastguard Worker unsigned int packet_len;
2107*86b64dcbSAndroid Build Coastguard Worker unsigned int total_len = 0;
2108*86b64dcbSAndroid Build Coastguard Worker unsigned char *urb_buffer = transfer->buffer;
2109*86b64dcbSAndroid Build Coastguard Worker
2110*86b64dcbSAndroid Build Coastguard Worker if (num_packets < 1)
2111*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_INVALID_PARAM;
2112*86b64dcbSAndroid Build Coastguard Worker
2113*86b64dcbSAndroid Build Coastguard Worker /* usbfs places arbitrary limits on iso URBs. this limit has changed
2114*86b64dcbSAndroid Build Coastguard Worker * at least three times, but we attempt to detect this limit during
2115*86b64dcbSAndroid Build Coastguard Worker * init and check it here. if the kernel rejects the request due to
2116*86b64dcbSAndroid Build Coastguard Worker * its size, we return an error indicating such to the user.
2117*86b64dcbSAndroid Build Coastguard Worker */
2118*86b64dcbSAndroid Build Coastguard Worker for (i = 0; i < num_packets; i++) {
2119*86b64dcbSAndroid Build Coastguard Worker packet_len = transfer->iso_packet_desc[i].length;
2120*86b64dcbSAndroid Build Coastguard Worker
2121*86b64dcbSAndroid Build Coastguard Worker if (packet_len > max_iso_packet_len) {
2122*86b64dcbSAndroid Build Coastguard Worker usbi_warn(TRANSFER_CTX(transfer),
2123*86b64dcbSAndroid Build Coastguard Worker "iso packet length of %u bytes exceeds maximum of %u bytes",
2124*86b64dcbSAndroid Build Coastguard Worker packet_len, max_iso_packet_len);
2125*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_INVALID_PARAM;
2126*86b64dcbSAndroid Build Coastguard Worker }
2127*86b64dcbSAndroid Build Coastguard Worker
2128*86b64dcbSAndroid Build Coastguard Worker total_len += packet_len;
2129*86b64dcbSAndroid Build Coastguard Worker }
2130*86b64dcbSAndroid Build Coastguard Worker
2131*86b64dcbSAndroid Build Coastguard Worker if (transfer->length < (int)total_len)
2132*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_INVALID_PARAM;
2133*86b64dcbSAndroid Build Coastguard Worker
2134*86b64dcbSAndroid Build Coastguard Worker /* usbfs limits the number of iso packets per URB */
2135*86b64dcbSAndroid Build Coastguard Worker num_urbs = (num_packets + (MAX_ISO_PACKETS_PER_URB - 1)) / MAX_ISO_PACKETS_PER_URB;
2136*86b64dcbSAndroid Build Coastguard Worker
2137*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "need %d urbs for new transfer with length %d", num_urbs, transfer->length);
2138*86b64dcbSAndroid Build Coastguard Worker
2139*86b64dcbSAndroid Build Coastguard Worker urbs = calloc(num_urbs, sizeof(*urbs));
2140*86b64dcbSAndroid Build Coastguard Worker if (!urbs)
2141*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_MEM;
2142*86b64dcbSAndroid Build Coastguard Worker
2143*86b64dcbSAndroid Build Coastguard Worker tpriv->iso_urbs = urbs;
2144*86b64dcbSAndroid Build Coastguard Worker tpriv->num_urbs = num_urbs;
2145*86b64dcbSAndroid Build Coastguard Worker tpriv->num_retired = 0;
2146*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_action = NORMAL;
2147*86b64dcbSAndroid Build Coastguard Worker tpriv->iso_packet_offset = 0;
2148*86b64dcbSAndroid Build Coastguard Worker
2149*86b64dcbSAndroid Build Coastguard Worker /* allocate + initialize each URB with the correct number of packets */
2150*86b64dcbSAndroid Build Coastguard Worker num_packets_remaining = num_packets;
2151*86b64dcbSAndroid Build Coastguard Worker for (i = 0, j = 0; i < num_urbs; i++) {
2152*86b64dcbSAndroid Build Coastguard Worker int num_packets_in_urb = MIN(num_packets_remaining, MAX_ISO_PACKETS_PER_URB);
2153*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb *urb;
2154*86b64dcbSAndroid Build Coastguard Worker size_t alloc_size;
2155*86b64dcbSAndroid Build Coastguard Worker int k;
2156*86b64dcbSAndroid Build Coastguard Worker
2157*86b64dcbSAndroid Build Coastguard Worker alloc_size = sizeof(*urb)
2158*86b64dcbSAndroid Build Coastguard Worker + (num_packets_in_urb * sizeof(struct usbfs_iso_packet_desc));
2159*86b64dcbSAndroid Build Coastguard Worker urb = calloc(1, alloc_size);
2160*86b64dcbSAndroid Build Coastguard Worker if (!urb) {
2161*86b64dcbSAndroid Build Coastguard Worker free_iso_urbs(tpriv);
2162*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_MEM;
2163*86b64dcbSAndroid Build Coastguard Worker }
2164*86b64dcbSAndroid Build Coastguard Worker urbs[i] = urb;
2165*86b64dcbSAndroid Build Coastguard Worker
2166*86b64dcbSAndroid Build Coastguard Worker /* populate packet lengths */
2167*86b64dcbSAndroid Build Coastguard Worker for (k = 0; k < num_packets_in_urb; j++, k++) {
2168*86b64dcbSAndroid Build Coastguard Worker packet_len = transfer->iso_packet_desc[j].length;
2169*86b64dcbSAndroid Build Coastguard Worker urb->buffer_length += packet_len;
2170*86b64dcbSAndroid Build Coastguard Worker urb->iso_frame_desc[k].length = packet_len;
2171*86b64dcbSAndroid Build Coastguard Worker }
2172*86b64dcbSAndroid Build Coastguard Worker
2173*86b64dcbSAndroid Build Coastguard Worker urb->usercontext = itransfer;
2174*86b64dcbSAndroid Build Coastguard Worker urb->type = USBFS_URB_TYPE_ISO;
2175*86b64dcbSAndroid Build Coastguard Worker /* FIXME: interface for non-ASAP data? */
2176*86b64dcbSAndroid Build Coastguard Worker urb->flags = USBFS_URB_ISO_ASAP;
2177*86b64dcbSAndroid Build Coastguard Worker urb->endpoint = transfer->endpoint;
2178*86b64dcbSAndroid Build Coastguard Worker urb->number_of_packets = num_packets_in_urb;
2179*86b64dcbSAndroid Build Coastguard Worker urb->buffer = urb_buffer;
2180*86b64dcbSAndroid Build Coastguard Worker
2181*86b64dcbSAndroid Build Coastguard Worker urb_buffer += urb->buffer_length;
2182*86b64dcbSAndroid Build Coastguard Worker num_packets_remaining -= num_packets_in_urb;
2183*86b64dcbSAndroid Build Coastguard Worker }
2184*86b64dcbSAndroid Build Coastguard Worker
2185*86b64dcbSAndroid Build Coastguard Worker /* submit URBs */
2186*86b64dcbSAndroid Build Coastguard Worker for (i = 0; i < num_urbs; i++) {
2187*86b64dcbSAndroid Build Coastguard Worker int r = ioctl(hpriv->fd, IOCTL_USBFS_SUBMITURB, urbs[i]);
2188*86b64dcbSAndroid Build Coastguard Worker
2189*86b64dcbSAndroid Build Coastguard Worker if (r == 0)
2190*86b64dcbSAndroid Build Coastguard Worker continue;
2191*86b64dcbSAndroid Build Coastguard Worker
2192*86b64dcbSAndroid Build Coastguard Worker if (errno == ENODEV) {
2193*86b64dcbSAndroid Build Coastguard Worker r = LIBUSB_ERROR_NO_DEVICE;
2194*86b64dcbSAndroid Build Coastguard Worker } else if (errno == EINVAL) {
2195*86b64dcbSAndroid Build Coastguard Worker usbi_warn(TRANSFER_CTX(transfer), "submiturb failed, transfer too large");
2196*86b64dcbSAndroid Build Coastguard Worker r = LIBUSB_ERROR_INVALID_PARAM;
2197*86b64dcbSAndroid Build Coastguard Worker } else if (errno == EMSGSIZE) {
2198*86b64dcbSAndroid Build Coastguard Worker usbi_warn(TRANSFER_CTX(transfer), "submiturb failed, iso packet length too large");
2199*86b64dcbSAndroid Build Coastguard Worker r = LIBUSB_ERROR_INVALID_PARAM;
2200*86b64dcbSAndroid Build Coastguard Worker } else {
2201*86b64dcbSAndroid Build Coastguard Worker usbi_err(TRANSFER_CTX(transfer), "submiturb failed, errno=%d", errno);
2202*86b64dcbSAndroid Build Coastguard Worker r = LIBUSB_ERROR_IO;
2203*86b64dcbSAndroid Build Coastguard Worker }
2204*86b64dcbSAndroid Build Coastguard Worker
2205*86b64dcbSAndroid Build Coastguard Worker /* if the first URB submission fails, we can simply free up and
2206*86b64dcbSAndroid Build Coastguard Worker * return failure immediately. */
2207*86b64dcbSAndroid Build Coastguard Worker if (i == 0) {
2208*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "first URB failed, easy peasy");
2209*86b64dcbSAndroid Build Coastguard Worker free_iso_urbs(tpriv);
2210*86b64dcbSAndroid Build Coastguard Worker return r;
2211*86b64dcbSAndroid Build Coastguard Worker }
2212*86b64dcbSAndroid Build Coastguard Worker
2213*86b64dcbSAndroid Build Coastguard Worker /* if it's not the first URB that failed, the situation is a bit
2214*86b64dcbSAndroid Build Coastguard Worker * tricky. we must discard all previous URBs. there are
2215*86b64dcbSAndroid Build Coastguard Worker * complications:
2216*86b64dcbSAndroid Build Coastguard Worker * - discarding is asynchronous - discarded urbs will be reaped
2217*86b64dcbSAndroid Build Coastguard Worker * later. the user must not have freed the transfer when the
2218*86b64dcbSAndroid Build Coastguard Worker * discarded URBs are reaped, otherwise libusb will be using
2219*86b64dcbSAndroid Build Coastguard Worker * freed memory.
2220*86b64dcbSAndroid Build Coastguard Worker * - the earlier URBs may have completed successfully and we do
2221*86b64dcbSAndroid Build Coastguard Worker * not want to throw away any data.
2222*86b64dcbSAndroid Build Coastguard Worker * so, in this case we discard all the previous URBs BUT we report
2223*86b64dcbSAndroid Build Coastguard Worker * that the transfer was submitted successfully. then later when
2224*86b64dcbSAndroid Build Coastguard Worker * the final discard completes we can report error to the user.
2225*86b64dcbSAndroid Build Coastguard Worker */
2226*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_action = SUBMIT_FAILED;
2227*86b64dcbSAndroid Build Coastguard Worker
2228*86b64dcbSAndroid Build Coastguard Worker /* The URBs we haven't submitted yet we count as already
2229*86b64dcbSAndroid Build Coastguard Worker * retired. */
2230*86b64dcbSAndroid Build Coastguard Worker tpriv->num_retired = num_urbs - i;
2231*86b64dcbSAndroid Build Coastguard Worker discard_urbs(itransfer, 0, i);
2232*86b64dcbSAndroid Build Coastguard Worker
2233*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "reporting successful submission but waiting for %d "
2234*86b64dcbSAndroid Build Coastguard Worker "discards before reporting error", i);
2235*86b64dcbSAndroid Build Coastguard Worker return 0;
2236*86b64dcbSAndroid Build Coastguard Worker }
2237*86b64dcbSAndroid Build Coastguard Worker
2238*86b64dcbSAndroid Build Coastguard Worker return 0;
2239*86b64dcbSAndroid Build Coastguard Worker }
2240*86b64dcbSAndroid Build Coastguard Worker
submit_control_transfer(struct usbi_transfer * itransfer)2241*86b64dcbSAndroid Build Coastguard Worker static int submit_control_transfer(struct usbi_transfer *itransfer)
2242*86b64dcbSAndroid Build Coastguard Worker {
2243*86b64dcbSAndroid Build Coastguard Worker struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
2244*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer =
2245*86b64dcbSAndroid Build Coastguard Worker USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2246*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv =
2247*86b64dcbSAndroid Build Coastguard Worker usbi_get_device_handle_priv(transfer->dev_handle);
2248*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb *urb;
2249*86b64dcbSAndroid Build Coastguard Worker int r;
2250*86b64dcbSAndroid Build Coastguard Worker
2251*86b64dcbSAndroid Build Coastguard Worker if (transfer->length - LIBUSB_CONTROL_SETUP_SIZE > MAX_CTRL_BUFFER_LENGTH)
2252*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_INVALID_PARAM;
2253*86b64dcbSAndroid Build Coastguard Worker
2254*86b64dcbSAndroid Build Coastguard Worker urb = calloc(1, sizeof(*urb));
2255*86b64dcbSAndroid Build Coastguard Worker if (!urb)
2256*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_MEM;
2257*86b64dcbSAndroid Build Coastguard Worker tpriv->urbs = urb;
2258*86b64dcbSAndroid Build Coastguard Worker tpriv->num_urbs = 1;
2259*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_action = NORMAL;
2260*86b64dcbSAndroid Build Coastguard Worker
2261*86b64dcbSAndroid Build Coastguard Worker urb->usercontext = itransfer;
2262*86b64dcbSAndroid Build Coastguard Worker urb->type = USBFS_URB_TYPE_CONTROL;
2263*86b64dcbSAndroid Build Coastguard Worker urb->endpoint = transfer->endpoint;
2264*86b64dcbSAndroid Build Coastguard Worker urb->buffer = transfer->buffer;
2265*86b64dcbSAndroid Build Coastguard Worker urb->buffer_length = transfer->length;
2266*86b64dcbSAndroid Build Coastguard Worker
2267*86b64dcbSAndroid Build Coastguard Worker r = ioctl(hpriv->fd, IOCTL_USBFS_SUBMITURB, urb);
2268*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
2269*86b64dcbSAndroid Build Coastguard Worker free(urb);
2270*86b64dcbSAndroid Build Coastguard Worker tpriv->urbs = NULL;
2271*86b64dcbSAndroid Build Coastguard Worker if (errno == ENODEV)
2272*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
2273*86b64dcbSAndroid Build Coastguard Worker
2274*86b64dcbSAndroid Build Coastguard Worker usbi_err(TRANSFER_CTX(transfer), "submiturb failed, errno=%d", errno);
2275*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
2276*86b64dcbSAndroid Build Coastguard Worker }
2277*86b64dcbSAndroid Build Coastguard Worker return 0;
2278*86b64dcbSAndroid Build Coastguard Worker }
2279*86b64dcbSAndroid Build Coastguard Worker
op_submit_transfer(struct usbi_transfer * itransfer)2280*86b64dcbSAndroid Build Coastguard Worker static int op_submit_transfer(struct usbi_transfer *itransfer)
2281*86b64dcbSAndroid Build Coastguard Worker {
2282*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer =
2283*86b64dcbSAndroid Build Coastguard Worker USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2284*86b64dcbSAndroid Build Coastguard Worker
2285*86b64dcbSAndroid Build Coastguard Worker switch (transfer->type) {
2286*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_CONTROL:
2287*86b64dcbSAndroid Build Coastguard Worker return submit_control_transfer(itransfer);
2288*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_BULK:
2289*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2290*86b64dcbSAndroid Build Coastguard Worker return submit_bulk_transfer(itransfer);
2291*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_INTERRUPT:
2292*86b64dcbSAndroid Build Coastguard Worker return submit_bulk_transfer(itransfer);
2293*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
2294*86b64dcbSAndroid Build Coastguard Worker return submit_iso_transfer(itransfer);
2295*86b64dcbSAndroid Build Coastguard Worker default:
2296*86b64dcbSAndroid Build Coastguard Worker usbi_err(TRANSFER_CTX(transfer), "unknown transfer type %u", transfer->type);
2297*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_INVALID_PARAM;
2298*86b64dcbSAndroid Build Coastguard Worker }
2299*86b64dcbSAndroid Build Coastguard Worker }
2300*86b64dcbSAndroid Build Coastguard Worker
op_cancel_transfer(struct usbi_transfer * itransfer)2301*86b64dcbSAndroid Build Coastguard Worker static int op_cancel_transfer(struct usbi_transfer *itransfer)
2302*86b64dcbSAndroid Build Coastguard Worker {
2303*86b64dcbSAndroid Build Coastguard Worker struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
2304*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer =
2305*86b64dcbSAndroid Build Coastguard Worker USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2306*86b64dcbSAndroid Build Coastguard Worker int r;
2307*86b64dcbSAndroid Build Coastguard Worker
2308*86b64dcbSAndroid Build Coastguard Worker if (!tpriv->urbs)
2309*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
2310*86b64dcbSAndroid Build Coastguard Worker
2311*86b64dcbSAndroid Build Coastguard Worker r = discard_urbs(itransfer, 0, tpriv->num_urbs);
2312*86b64dcbSAndroid Build Coastguard Worker if (r != 0)
2313*86b64dcbSAndroid Build Coastguard Worker return r;
2314*86b64dcbSAndroid Build Coastguard Worker
2315*86b64dcbSAndroid Build Coastguard Worker switch (transfer->type) {
2316*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_BULK:
2317*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2318*86b64dcbSAndroid Build Coastguard Worker if (tpriv->reap_action == ERROR)
2319*86b64dcbSAndroid Build Coastguard Worker break;
2320*86b64dcbSAndroid Build Coastguard Worker /* else, fall through */
2321*86b64dcbSAndroid Build Coastguard Worker default:
2322*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_action = CANCELLED;
2323*86b64dcbSAndroid Build Coastguard Worker }
2324*86b64dcbSAndroid Build Coastguard Worker
2325*86b64dcbSAndroid Build Coastguard Worker return 0;
2326*86b64dcbSAndroid Build Coastguard Worker }
2327*86b64dcbSAndroid Build Coastguard Worker
op_clear_transfer_priv(struct usbi_transfer * itransfer)2328*86b64dcbSAndroid Build Coastguard Worker static void op_clear_transfer_priv(struct usbi_transfer *itransfer)
2329*86b64dcbSAndroid Build Coastguard Worker {
2330*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer =
2331*86b64dcbSAndroid Build Coastguard Worker USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2332*86b64dcbSAndroid Build Coastguard Worker struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
2333*86b64dcbSAndroid Build Coastguard Worker
2334*86b64dcbSAndroid Build Coastguard Worker switch (transfer->type) {
2335*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_CONTROL:
2336*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_BULK:
2337*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2338*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_INTERRUPT:
2339*86b64dcbSAndroid Build Coastguard Worker if (tpriv->urbs) {
2340*86b64dcbSAndroid Build Coastguard Worker free(tpriv->urbs);
2341*86b64dcbSAndroid Build Coastguard Worker tpriv->urbs = NULL;
2342*86b64dcbSAndroid Build Coastguard Worker }
2343*86b64dcbSAndroid Build Coastguard Worker break;
2344*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
2345*86b64dcbSAndroid Build Coastguard Worker if (tpriv->iso_urbs) {
2346*86b64dcbSAndroid Build Coastguard Worker free_iso_urbs(tpriv);
2347*86b64dcbSAndroid Build Coastguard Worker tpriv->iso_urbs = NULL;
2348*86b64dcbSAndroid Build Coastguard Worker }
2349*86b64dcbSAndroid Build Coastguard Worker break;
2350*86b64dcbSAndroid Build Coastguard Worker default:
2351*86b64dcbSAndroid Build Coastguard Worker usbi_err(TRANSFER_CTX(transfer), "unknown transfer type %u", transfer->type);
2352*86b64dcbSAndroid Build Coastguard Worker }
2353*86b64dcbSAndroid Build Coastguard Worker }
2354*86b64dcbSAndroid Build Coastguard Worker
handle_bulk_completion(struct usbi_transfer * itransfer,struct usbfs_urb * urb)2355*86b64dcbSAndroid Build Coastguard Worker static int handle_bulk_completion(struct usbi_transfer *itransfer,
2356*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb *urb)
2357*86b64dcbSAndroid Build Coastguard Worker {
2358*86b64dcbSAndroid Build Coastguard Worker struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
2359*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2360*86b64dcbSAndroid Build Coastguard Worker int urb_idx = urb - tpriv->urbs;
2361*86b64dcbSAndroid Build Coastguard Worker
2362*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_lock(&itransfer->lock);
2363*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "handling completion status %d of bulk urb %d/%d", urb->status,
2364*86b64dcbSAndroid Build Coastguard Worker urb_idx + 1, tpriv->num_urbs);
2365*86b64dcbSAndroid Build Coastguard Worker
2366*86b64dcbSAndroid Build Coastguard Worker tpriv->num_retired++;
2367*86b64dcbSAndroid Build Coastguard Worker
2368*86b64dcbSAndroid Build Coastguard Worker if (tpriv->reap_action != NORMAL) {
2369*86b64dcbSAndroid Build Coastguard Worker /* cancelled, submit_fail, or completed early */
2370*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "abnormal reap: urb status %d", urb->status);
2371*86b64dcbSAndroid Build Coastguard Worker
2372*86b64dcbSAndroid Build Coastguard Worker /* even though we're in the process of cancelling, it's possible that
2373*86b64dcbSAndroid Build Coastguard Worker * we may receive some data in these URBs that we don't want to lose.
2374*86b64dcbSAndroid Build Coastguard Worker * examples:
2375*86b64dcbSAndroid Build Coastguard Worker * 1. while the kernel is cancelling all the packets that make up an
2376*86b64dcbSAndroid Build Coastguard Worker * URB, a few of them might complete. so we get back a successful
2377*86b64dcbSAndroid Build Coastguard Worker * cancellation *and* some data.
2378*86b64dcbSAndroid Build Coastguard Worker * 2. we receive a short URB which marks the early completion condition,
2379*86b64dcbSAndroid Build Coastguard Worker * so we start cancelling the remaining URBs. however, we're too
2380*86b64dcbSAndroid Build Coastguard Worker * slow and another URB completes (or at least completes partially).
2381*86b64dcbSAndroid Build Coastguard Worker * (this can't happen since we always use BULK_CONTINUATION.)
2382*86b64dcbSAndroid Build Coastguard Worker *
2383*86b64dcbSAndroid Build Coastguard Worker * When this happens, our objectives are not to lose any "surplus" data,
2384*86b64dcbSAndroid Build Coastguard Worker * and also to stick it at the end of the previously-received data
2385*86b64dcbSAndroid Build Coastguard Worker * (closing any holes), so that libusb reports the total amount of
2386*86b64dcbSAndroid Build Coastguard Worker * transferred data and presents it in a contiguous chunk.
2387*86b64dcbSAndroid Build Coastguard Worker */
2388*86b64dcbSAndroid Build Coastguard Worker if (urb->actual_length > 0) {
2389*86b64dcbSAndroid Build Coastguard Worker unsigned char *target = transfer->buffer + itransfer->transferred;
2390*86b64dcbSAndroid Build Coastguard Worker
2391*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "received %d bytes of surplus data", urb->actual_length);
2392*86b64dcbSAndroid Build Coastguard Worker if (urb->buffer != target) {
2393*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "moving surplus data from offset %zu to offset %zu",
2394*86b64dcbSAndroid Build Coastguard Worker (unsigned char *)urb->buffer - transfer->buffer,
2395*86b64dcbSAndroid Build Coastguard Worker target - transfer->buffer);
2396*86b64dcbSAndroid Build Coastguard Worker memmove(target, urb->buffer, urb->actual_length);
2397*86b64dcbSAndroid Build Coastguard Worker }
2398*86b64dcbSAndroid Build Coastguard Worker itransfer->transferred += urb->actual_length;
2399*86b64dcbSAndroid Build Coastguard Worker }
2400*86b64dcbSAndroid Build Coastguard Worker
2401*86b64dcbSAndroid Build Coastguard Worker if (tpriv->num_retired == tpriv->num_urbs) {
2402*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "abnormal reap: last URB handled, reporting");
2403*86b64dcbSAndroid Build Coastguard Worker if (tpriv->reap_action != COMPLETED_EARLY &&
2404*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED)
2405*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_status = LIBUSB_TRANSFER_ERROR;
2406*86b64dcbSAndroid Build Coastguard Worker goto completed;
2407*86b64dcbSAndroid Build Coastguard Worker }
2408*86b64dcbSAndroid Build Coastguard Worker goto out_unlock;
2409*86b64dcbSAndroid Build Coastguard Worker }
2410*86b64dcbSAndroid Build Coastguard Worker
2411*86b64dcbSAndroid Build Coastguard Worker itransfer->transferred += urb->actual_length;
2412*86b64dcbSAndroid Build Coastguard Worker
2413*86b64dcbSAndroid Build Coastguard Worker /* Many of these errors can occur on *any* urb of a multi-urb
2414*86b64dcbSAndroid Build Coastguard Worker * transfer. When they do, we tear down the rest of the transfer.
2415*86b64dcbSAndroid Build Coastguard Worker */
2416*86b64dcbSAndroid Build Coastguard Worker switch (urb->status) {
2417*86b64dcbSAndroid Build Coastguard Worker case 0:
2418*86b64dcbSAndroid Build Coastguard Worker break;
2419*86b64dcbSAndroid Build Coastguard Worker case -EREMOTEIO: /* short transfer */
2420*86b64dcbSAndroid Build Coastguard Worker break;
2421*86b64dcbSAndroid Build Coastguard Worker case -ENOENT: /* cancelled */
2422*86b64dcbSAndroid Build Coastguard Worker case -ECONNRESET:
2423*86b64dcbSAndroid Build Coastguard Worker break;
2424*86b64dcbSAndroid Build Coastguard Worker case -ENODEV:
2425*86b64dcbSAndroid Build Coastguard Worker case -ESHUTDOWN:
2426*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "device removed");
2427*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_status = LIBUSB_TRANSFER_NO_DEVICE;
2428*86b64dcbSAndroid Build Coastguard Worker goto cancel_remaining;
2429*86b64dcbSAndroid Build Coastguard Worker case -EPIPE:
2430*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "detected endpoint stall");
2431*86b64dcbSAndroid Build Coastguard Worker if (tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED)
2432*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_status = LIBUSB_TRANSFER_STALL;
2433*86b64dcbSAndroid Build Coastguard Worker goto cancel_remaining;
2434*86b64dcbSAndroid Build Coastguard Worker case -EOVERFLOW:
2435*86b64dcbSAndroid Build Coastguard Worker /* overflow can only ever occur in the last urb */
2436*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "overflow, actual_length=%d", urb->actual_length);
2437*86b64dcbSAndroid Build Coastguard Worker if (tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED)
2438*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_status = LIBUSB_TRANSFER_OVERFLOW;
2439*86b64dcbSAndroid Build Coastguard Worker goto completed;
2440*86b64dcbSAndroid Build Coastguard Worker case -ETIME:
2441*86b64dcbSAndroid Build Coastguard Worker case -EPROTO:
2442*86b64dcbSAndroid Build Coastguard Worker case -EILSEQ:
2443*86b64dcbSAndroid Build Coastguard Worker case -ECOMM:
2444*86b64dcbSAndroid Build Coastguard Worker case -ENOSR:
2445*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "low-level bus error %d", urb->status);
2446*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_action = ERROR;
2447*86b64dcbSAndroid Build Coastguard Worker goto cancel_remaining;
2448*86b64dcbSAndroid Build Coastguard Worker default:
2449*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ITRANSFER_CTX(itransfer), "unrecognised urb status %d", urb->status);
2450*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_action = ERROR;
2451*86b64dcbSAndroid Build Coastguard Worker goto cancel_remaining;
2452*86b64dcbSAndroid Build Coastguard Worker }
2453*86b64dcbSAndroid Build Coastguard Worker
2454*86b64dcbSAndroid Build Coastguard Worker /* if we've reaped all urbs or we got less data than requested then we're
2455*86b64dcbSAndroid Build Coastguard Worker * done */
2456*86b64dcbSAndroid Build Coastguard Worker if (tpriv->num_retired == tpriv->num_urbs) {
2457*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "all URBs in transfer reaped --> complete!");
2458*86b64dcbSAndroid Build Coastguard Worker goto completed;
2459*86b64dcbSAndroid Build Coastguard Worker } else if (urb->actual_length < urb->buffer_length) {
2460*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "short transfer %d/%d --> complete!",
2461*86b64dcbSAndroid Build Coastguard Worker urb->actual_length, urb->buffer_length);
2462*86b64dcbSAndroid Build Coastguard Worker if (tpriv->reap_action == NORMAL)
2463*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_action = COMPLETED_EARLY;
2464*86b64dcbSAndroid Build Coastguard Worker } else {
2465*86b64dcbSAndroid Build Coastguard Worker goto out_unlock;
2466*86b64dcbSAndroid Build Coastguard Worker }
2467*86b64dcbSAndroid Build Coastguard Worker
2468*86b64dcbSAndroid Build Coastguard Worker cancel_remaining:
2469*86b64dcbSAndroid Build Coastguard Worker if (tpriv->reap_action == ERROR && tpriv->reap_status == LIBUSB_TRANSFER_COMPLETED)
2470*86b64dcbSAndroid Build Coastguard Worker tpriv->reap_status = LIBUSB_TRANSFER_ERROR;
2471*86b64dcbSAndroid Build Coastguard Worker
2472*86b64dcbSAndroid Build Coastguard Worker if (tpriv->num_retired == tpriv->num_urbs) /* nothing to cancel */
2473*86b64dcbSAndroid Build Coastguard Worker goto completed;
2474*86b64dcbSAndroid Build Coastguard Worker
2475*86b64dcbSAndroid Build Coastguard Worker /* cancel remaining urbs and wait for their completion before
2476*86b64dcbSAndroid Build Coastguard Worker * reporting results */
2477*86b64dcbSAndroid Build Coastguard Worker discard_urbs(itransfer, urb_idx + 1, tpriv->num_urbs);
2478*86b64dcbSAndroid Build Coastguard Worker
2479*86b64dcbSAndroid Build Coastguard Worker out_unlock:
2480*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_unlock(&itransfer->lock);
2481*86b64dcbSAndroid Build Coastguard Worker return 0;
2482*86b64dcbSAndroid Build Coastguard Worker
2483*86b64dcbSAndroid Build Coastguard Worker completed:
2484*86b64dcbSAndroid Build Coastguard Worker free(tpriv->urbs);
2485*86b64dcbSAndroid Build Coastguard Worker tpriv->urbs = NULL;
2486*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_unlock(&itransfer->lock);
2487*86b64dcbSAndroid Build Coastguard Worker return tpriv->reap_action == CANCELLED ?
2488*86b64dcbSAndroid Build Coastguard Worker usbi_handle_transfer_cancellation(itransfer) :
2489*86b64dcbSAndroid Build Coastguard Worker usbi_handle_transfer_completion(itransfer, tpriv->reap_status);
2490*86b64dcbSAndroid Build Coastguard Worker }
2491*86b64dcbSAndroid Build Coastguard Worker
handle_iso_completion(struct usbi_transfer * itransfer,struct usbfs_urb * urb)2492*86b64dcbSAndroid Build Coastguard Worker static int handle_iso_completion(struct usbi_transfer *itransfer,
2493*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb *urb)
2494*86b64dcbSAndroid Build Coastguard Worker {
2495*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer =
2496*86b64dcbSAndroid Build Coastguard Worker USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2497*86b64dcbSAndroid Build Coastguard Worker struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
2498*86b64dcbSAndroid Build Coastguard Worker int num_urbs = tpriv->num_urbs;
2499*86b64dcbSAndroid Build Coastguard Worker int urb_idx = 0;
2500*86b64dcbSAndroid Build Coastguard Worker int i;
2501*86b64dcbSAndroid Build Coastguard Worker enum libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED;
2502*86b64dcbSAndroid Build Coastguard Worker
2503*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_lock(&itransfer->lock);
2504*86b64dcbSAndroid Build Coastguard Worker for (i = 0; i < num_urbs; i++) {
2505*86b64dcbSAndroid Build Coastguard Worker if (urb == tpriv->iso_urbs[i]) {
2506*86b64dcbSAndroid Build Coastguard Worker urb_idx = i + 1;
2507*86b64dcbSAndroid Build Coastguard Worker break;
2508*86b64dcbSAndroid Build Coastguard Worker }
2509*86b64dcbSAndroid Build Coastguard Worker }
2510*86b64dcbSAndroid Build Coastguard Worker if (urb_idx == 0) {
2511*86b64dcbSAndroid Build Coastguard Worker usbi_err(TRANSFER_CTX(transfer), "could not locate urb!");
2512*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_unlock(&itransfer->lock);
2513*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NOT_FOUND;
2514*86b64dcbSAndroid Build Coastguard Worker }
2515*86b64dcbSAndroid Build Coastguard Worker
2516*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "handling completion status %d of iso urb %d/%d", urb->status,
2517*86b64dcbSAndroid Build Coastguard Worker urb_idx, num_urbs);
2518*86b64dcbSAndroid Build Coastguard Worker
2519*86b64dcbSAndroid Build Coastguard Worker /* copy isochronous results back in */
2520*86b64dcbSAndroid Build Coastguard Worker
2521*86b64dcbSAndroid Build Coastguard Worker for (i = 0; i < urb->number_of_packets; i++) {
2522*86b64dcbSAndroid Build Coastguard Worker struct usbfs_iso_packet_desc *urb_desc = &urb->iso_frame_desc[i];
2523*86b64dcbSAndroid Build Coastguard Worker struct libusb_iso_packet_descriptor *lib_desc =
2524*86b64dcbSAndroid Build Coastguard Worker &transfer->iso_packet_desc[tpriv->iso_packet_offset++];
2525*86b64dcbSAndroid Build Coastguard Worker
2526*86b64dcbSAndroid Build Coastguard Worker lib_desc->status = LIBUSB_TRANSFER_COMPLETED;
2527*86b64dcbSAndroid Build Coastguard Worker switch (urb_desc->status) {
2528*86b64dcbSAndroid Build Coastguard Worker case 0:
2529*86b64dcbSAndroid Build Coastguard Worker break;
2530*86b64dcbSAndroid Build Coastguard Worker case -ENOENT: /* cancelled */
2531*86b64dcbSAndroid Build Coastguard Worker case -ECONNRESET:
2532*86b64dcbSAndroid Build Coastguard Worker break;
2533*86b64dcbSAndroid Build Coastguard Worker case -ENODEV:
2534*86b64dcbSAndroid Build Coastguard Worker case -ESHUTDOWN:
2535*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "packet %d - device removed", i);
2536*86b64dcbSAndroid Build Coastguard Worker lib_desc->status = LIBUSB_TRANSFER_NO_DEVICE;
2537*86b64dcbSAndroid Build Coastguard Worker break;
2538*86b64dcbSAndroid Build Coastguard Worker case -EPIPE:
2539*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "packet %d - detected endpoint stall", i);
2540*86b64dcbSAndroid Build Coastguard Worker lib_desc->status = LIBUSB_TRANSFER_STALL;
2541*86b64dcbSAndroid Build Coastguard Worker break;
2542*86b64dcbSAndroid Build Coastguard Worker case -EOVERFLOW:
2543*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "packet %d - overflow error", i);
2544*86b64dcbSAndroid Build Coastguard Worker lib_desc->status = LIBUSB_TRANSFER_OVERFLOW;
2545*86b64dcbSAndroid Build Coastguard Worker break;
2546*86b64dcbSAndroid Build Coastguard Worker case -ETIME:
2547*86b64dcbSAndroid Build Coastguard Worker case -EPROTO:
2548*86b64dcbSAndroid Build Coastguard Worker case -EILSEQ:
2549*86b64dcbSAndroid Build Coastguard Worker case -ECOMM:
2550*86b64dcbSAndroid Build Coastguard Worker case -ENOSR:
2551*86b64dcbSAndroid Build Coastguard Worker case -EXDEV:
2552*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "packet %d - low-level USB error %d", i, urb_desc->status);
2553*86b64dcbSAndroid Build Coastguard Worker lib_desc->status = LIBUSB_TRANSFER_ERROR;
2554*86b64dcbSAndroid Build Coastguard Worker break;
2555*86b64dcbSAndroid Build Coastguard Worker default:
2556*86b64dcbSAndroid Build Coastguard Worker usbi_warn(TRANSFER_CTX(transfer), "packet %d - unrecognised urb status %d",
2557*86b64dcbSAndroid Build Coastguard Worker i, urb_desc->status);
2558*86b64dcbSAndroid Build Coastguard Worker lib_desc->status = LIBUSB_TRANSFER_ERROR;
2559*86b64dcbSAndroid Build Coastguard Worker break;
2560*86b64dcbSAndroid Build Coastguard Worker }
2561*86b64dcbSAndroid Build Coastguard Worker lib_desc->actual_length = urb_desc->actual_length;
2562*86b64dcbSAndroid Build Coastguard Worker }
2563*86b64dcbSAndroid Build Coastguard Worker
2564*86b64dcbSAndroid Build Coastguard Worker tpriv->num_retired++;
2565*86b64dcbSAndroid Build Coastguard Worker
2566*86b64dcbSAndroid Build Coastguard Worker if (tpriv->reap_action != NORMAL) { /* cancelled or submit_fail */
2567*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "CANCEL: urb status %d", urb->status);
2568*86b64dcbSAndroid Build Coastguard Worker
2569*86b64dcbSAndroid Build Coastguard Worker if (tpriv->num_retired == num_urbs) {
2570*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "CANCEL: last URB handled, reporting");
2571*86b64dcbSAndroid Build Coastguard Worker free_iso_urbs(tpriv);
2572*86b64dcbSAndroid Build Coastguard Worker if (tpriv->reap_action == CANCELLED) {
2573*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_unlock(&itransfer->lock);
2574*86b64dcbSAndroid Build Coastguard Worker return usbi_handle_transfer_cancellation(itransfer);
2575*86b64dcbSAndroid Build Coastguard Worker } else {
2576*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_unlock(&itransfer->lock);
2577*86b64dcbSAndroid Build Coastguard Worker return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_ERROR);
2578*86b64dcbSAndroid Build Coastguard Worker }
2579*86b64dcbSAndroid Build Coastguard Worker }
2580*86b64dcbSAndroid Build Coastguard Worker goto out;
2581*86b64dcbSAndroid Build Coastguard Worker }
2582*86b64dcbSAndroid Build Coastguard Worker
2583*86b64dcbSAndroid Build Coastguard Worker switch (urb->status) {
2584*86b64dcbSAndroid Build Coastguard Worker case 0:
2585*86b64dcbSAndroid Build Coastguard Worker break;
2586*86b64dcbSAndroid Build Coastguard Worker case -ENOENT: /* cancelled */
2587*86b64dcbSAndroid Build Coastguard Worker case -ECONNRESET:
2588*86b64dcbSAndroid Build Coastguard Worker break;
2589*86b64dcbSAndroid Build Coastguard Worker case -ESHUTDOWN:
2590*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "device removed");
2591*86b64dcbSAndroid Build Coastguard Worker status = LIBUSB_TRANSFER_NO_DEVICE;
2592*86b64dcbSAndroid Build Coastguard Worker break;
2593*86b64dcbSAndroid Build Coastguard Worker default:
2594*86b64dcbSAndroid Build Coastguard Worker usbi_warn(TRANSFER_CTX(transfer), "unrecognised urb status %d", urb->status);
2595*86b64dcbSAndroid Build Coastguard Worker status = LIBUSB_TRANSFER_ERROR;
2596*86b64dcbSAndroid Build Coastguard Worker break;
2597*86b64dcbSAndroid Build Coastguard Worker }
2598*86b64dcbSAndroid Build Coastguard Worker
2599*86b64dcbSAndroid Build Coastguard Worker /* if we've reaped all urbs then we're done */
2600*86b64dcbSAndroid Build Coastguard Worker if (tpriv->num_retired == num_urbs) {
2601*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(TRANSFER_CTX(transfer), "all URBs in transfer reaped --> complete!");
2602*86b64dcbSAndroid Build Coastguard Worker free_iso_urbs(tpriv);
2603*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_unlock(&itransfer->lock);
2604*86b64dcbSAndroid Build Coastguard Worker return usbi_handle_transfer_completion(itransfer, status);
2605*86b64dcbSAndroid Build Coastguard Worker }
2606*86b64dcbSAndroid Build Coastguard Worker
2607*86b64dcbSAndroid Build Coastguard Worker out:
2608*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_unlock(&itransfer->lock);
2609*86b64dcbSAndroid Build Coastguard Worker return 0;
2610*86b64dcbSAndroid Build Coastguard Worker }
2611*86b64dcbSAndroid Build Coastguard Worker
handle_control_completion(struct usbi_transfer * itransfer,struct usbfs_urb * urb)2612*86b64dcbSAndroid Build Coastguard Worker static int handle_control_completion(struct usbi_transfer *itransfer,
2613*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb *urb)
2614*86b64dcbSAndroid Build Coastguard Worker {
2615*86b64dcbSAndroid Build Coastguard Worker struct linux_transfer_priv *tpriv = usbi_get_transfer_priv(itransfer);
2616*86b64dcbSAndroid Build Coastguard Worker int status;
2617*86b64dcbSAndroid Build Coastguard Worker
2618*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_lock(&itransfer->lock);
2619*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ITRANSFER_CTX(itransfer), "handling completion status %d", urb->status);
2620*86b64dcbSAndroid Build Coastguard Worker
2621*86b64dcbSAndroid Build Coastguard Worker itransfer->transferred += urb->actual_length;
2622*86b64dcbSAndroid Build Coastguard Worker
2623*86b64dcbSAndroid Build Coastguard Worker if (tpriv->reap_action == CANCELLED) {
2624*86b64dcbSAndroid Build Coastguard Worker if (urb->status && urb->status != -ENOENT)
2625*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ITRANSFER_CTX(itransfer), "cancel: unrecognised urb status %d",
2626*86b64dcbSAndroid Build Coastguard Worker urb->status);
2627*86b64dcbSAndroid Build Coastguard Worker free(tpriv->urbs);
2628*86b64dcbSAndroid Build Coastguard Worker tpriv->urbs = NULL;
2629*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_unlock(&itransfer->lock);
2630*86b64dcbSAndroid Build Coastguard Worker return usbi_handle_transfer_cancellation(itransfer);
2631*86b64dcbSAndroid Build Coastguard Worker }
2632*86b64dcbSAndroid Build Coastguard Worker
2633*86b64dcbSAndroid Build Coastguard Worker switch (urb->status) {
2634*86b64dcbSAndroid Build Coastguard Worker case 0:
2635*86b64dcbSAndroid Build Coastguard Worker status = LIBUSB_TRANSFER_COMPLETED;
2636*86b64dcbSAndroid Build Coastguard Worker break;
2637*86b64dcbSAndroid Build Coastguard Worker case -ENOENT: /* cancelled */
2638*86b64dcbSAndroid Build Coastguard Worker status = LIBUSB_TRANSFER_CANCELLED;
2639*86b64dcbSAndroid Build Coastguard Worker break;
2640*86b64dcbSAndroid Build Coastguard Worker case -ENODEV:
2641*86b64dcbSAndroid Build Coastguard Worker case -ESHUTDOWN:
2642*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ITRANSFER_CTX(itransfer), "device removed");
2643*86b64dcbSAndroid Build Coastguard Worker status = LIBUSB_TRANSFER_NO_DEVICE;
2644*86b64dcbSAndroid Build Coastguard Worker break;
2645*86b64dcbSAndroid Build Coastguard Worker case -EPIPE:
2646*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ITRANSFER_CTX(itransfer), "unsupported control request");
2647*86b64dcbSAndroid Build Coastguard Worker status = LIBUSB_TRANSFER_STALL;
2648*86b64dcbSAndroid Build Coastguard Worker break;
2649*86b64dcbSAndroid Build Coastguard Worker case -EOVERFLOW:
2650*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ITRANSFER_CTX(itransfer), "overflow, actual_length=%d", urb->actual_length);
2651*86b64dcbSAndroid Build Coastguard Worker status = LIBUSB_TRANSFER_OVERFLOW;
2652*86b64dcbSAndroid Build Coastguard Worker break;
2653*86b64dcbSAndroid Build Coastguard Worker case -ETIME:
2654*86b64dcbSAndroid Build Coastguard Worker case -EPROTO:
2655*86b64dcbSAndroid Build Coastguard Worker case -EILSEQ:
2656*86b64dcbSAndroid Build Coastguard Worker case -ECOMM:
2657*86b64dcbSAndroid Build Coastguard Worker case -ENOSR:
2658*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(ITRANSFER_CTX(itransfer), "low-level bus error %d", urb->status);
2659*86b64dcbSAndroid Build Coastguard Worker status = LIBUSB_TRANSFER_ERROR;
2660*86b64dcbSAndroid Build Coastguard Worker break;
2661*86b64dcbSAndroid Build Coastguard Worker default:
2662*86b64dcbSAndroid Build Coastguard Worker usbi_warn(ITRANSFER_CTX(itransfer), "unrecognised urb status %d", urb->status);
2663*86b64dcbSAndroid Build Coastguard Worker status = LIBUSB_TRANSFER_ERROR;
2664*86b64dcbSAndroid Build Coastguard Worker break;
2665*86b64dcbSAndroid Build Coastguard Worker }
2666*86b64dcbSAndroid Build Coastguard Worker
2667*86b64dcbSAndroid Build Coastguard Worker free(tpriv->urbs);
2668*86b64dcbSAndroid Build Coastguard Worker tpriv->urbs = NULL;
2669*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_unlock(&itransfer->lock);
2670*86b64dcbSAndroid Build Coastguard Worker return usbi_handle_transfer_completion(itransfer, status);
2671*86b64dcbSAndroid Build Coastguard Worker }
2672*86b64dcbSAndroid Build Coastguard Worker
reap_for_handle(struct libusb_device_handle * handle)2673*86b64dcbSAndroid Build Coastguard Worker static int reap_for_handle(struct libusb_device_handle *handle)
2674*86b64dcbSAndroid Build Coastguard Worker {
2675*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = usbi_get_device_handle_priv(handle);
2676*86b64dcbSAndroid Build Coastguard Worker int r;
2677*86b64dcbSAndroid Build Coastguard Worker struct usbfs_urb *urb = NULL;
2678*86b64dcbSAndroid Build Coastguard Worker struct usbi_transfer *itransfer;
2679*86b64dcbSAndroid Build Coastguard Worker struct libusb_transfer *transfer;
2680*86b64dcbSAndroid Build Coastguard Worker
2681*86b64dcbSAndroid Build Coastguard Worker r = ioctl(hpriv->fd, IOCTL_USBFS_REAPURBNDELAY, &urb);
2682*86b64dcbSAndroid Build Coastguard Worker if (r < 0) {
2683*86b64dcbSAndroid Build Coastguard Worker if (errno == EAGAIN)
2684*86b64dcbSAndroid Build Coastguard Worker return 1;
2685*86b64dcbSAndroid Build Coastguard Worker if (errno == ENODEV)
2686*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_NO_DEVICE;
2687*86b64dcbSAndroid Build Coastguard Worker
2688*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "reap failed, errno=%d", errno);
2689*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_IO;
2690*86b64dcbSAndroid Build Coastguard Worker }
2691*86b64dcbSAndroid Build Coastguard Worker
2692*86b64dcbSAndroid Build Coastguard Worker itransfer = urb->usercontext;
2693*86b64dcbSAndroid Build Coastguard Worker transfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer);
2694*86b64dcbSAndroid Build Coastguard Worker
2695*86b64dcbSAndroid Build Coastguard Worker usbi_dbg(HANDLE_CTX(handle), "urb type=%u status=%d transferred=%d", urb->type, urb->status, urb->actual_length);
2696*86b64dcbSAndroid Build Coastguard Worker
2697*86b64dcbSAndroid Build Coastguard Worker switch (transfer->type) {
2698*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS:
2699*86b64dcbSAndroid Build Coastguard Worker return handle_iso_completion(itransfer, urb);
2700*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_BULK:
2701*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_BULK_STREAM:
2702*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_INTERRUPT:
2703*86b64dcbSAndroid Build Coastguard Worker return handle_bulk_completion(itransfer, urb);
2704*86b64dcbSAndroid Build Coastguard Worker case LIBUSB_TRANSFER_TYPE_CONTROL:
2705*86b64dcbSAndroid Build Coastguard Worker return handle_control_completion(itransfer, urb);
2706*86b64dcbSAndroid Build Coastguard Worker default:
2707*86b64dcbSAndroid Build Coastguard Worker usbi_err(HANDLE_CTX(handle), "unrecognised transfer type %u", transfer->type);
2708*86b64dcbSAndroid Build Coastguard Worker return LIBUSB_ERROR_OTHER;
2709*86b64dcbSAndroid Build Coastguard Worker }
2710*86b64dcbSAndroid Build Coastguard Worker }
2711*86b64dcbSAndroid Build Coastguard Worker
op_handle_events(struct libusb_context * ctx,void * event_data,unsigned int count,unsigned int num_ready)2712*86b64dcbSAndroid Build Coastguard Worker static int op_handle_events(struct libusb_context *ctx,
2713*86b64dcbSAndroid Build Coastguard Worker void *event_data, unsigned int count, unsigned int num_ready)
2714*86b64dcbSAndroid Build Coastguard Worker {
2715*86b64dcbSAndroid Build Coastguard Worker struct pollfd *fds = event_data;
2716*86b64dcbSAndroid Build Coastguard Worker unsigned int n;
2717*86b64dcbSAndroid Build Coastguard Worker int r;
2718*86b64dcbSAndroid Build Coastguard Worker
2719*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_lock(&ctx->open_devs_lock);
2720*86b64dcbSAndroid Build Coastguard Worker for (n = 0; n < count && num_ready > 0; n++) {
2721*86b64dcbSAndroid Build Coastguard Worker struct pollfd *pollfd = &fds[n];
2722*86b64dcbSAndroid Build Coastguard Worker struct libusb_device_handle *handle;
2723*86b64dcbSAndroid Build Coastguard Worker struct linux_device_handle_priv *hpriv = NULL;
2724*86b64dcbSAndroid Build Coastguard Worker int reap_count;
2725*86b64dcbSAndroid Build Coastguard Worker
2726*86b64dcbSAndroid Build Coastguard Worker if (!pollfd->revents)
2727*86b64dcbSAndroid Build Coastguard Worker continue;
2728*86b64dcbSAndroid Build Coastguard Worker
2729*86b64dcbSAndroid Build Coastguard Worker num_ready--;
2730*86b64dcbSAndroid Build Coastguard Worker for_each_open_device(ctx, handle) {
2731*86b64dcbSAndroid Build Coastguard Worker hpriv = usbi_get_device_handle_priv(handle);
2732*86b64dcbSAndroid Build Coastguard Worker if (hpriv->fd == pollfd->fd)
2733*86b64dcbSAndroid Build Coastguard Worker break;
2734*86b64dcbSAndroid Build Coastguard Worker }
2735*86b64dcbSAndroid Build Coastguard Worker
2736*86b64dcbSAndroid Build Coastguard Worker if (!hpriv || hpriv->fd != pollfd->fd) {
2737*86b64dcbSAndroid Build Coastguard Worker usbi_err(ctx, "cannot find handle for fd %d",
2738*86b64dcbSAndroid Build Coastguard Worker pollfd->fd);
2739*86b64dcbSAndroid Build Coastguard Worker continue;
2740*86b64dcbSAndroid Build Coastguard Worker }
2741*86b64dcbSAndroid Build Coastguard Worker
2742*86b64dcbSAndroid Build Coastguard Worker if (pollfd->revents & POLLERR) {
2743*86b64dcbSAndroid Build Coastguard Worker /* remove the fd from the pollfd set so that it doesn't continuously
2744*86b64dcbSAndroid Build Coastguard Worker * trigger an event, and flag that it has been removed so op_close()
2745*86b64dcbSAndroid Build Coastguard Worker * doesn't try to remove it a second time */
2746*86b64dcbSAndroid Build Coastguard Worker usbi_remove_event_source(HANDLE_CTX(handle), hpriv->fd);
2747*86b64dcbSAndroid Build Coastguard Worker hpriv->fd_removed = 1;
2748*86b64dcbSAndroid Build Coastguard Worker
2749*86b64dcbSAndroid Build Coastguard Worker /* device will still be marked as attached if hotplug monitor thread
2750*86b64dcbSAndroid Build Coastguard Worker * hasn't processed remove event yet */
2751*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_static_lock(&linux_hotplug_lock);
2752*86b64dcbSAndroid Build Coastguard Worker if (usbi_atomic_load(&handle->dev->attached))
2753*86b64dcbSAndroid Build Coastguard Worker linux_device_disconnected(handle->dev->bus_number,
2754*86b64dcbSAndroid Build Coastguard Worker handle->dev->device_address);
2755*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_static_unlock(&linux_hotplug_lock);
2756*86b64dcbSAndroid Build Coastguard Worker
2757*86b64dcbSAndroid Build Coastguard Worker if (hpriv->caps & USBFS_CAP_REAP_AFTER_DISCONNECT) {
2758*86b64dcbSAndroid Build Coastguard Worker do {
2759*86b64dcbSAndroid Build Coastguard Worker r = reap_for_handle(handle);
2760*86b64dcbSAndroid Build Coastguard Worker } while (r == 0);
2761*86b64dcbSAndroid Build Coastguard Worker }
2762*86b64dcbSAndroid Build Coastguard Worker
2763*86b64dcbSAndroid Build Coastguard Worker usbi_handle_disconnect(handle);
2764*86b64dcbSAndroid Build Coastguard Worker continue;
2765*86b64dcbSAndroid Build Coastguard Worker }
2766*86b64dcbSAndroid Build Coastguard Worker
2767*86b64dcbSAndroid Build Coastguard Worker reap_count = 0;
2768*86b64dcbSAndroid Build Coastguard Worker do {
2769*86b64dcbSAndroid Build Coastguard Worker r = reap_for_handle(handle);
2770*86b64dcbSAndroid Build Coastguard Worker } while (r == 0 && ++reap_count <= 25);
2771*86b64dcbSAndroid Build Coastguard Worker
2772*86b64dcbSAndroid Build Coastguard Worker if (r == 1 || r == LIBUSB_ERROR_NO_DEVICE)
2773*86b64dcbSAndroid Build Coastguard Worker continue;
2774*86b64dcbSAndroid Build Coastguard Worker else if (r < 0)
2775*86b64dcbSAndroid Build Coastguard Worker goto out;
2776*86b64dcbSAndroid Build Coastguard Worker }
2777*86b64dcbSAndroid Build Coastguard Worker
2778*86b64dcbSAndroid Build Coastguard Worker r = 0;
2779*86b64dcbSAndroid Build Coastguard Worker out:
2780*86b64dcbSAndroid Build Coastguard Worker usbi_mutex_unlock(&ctx->open_devs_lock);
2781*86b64dcbSAndroid Build Coastguard Worker return r;
2782*86b64dcbSAndroid Build Coastguard Worker }
2783*86b64dcbSAndroid Build Coastguard Worker
2784*86b64dcbSAndroid Build Coastguard Worker const struct usbi_os_backend usbi_backend = {
2785*86b64dcbSAndroid Build Coastguard Worker .name = "Linux usbfs",
2786*86b64dcbSAndroid Build Coastguard Worker .caps = USBI_CAP_HAS_HID_ACCESS|USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER,
2787*86b64dcbSAndroid Build Coastguard Worker .init = op_init,
2788*86b64dcbSAndroid Build Coastguard Worker .exit = op_exit,
2789*86b64dcbSAndroid Build Coastguard Worker .set_option = op_set_option,
2790*86b64dcbSAndroid Build Coastguard Worker .hotplug_poll = op_hotplug_poll,
2791*86b64dcbSAndroid Build Coastguard Worker .get_active_config_descriptor = op_get_active_config_descriptor,
2792*86b64dcbSAndroid Build Coastguard Worker .get_config_descriptor = op_get_config_descriptor,
2793*86b64dcbSAndroid Build Coastguard Worker .get_config_descriptor_by_value = op_get_config_descriptor_by_value,
2794*86b64dcbSAndroid Build Coastguard Worker
2795*86b64dcbSAndroid Build Coastguard Worker .wrap_sys_device = op_wrap_sys_device,
2796*86b64dcbSAndroid Build Coastguard Worker .open = op_open,
2797*86b64dcbSAndroid Build Coastguard Worker .close = op_close,
2798*86b64dcbSAndroid Build Coastguard Worker .get_configuration = op_get_configuration,
2799*86b64dcbSAndroid Build Coastguard Worker .set_configuration = op_set_configuration,
2800*86b64dcbSAndroid Build Coastguard Worker .claim_interface = op_claim_interface,
2801*86b64dcbSAndroid Build Coastguard Worker .release_interface = op_release_interface,
2802*86b64dcbSAndroid Build Coastguard Worker
2803*86b64dcbSAndroid Build Coastguard Worker .set_interface_altsetting = op_set_interface,
2804*86b64dcbSAndroid Build Coastguard Worker .clear_halt = op_clear_halt,
2805*86b64dcbSAndroid Build Coastguard Worker .reset_device = op_reset_device,
2806*86b64dcbSAndroid Build Coastguard Worker
2807*86b64dcbSAndroid Build Coastguard Worker .alloc_streams = op_alloc_streams,
2808*86b64dcbSAndroid Build Coastguard Worker .free_streams = op_free_streams,
2809*86b64dcbSAndroid Build Coastguard Worker
2810*86b64dcbSAndroid Build Coastguard Worker .dev_mem_alloc = op_dev_mem_alloc,
2811*86b64dcbSAndroid Build Coastguard Worker .dev_mem_free = op_dev_mem_free,
2812*86b64dcbSAndroid Build Coastguard Worker
2813*86b64dcbSAndroid Build Coastguard Worker .kernel_driver_active = op_kernel_driver_active,
2814*86b64dcbSAndroid Build Coastguard Worker .detach_kernel_driver = op_detach_kernel_driver,
2815*86b64dcbSAndroid Build Coastguard Worker .attach_kernel_driver = op_attach_kernel_driver,
2816*86b64dcbSAndroid Build Coastguard Worker
2817*86b64dcbSAndroid Build Coastguard Worker .destroy_device = op_destroy_device,
2818*86b64dcbSAndroid Build Coastguard Worker
2819*86b64dcbSAndroid Build Coastguard Worker .submit_transfer = op_submit_transfer,
2820*86b64dcbSAndroid Build Coastguard Worker .cancel_transfer = op_cancel_transfer,
2821*86b64dcbSAndroid Build Coastguard Worker .clear_transfer_priv = op_clear_transfer_priv,
2822*86b64dcbSAndroid Build Coastguard Worker
2823*86b64dcbSAndroid Build Coastguard Worker .handle_events = op_handle_events,
2824*86b64dcbSAndroid Build Coastguard Worker
2825*86b64dcbSAndroid Build Coastguard Worker .context_priv_size = sizeof(struct linux_context_priv),
2826*86b64dcbSAndroid Build Coastguard Worker .device_priv_size = sizeof(struct linux_device_priv),
2827*86b64dcbSAndroid Build Coastguard Worker .device_handle_priv_size = sizeof(struct linux_device_handle_priv),
2828*86b64dcbSAndroid Build Coastguard Worker .transfer_priv_size = sizeof(struct linux_transfer_priv),
2829*86b64dcbSAndroid Build Coastguard Worker };
2830