1*00c7fec1SAndroid Build Coastguard Worker /*
2*00c7fec1SAndroid Build Coastguard Worker * Copyright (C) 2010 The Android Open Source Project
3*00c7fec1SAndroid Build Coastguard Worker *
4*00c7fec1SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*00c7fec1SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*00c7fec1SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*00c7fec1SAndroid Build Coastguard Worker *
8*00c7fec1SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*00c7fec1SAndroid Build Coastguard Worker *
10*00c7fec1SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*00c7fec1SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*00c7fec1SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*00c7fec1SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*00c7fec1SAndroid Build Coastguard Worker * limitations under the License.
15*00c7fec1SAndroid Build Coastguard Worker */
16*00c7fec1SAndroid Build Coastguard Worker
17*00c7fec1SAndroid Build Coastguard Worker #ifndef _GNU_SOURCE
18*00c7fec1SAndroid Build Coastguard Worker #define _GNU_SOURCE
19*00c7fec1SAndroid Build Coastguard Worker #endif
20*00c7fec1SAndroid Build Coastguard Worker
21*00c7fec1SAndroid Build Coastguard Worker #include <usbhost/usbhost.h>
22*00c7fec1SAndroid Build Coastguard Worker
23*00c7fec1SAndroid Build Coastguard Worker #include "usbhost_private.h"
24*00c7fec1SAndroid Build Coastguard Worker
25*00c7fec1SAndroid Build Coastguard Worker #include <stdio.h>
26*00c7fec1SAndroid Build Coastguard Worker #include <stdlib.h>
27*00c7fec1SAndroid Build Coastguard Worker #include <unistd.h>
28*00c7fec1SAndroid Build Coastguard Worker #include <string.h>
29*00c7fec1SAndroid Build Coastguard Worker #include <stddef.h>
30*00c7fec1SAndroid Build Coastguard Worker
31*00c7fec1SAndroid Build Coastguard Worker #include <sys/ioctl.h>
32*00c7fec1SAndroid Build Coastguard Worker #include <sys/types.h>
33*00c7fec1SAndroid Build Coastguard Worker #include <sys/time.h>
34*00c7fec1SAndroid Build Coastguard Worker #include <sys/inotify.h>
35*00c7fec1SAndroid Build Coastguard Worker #include <dirent.h>
36*00c7fec1SAndroid Build Coastguard Worker #include <fcntl.h>
37*00c7fec1SAndroid Build Coastguard Worker #include <errno.h>
38*00c7fec1SAndroid Build Coastguard Worker #include <ctype.h>
39*00c7fec1SAndroid Build Coastguard Worker #include <poll.h>
40*00c7fec1SAndroid Build Coastguard Worker
41*00c7fec1SAndroid Build Coastguard Worker #include <linux/usbdevice_fs.h>
42*00c7fec1SAndroid Build Coastguard Worker
43*00c7fec1SAndroid Build Coastguard Worker // #define DEBUG 1
44*00c7fec1SAndroid Build Coastguard Worker #if defined(DEBUG)
45*00c7fec1SAndroid Build Coastguard Worker #if defined(__BIONIC__)
46*00c7fec1SAndroid Build Coastguard Worker #define D ALOGD
47*00c7fec1SAndroid Build Coastguard Worker #else
48*00c7fec1SAndroid Build Coastguard Worker #define D printf
49*00c7fec1SAndroid Build Coastguard Worker #endif
50*00c7fec1SAndroid Build Coastguard Worker #else
51*00c7fec1SAndroid Build Coastguard Worker #define D(...)
52*00c7fec1SAndroid Build Coastguard Worker #endif
53*00c7fec1SAndroid Build Coastguard Worker
54*00c7fec1SAndroid Build Coastguard Worker #define DEV_DIR "/dev"
55*00c7fec1SAndroid Build Coastguard Worker #define DEV_BUS_DIR DEV_DIR "/bus"
56*00c7fec1SAndroid Build Coastguard Worker #define USB_FS_DIR DEV_BUS_DIR "/usb"
57*00c7fec1SAndroid Build Coastguard Worker #define USB_FS_ID_SCANNER USB_FS_DIR "/%d/%d"
58*00c7fec1SAndroid Build Coastguard Worker #define USB_FS_ID_FORMAT USB_FS_DIR "/%03d/%03d"
59*00c7fec1SAndroid Build Coastguard Worker
60*00c7fec1SAndroid Build Coastguard Worker // Some devices fail to send string descriptors if we attempt reading > 255 bytes
61*00c7fec1SAndroid Build Coastguard Worker #define MAX_STRING_DESCRIPTOR_LENGTH 255
62*00c7fec1SAndroid Build Coastguard Worker
63*00c7fec1SAndroid Build Coastguard Worker #define MAX_USBFS_WD_COUNT 10
64*00c7fec1SAndroid Build Coastguard Worker
65*00c7fec1SAndroid Build Coastguard Worker struct usb_host_context {
66*00c7fec1SAndroid Build Coastguard Worker int fd;
67*00c7fec1SAndroid Build Coastguard Worker usb_device_added_cb cb_added;
68*00c7fec1SAndroid Build Coastguard Worker usb_device_removed_cb cb_removed;
69*00c7fec1SAndroid Build Coastguard Worker void *data;
70*00c7fec1SAndroid Build Coastguard Worker int wds[MAX_USBFS_WD_COUNT];
71*00c7fec1SAndroid Build Coastguard Worker int wdd;
72*00c7fec1SAndroid Build Coastguard Worker int wddbus;
73*00c7fec1SAndroid Build Coastguard Worker };
74*00c7fec1SAndroid Build Coastguard Worker
75*00c7fec1SAndroid Build Coastguard Worker struct usb_device {
76*00c7fec1SAndroid Build Coastguard Worker char dev_name[64];
77*00c7fec1SAndroid Build Coastguard Worker unsigned char desc[MAX_DESCRIPTORS_LENGTH];
78*00c7fec1SAndroid Build Coastguard Worker int desc_length;
79*00c7fec1SAndroid Build Coastguard Worker int fd;
80*00c7fec1SAndroid Build Coastguard Worker int writeable;
81*00c7fec1SAndroid Build Coastguard Worker };
82*00c7fec1SAndroid Build Coastguard Worker
badname(const char * name)83*00c7fec1SAndroid Build Coastguard Worker static inline int badname(const char *name)
84*00c7fec1SAndroid Build Coastguard Worker {
85*00c7fec1SAndroid Build Coastguard Worker while(*name) {
86*00c7fec1SAndroid Build Coastguard Worker if(!isdigit(*name++)) return 1;
87*00c7fec1SAndroid Build Coastguard Worker }
88*00c7fec1SAndroid Build Coastguard Worker return 0;
89*00c7fec1SAndroid Build Coastguard Worker }
90*00c7fec1SAndroid Build Coastguard Worker
find_existing_devices_bus(char * busname,usb_device_added_cb added_cb,void * client_data)91*00c7fec1SAndroid Build Coastguard Worker static int find_existing_devices_bus(char *busname,
92*00c7fec1SAndroid Build Coastguard Worker usb_device_added_cb added_cb,
93*00c7fec1SAndroid Build Coastguard Worker void *client_data)
94*00c7fec1SAndroid Build Coastguard Worker {
95*00c7fec1SAndroid Build Coastguard Worker char devname[32];
96*00c7fec1SAndroid Build Coastguard Worker DIR *devdir;
97*00c7fec1SAndroid Build Coastguard Worker struct dirent *de;
98*00c7fec1SAndroid Build Coastguard Worker int done = 0;
99*00c7fec1SAndroid Build Coastguard Worker
100*00c7fec1SAndroid Build Coastguard Worker devdir = opendir(busname);
101*00c7fec1SAndroid Build Coastguard Worker if(devdir == 0) return 0;
102*00c7fec1SAndroid Build Coastguard Worker
103*00c7fec1SAndroid Build Coastguard Worker while ((de = readdir(devdir)) && !done) {
104*00c7fec1SAndroid Build Coastguard Worker if(badname(de->d_name)) continue;
105*00c7fec1SAndroid Build Coastguard Worker
106*00c7fec1SAndroid Build Coastguard Worker snprintf(devname, sizeof(devname), "%s/%s", busname, de->d_name);
107*00c7fec1SAndroid Build Coastguard Worker done = added_cb(devname, client_data);
108*00c7fec1SAndroid Build Coastguard Worker } // end of devdir while
109*00c7fec1SAndroid Build Coastguard Worker closedir(devdir);
110*00c7fec1SAndroid Build Coastguard Worker
111*00c7fec1SAndroid Build Coastguard Worker return done;
112*00c7fec1SAndroid Build Coastguard Worker }
113*00c7fec1SAndroid Build Coastguard Worker
114*00c7fec1SAndroid Build Coastguard Worker /* returns true if one of the callbacks indicates we are done */
find_existing_devices(usb_device_added_cb added_cb,void * client_data)115*00c7fec1SAndroid Build Coastguard Worker static int find_existing_devices(usb_device_added_cb added_cb,
116*00c7fec1SAndroid Build Coastguard Worker void *client_data)
117*00c7fec1SAndroid Build Coastguard Worker {
118*00c7fec1SAndroid Build Coastguard Worker char busname[32];
119*00c7fec1SAndroid Build Coastguard Worker DIR *busdir;
120*00c7fec1SAndroid Build Coastguard Worker struct dirent *de;
121*00c7fec1SAndroid Build Coastguard Worker int done = 0;
122*00c7fec1SAndroid Build Coastguard Worker
123*00c7fec1SAndroid Build Coastguard Worker busdir = opendir(USB_FS_DIR);
124*00c7fec1SAndroid Build Coastguard Worker if(busdir == 0) return 0;
125*00c7fec1SAndroid Build Coastguard Worker
126*00c7fec1SAndroid Build Coastguard Worker while ((de = readdir(busdir)) != 0 && !done) {
127*00c7fec1SAndroid Build Coastguard Worker if(badname(de->d_name)) continue;
128*00c7fec1SAndroid Build Coastguard Worker
129*00c7fec1SAndroid Build Coastguard Worker snprintf(busname, sizeof(busname), USB_FS_DIR "/%s", de->d_name);
130*00c7fec1SAndroid Build Coastguard Worker done = find_existing_devices_bus(busname, added_cb,
131*00c7fec1SAndroid Build Coastguard Worker client_data);
132*00c7fec1SAndroid Build Coastguard Worker } //end of busdir while
133*00c7fec1SAndroid Build Coastguard Worker closedir(busdir);
134*00c7fec1SAndroid Build Coastguard Worker
135*00c7fec1SAndroid Build Coastguard Worker return done;
136*00c7fec1SAndroid Build Coastguard Worker }
137*00c7fec1SAndroid Build Coastguard Worker
watch_existing_subdirs(struct usb_host_context * context,int * wds,int wd_count)138*00c7fec1SAndroid Build Coastguard Worker static void watch_existing_subdirs(struct usb_host_context *context,
139*00c7fec1SAndroid Build Coastguard Worker int *wds, int wd_count)
140*00c7fec1SAndroid Build Coastguard Worker {
141*00c7fec1SAndroid Build Coastguard Worker char path[100];
142*00c7fec1SAndroid Build Coastguard Worker int i, ret;
143*00c7fec1SAndroid Build Coastguard Worker
144*00c7fec1SAndroid Build Coastguard Worker wds[0] = inotify_add_watch(context->fd, USB_FS_DIR, IN_CREATE | IN_DELETE);
145*00c7fec1SAndroid Build Coastguard Worker if (wds[0] < 0)
146*00c7fec1SAndroid Build Coastguard Worker return;
147*00c7fec1SAndroid Build Coastguard Worker
148*00c7fec1SAndroid Build Coastguard Worker /* watch existing subdirectories of USB_FS_DIR */
149*00c7fec1SAndroid Build Coastguard Worker for (i = 1; i < wd_count; i++) {
150*00c7fec1SAndroid Build Coastguard Worker snprintf(path, sizeof(path), USB_FS_DIR "/%03d", i);
151*00c7fec1SAndroid Build Coastguard Worker ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE);
152*00c7fec1SAndroid Build Coastguard Worker if (ret >= 0)
153*00c7fec1SAndroid Build Coastguard Worker wds[i] = ret;
154*00c7fec1SAndroid Build Coastguard Worker }
155*00c7fec1SAndroid Build Coastguard Worker }
156*00c7fec1SAndroid Build Coastguard Worker
usb_host_init()157*00c7fec1SAndroid Build Coastguard Worker struct usb_host_context *usb_host_init()
158*00c7fec1SAndroid Build Coastguard Worker {
159*00c7fec1SAndroid Build Coastguard Worker struct usb_host_context *context = calloc(1, sizeof(struct usb_host_context));
160*00c7fec1SAndroid Build Coastguard Worker if (!context) {
161*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "out of memory in usb_host_context\n");
162*00c7fec1SAndroid Build Coastguard Worker return NULL;
163*00c7fec1SAndroid Build Coastguard Worker }
164*00c7fec1SAndroid Build Coastguard Worker context->fd = inotify_init();
165*00c7fec1SAndroid Build Coastguard Worker if (context->fd < 0) {
166*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "inotify_init failed\n");
167*00c7fec1SAndroid Build Coastguard Worker free(context);
168*00c7fec1SAndroid Build Coastguard Worker return NULL;
169*00c7fec1SAndroid Build Coastguard Worker }
170*00c7fec1SAndroid Build Coastguard Worker return context;
171*00c7fec1SAndroid Build Coastguard Worker }
172*00c7fec1SAndroid Build Coastguard Worker
usb_host_cleanup(struct usb_host_context * context)173*00c7fec1SAndroid Build Coastguard Worker void usb_host_cleanup(struct usb_host_context *context)
174*00c7fec1SAndroid Build Coastguard Worker {
175*00c7fec1SAndroid Build Coastguard Worker close(context->fd);
176*00c7fec1SAndroid Build Coastguard Worker free(context);
177*00c7fec1SAndroid Build Coastguard Worker }
178*00c7fec1SAndroid Build Coastguard Worker
usb_host_get_fd(struct usb_host_context * context)179*00c7fec1SAndroid Build Coastguard Worker int usb_host_get_fd(struct usb_host_context *context)
180*00c7fec1SAndroid Build Coastguard Worker {
181*00c7fec1SAndroid Build Coastguard Worker return context->fd;
182*00c7fec1SAndroid Build Coastguard Worker } /* usb_host_get_fd() */
183*00c7fec1SAndroid Build Coastguard Worker
usb_host_load(struct usb_host_context * context,usb_device_added_cb added_cb,usb_device_removed_cb removed_cb,usb_discovery_done_cb discovery_done_cb,void * client_data)184*00c7fec1SAndroid Build Coastguard Worker int usb_host_load(struct usb_host_context *context,
185*00c7fec1SAndroid Build Coastguard Worker usb_device_added_cb added_cb,
186*00c7fec1SAndroid Build Coastguard Worker usb_device_removed_cb removed_cb,
187*00c7fec1SAndroid Build Coastguard Worker usb_discovery_done_cb discovery_done_cb,
188*00c7fec1SAndroid Build Coastguard Worker void *client_data)
189*00c7fec1SAndroid Build Coastguard Worker {
190*00c7fec1SAndroid Build Coastguard Worker int done = 0;
191*00c7fec1SAndroid Build Coastguard Worker int i;
192*00c7fec1SAndroid Build Coastguard Worker
193*00c7fec1SAndroid Build Coastguard Worker context->cb_added = added_cb;
194*00c7fec1SAndroid Build Coastguard Worker context->cb_removed = removed_cb;
195*00c7fec1SAndroid Build Coastguard Worker context->data = client_data;
196*00c7fec1SAndroid Build Coastguard Worker
197*00c7fec1SAndroid Build Coastguard Worker D("Created device discovery thread\n");
198*00c7fec1SAndroid Build Coastguard Worker
199*00c7fec1SAndroid Build Coastguard Worker /* watch for files added and deleted within USB_FS_DIR */
200*00c7fec1SAndroid Build Coastguard Worker context->wddbus = -1;
201*00c7fec1SAndroid Build Coastguard Worker for (i = 0; i < MAX_USBFS_WD_COUNT; i++)
202*00c7fec1SAndroid Build Coastguard Worker context->wds[i] = -1;
203*00c7fec1SAndroid Build Coastguard Worker
204*00c7fec1SAndroid Build Coastguard Worker /* watch the root for new subdirectories */
205*00c7fec1SAndroid Build Coastguard Worker context->wdd = inotify_add_watch(context->fd, DEV_DIR, IN_CREATE | IN_DELETE);
206*00c7fec1SAndroid Build Coastguard Worker if (context->wdd < 0) {
207*00c7fec1SAndroid Build Coastguard Worker fprintf(stderr, "inotify_add_watch failed\n");
208*00c7fec1SAndroid Build Coastguard Worker if (discovery_done_cb)
209*00c7fec1SAndroid Build Coastguard Worker discovery_done_cb(client_data);
210*00c7fec1SAndroid Build Coastguard Worker return done;
211*00c7fec1SAndroid Build Coastguard Worker }
212*00c7fec1SAndroid Build Coastguard Worker
213*00c7fec1SAndroid Build Coastguard Worker watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
214*00c7fec1SAndroid Build Coastguard Worker
215*00c7fec1SAndroid Build Coastguard Worker /* check for existing devices first, after we have inotify set up */
216*00c7fec1SAndroid Build Coastguard Worker done = find_existing_devices(added_cb, client_data);
217*00c7fec1SAndroid Build Coastguard Worker if (discovery_done_cb)
218*00c7fec1SAndroid Build Coastguard Worker done |= discovery_done_cb(client_data);
219*00c7fec1SAndroid Build Coastguard Worker
220*00c7fec1SAndroid Build Coastguard Worker return done;
221*00c7fec1SAndroid Build Coastguard Worker } /* usb_host_load() */
222*00c7fec1SAndroid Build Coastguard Worker
usb_host_read_event(struct usb_host_context * context)223*00c7fec1SAndroid Build Coastguard Worker int usb_host_read_event(struct usb_host_context *context)
224*00c7fec1SAndroid Build Coastguard Worker {
225*00c7fec1SAndroid Build Coastguard Worker struct inotify_event* event;
226*00c7fec1SAndroid Build Coastguard Worker char event_buf[512];
227*00c7fec1SAndroid Build Coastguard Worker char path[100];
228*00c7fec1SAndroid Build Coastguard Worker int i, ret, done = 0;
229*00c7fec1SAndroid Build Coastguard Worker int offset = 0;
230*00c7fec1SAndroid Build Coastguard Worker int wd;
231*00c7fec1SAndroid Build Coastguard Worker
232*00c7fec1SAndroid Build Coastguard Worker ret = read(context->fd, event_buf, sizeof(event_buf));
233*00c7fec1SAndroid Build Coastguard Worker if (ret >= (int)sizeof(struct inotify_event)) {
234*00c7fec1SAndroid Build Coastguard Worker while (offset < ret && !done) {
235*00c7fec1SAndroid Build Coastguard Worker event = (struct inotify_event*)&event_buf[offset];
236*00c7fec1SAndroid Build Coastguard Worker done = 0;
237*00c7fec1SAndroid Build Coastguard Worker wd = event->wd;
238*00c7fec1SAndroid Build Coastguard Worker if (wd == context->wdd) {
239*00c7fec1SAndroid Build Coastguard Worker if ((event->mask & IN_CREATE) && !strcmp(event->name, "bus")) {
240*00c7fec1SAndroid Build Coastguard Worker context->wddbus = inotify_add_watch(context->fd, DEV_BUS_DIR, IN_CREATE | IN_DELETE);
241*00c7fec1SAndroid Build Coastguard Worker if (context->wddbus < 0) {
242*00c7fec1SAndroid Build Coastguard Worker done = 1;
243*00c7fec1SAndroid Build Coastguard Worker } else {
244*00c7fec1SAndroid Build Coastguard Worker watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
245*00c7fec1SAndroid Build Coastguard Worker done = find_existing_devices(context->cb_added, context->data);
246*00c7fec1SAndroid Build Coastguard Worker }
247*00c7fec1SAndroid Build Coastguard Worker }
248*00c7fec1SAndroid Build Coastguard Worker } else if (wd == context->wddbus) {
249*00c7fec1SAndroid Build Coastguard Worker if ((event->mask & IN_CREATE) && !strcmp(event->name, "usb")) {
250*00c7fec1SAndroid Build Coastguard Worker watch_existing_subdirs(context, context->wds, MAX_USBFS_WD_COUNT);
251*00c7fec1SAndroid Build Coastguard Worker done = find_existing_devices(context->cb_added, context->data);
252*00c7fec1SAndroid Build Coastguard Worker } else if ((event->mask & IN_DELETE) && !strcmp(event->name, "usb")) {
253*00c7fec1SAndroid Build Coastguard Worker for (i = 0; i < MAX_USBFS_WD_COUNT; i++) {
254*00c7fec1SAndroid Build Coastguard Worker if (context->wds[i] >= 0) {
255*00c7fec1SAndroid Build Coastguard Worker inotify_rm_watch(context->fd, context->wds[i]);
256*00c7fec1SAndroid Build Coastguard Worker context->wds[i] = -1;
257*00c7fec1SAndroid Build Coastguard Worker }
258*00c7fec1SAndroid Build Coastguard Worker }
259*00c7fec1SAndroid Build Coastguard Worker }
260*00c7fec1SAndroid Build Coastguard Worker } else if (wd == context->wds[0]) {
261*00c7fec1SAndroid Build Coastguard Worker i = atoi(event->name);
262*00c7fec1SAndroid Build Coastguard Worker snprintf(path, sizeof(path), USB_FS_DIR "/%s", event->name);
263*00c7fec1SAndroid Build Coastguard Worker D("%s subdirectory %s: index: %d\n", (event->mask & IN_CREATE) ?
264*00c7fec1SAndroid Build Coastguard Worker "new" : "gone", path, i);
265*00c7fec1SAndroid Build Coastguard Worker if (i > 0 && i < MAX_USBFS_WD_COUNT) {
266*00c7fec1SAndroid Build Coastguard Worker int local_ret = 0;
267*00c7fec1SAndroid Build Coastguard Worker if (event->mask & IN_CREATE) {
268*00c7fec1SAndroid Build Coastguard Worker local_ret = inotify_add_watch(context->fd, path,
269*00c7fec1SAndroid Build Coastguard Worker IN_CREATE | IN_DELETE);
270*00c7fec1SAndroid Build Coastguard Worker if (local_ret >= 0)
271*00c7fec1SAndroid Build Coastguard Worker context->wds[i] = local_ret;
272*00c7fec1SAndroid Build Coastguard Worker done = find_existing_devices_bus(path, context->cb_added,
273*00c7fec1SAndroid Build Coastguard Worker context->data);
274*00c7fec1SAndroid Build Coastguard Worker } else if (event->mask & IN_DELETE) {
275*00c7fec1SAndroid Build Coastguard Worker inotify_rm_watch(context->fd, context->wds[i]);
276*00c7fec1SAndroid Build Coastguard Worker context->wds[i] = -1;
277*00c7fec1SAndroid Build Coastguard Worker }
278*00c7fec1SAndroid Build Coastguard Worker }
279*00c7fec1SAndroid Build Coastguard Worker } else {
280*00c7fec1SAndroid Build Coastguard Worker for (i = 1; (i < MAX_USBFS_WD_COUNT) && !done; i++) {
281*00c7fec1SAndroid Build Coastguard Worker if (wd == context->wds[i]) {
282*00c7fec1SAndroid Build Coastguard Worker snprintf(path, sizeof(path), USB_FS_DIR "/%03d/%s", i, event->name);
283*00c7fec1SAndroid Build Coastguard Worker if (event->mask == IN_CREATE) {
284*00c7fec1SAndroid Build Coastguard Worker D("new device %s\n", path);
285*00c7fec1SAndroid Build Coastguard Worker done = context->cb_added(path, context->data);
286*00c7fec1SAndroid Build Coastguard Worker } else if (event->mask == IN_DELETE) {
287*00c7fec1SAndroid Build Coastguard Worker D("gone device %s\n", path);
288*00c7fec1SAndroid Build Coastguard Worker done = context->cb_removed(path, context->data);
289*00c7fec1SAndroid Build Coastguard Worker }
290*00c7fec1SAndroid Build Coastguard Worker }
291*00c7fec1SAndroid Build Coastguard Worker }
292*00c7fec1SAndroid Build Coastguard Worker }
293*00c7fec1SAndroid Build Coastguard Worker
294*00c7fec1SAndroid Build Coastguard Worker offset += sizeof(struct inotify_event) + event->len;
295*00c7fec1SAndroid Build Coastguard Worker }
296*00c7fec1SAndroid Build Coastguard Worker }
297*00c7fec1SAndroid Build Coastguard Worker
298*00c7fec1SAndroid Build Coastguard Worker return done;
299*00c7fec1SAndroid Build Coastguard Worker } /* usb_host_read_event() */
300*00c7fec1SAndroid Build Coastguard Worker
usb_host_run(struct usb_host_context * context,usb_device_added_cb added_cb,usb_device_removed_cb removed_cb,usb_discovery_done_cb discovery_done_cb,void * client_data)301*00c7fec1SAndroid Build Coastguard Worker void usb_host_run(struct usb_host_context *context,
302*00c7fec1SAndroid Build Coastguard Worker usb_device_added_cb added_cb,
303*00c7fec1SAndroid Build Coastguard Worker usb_device_removed_cb removed_cb,
304*00c7fec1SAndroid Build Coastguard Worker usb_discovery_done_cb discovery_done_cb,
305*00c7fec1SAndroid Build Coastguard Worker void *client_data)
306*00c7fec1SAndroid Build Coastguard Worker {
307*00c7fec1SAndroid Build Coastguard Worker int done;
308*00c7fec1SAndroid Build Coastguard Worker
309*00c7fec1SAndroid Build Coastguard Worker done = usb_host_load(context, added_cb, removed_cb, discovery_done_cb, client_data);
310*00c7fec1SAndroid Build Coastguard Worker
311*00c7fec1SAndroid Build Coastguard Worker while (!done) {
312*00c7fec1SAndroid Build Coastguard Worker
313*00c7fec1SAndroid Build Coastguard Worker done = usb_host_read_event(context);
314*00c7fec1SAndroid Build Coastguard Worker }
315*00c7fec1SAndroid Build Coastguard Worker } /* usb_host_run() */
316*00c7fec1SAndroid Build Coastguard Worker
usb_device_open(const char * dev_name)317*00c7fec1SAndroid Build Coastguard Worker struct usb_device *usb_device_open(const char *dev_name)
318*00c7fec1SAndroid Build Coastguard Worker {
319*00c7fec1SAndroid Build Coastguard Worker int fd, attempts, writeable = 1;
320*00c7fec1SAndroid Build Coastguard Worker const int SLEEP_BETWEEN_ATTEMPTS_US = 100000; /* 100 ms */
321*00c7fec1SAndroid Build Coastguard Worker const int64_t MAX_ATTEMPTS = 10; /* 1s */
322*00c7fec1SAndroid Build Coastguard Worker D("usb_device_open %s\n", dev_name);
323*00c7fec1SAndroid Build Coastguard Worker
324*00c7fec1SAndroid Build Coastguard Worker /* Hack around waiting for permissions to be set on the USB device node.
325*00c7fec1SAndroid Build Coastguard Worker * Should really be a timeout instead of attempt count, and should REALLY
326*00c7fec1SAndroid Build Coastguard Worker * be triggered by the perm change via inotify rather than polling.
327*00c7fec1SAndroid Build Coastguard Worker */
328*00c7fec1SAndroid Build Coastguard Worker for (attempts = 0; attempts < MAX_ATTEMPTS; ++attempts) {
329*00c7fec1SAndroid Build Coastguard Worker if (access(dev_name, R_OK | W_OK) == 0) {
330*00c7fec1SAndroid Build Coastguard Worker writeable = 1;
331*00c7fec1SAndroid Build Coastguard Worker break;
332*00c7fec1SAndroid Build Coastguard Worker } else {
333*00c7fec1SAndroid Build Coastguard Worker if (access(dev_name, R_OK) == 0) {
334*00c7fec1SAndroid Build Coastguard Worker /* double check that write permission didn't just come along too! */
335*00c7fec1SAndroid Build Coastguard Worker writeable = (access(dev_name, R_OK | W_OK) == 0);
336*00c7fec1SAndroid Build Coastguard Worker break;
337*00c7fec1SAndroid Build Coastguard Worker }
338*00c7fec1SAndroid Build Coastguard Worker }
339*00c7fec1SAndroid Build Coastguard Worker /* not writeable or readable - sleep and try again. */
340*00c7fec1SAndroid Build Coastguard Worker D("usb_device_open no access sleeping\n");
341*00c7fec1SAndroid Build Coastguard Worker usleep(SLEEP_BETWEEN_ATTEMPTS_US);
342*00c7fec1SAndroid Build Coastguard Worker }
343*00c7fec1SAndroid Build Coastguard Worker
344*00c7fec1SAndroid Build Coastguard Worker if (writeable) {
345*00c7fec1SAndroid Build Coastguard Worker fd = open(dev_name, O_RDWR);
346*00c7fec1SAndroid Build Coastguard Worker } else {
347*00c7fec1SAndroid Build Coastguard Worker fd = open(dev_name, O_RDONLY);
348*00c7fec1SAndroid Build Coastguard Worker }
349*00c7fec1SAndroid Build Coastguard Worker D("usb_device_open open returned %d writeable %d errno %d\n", fd, writeable, errno);
350*00c7fec1SAndroid Build Coastguard Worker if (fd < 0) return NULL;
351*00c7fec1SAndroid Build Coastguard Worker
352*00c7fec1SAndroid Build Coastguard Worker struct usb_device* result = usb_device_new(dev_name, fd);
353*00c7fec1SAndroid Build Coastguard Worker if (result)
354*00c7fec1SAndroid Build Coastguard Worker result->writeable = writeable;
355*00c7fec1SAndroid Build Coastguard Worker return result;
356*00c7fec1SAndroid Build Coastguard Worker }
357*00c7fec1SAndroid Build Coastguard Worker
usb_device_close(struct usb_device * device)358*00c7fec1SAndroid Build Coastguard Worker void usb_device_close(struct usb_device *device)
359*00c7fec1SAndroid Build Coastguard Worker {
360*00c7fec1SAndroid Build Coastguard Worker close(device->fd);
361*00c7fec1SAndroid Build Coastguard Worker free(device);
362*00c7fec1SAndroid Build Coastguard Worker }
363*00c7fec1SAndroid Build Coastguard Worker
usb_device_new(const char * dev_name,int fd)364*00c7fec1SAndroid Build Coastguard Worker struct usb_device *usb_device_new(const char *dev_name, int fd)
365*00c7fec1SAndroid Build Coastguard Worker {
366*00c7fec1SAndroid Build Coastguard Worker struct usb_device *device = calloc(1, sizeof(struct usb_device));
367*00c7fec1SAndroid Build Coastguard Worker int length;
368*00c7fec1SAndroid Build Coastguard Worker
369*00c7fec1SAndroid Build Coastguard Worker D("usb_device_new %s fd: %d\n", dev_name, fd);
370*00c7fec1SAndroid Build Coastguard Worker
371*00c7fec1SAndroid Build Coastguard Worker if (lseek(fd, 0, SEEK_SET) != 0)
372*00c7fec1SAndroid Build Coastguard Worker goto failed;
373*00c7fec1SAndroid Build Coastguard Worker length = read(fd, device->desc, sizeof(device->desc));
374*00c7fec1SAndroid Build Coastguard Worker D("usb_device_new read returned %d errno %d\n", length, errno);
375*00c7fec1SAndroid Build Coastguard Worker if (length < 0)
376*00c7fec1SAndroid Build Coastguard Worker goto failed;
377*00c7fec1SAndroid Build Coastguard Worker
378*00c7fec1SAndroid Build Coastguard Worker strncpy(device->dev_name, dev_name, sizeof(device->dev_name) - 1);
379*00c7fec1SAndroid Build Coastguard Worker device->fd = fd;
380*00c7fec1SAndroid Build Coastguard Worker device->desc_length = length;
381*00c7fec1SAndroid Build Coastguard Worker // assume we are writeable, since usb_device_get_fd will only return writeable fds
382*00c7fec1SAndroid Build Coastguard Worker device->writeable = 1;
383*00c7fec1SAndroid Build Coastguard Worker return device;
384*00c7fec1SAndroid Build Coastguard Worker
385*00c7fec1SAndroid Build Coastguard Worker failed:
386*00c7fec1SAndroid Build Coastguard Worker // TODO It would be more appropriate to have callers do this
387*00c7fec1SAndroid Build Coastguard Worker // since this function doesn't "own" this file descriptor.
388*00c7fec1SAndroid Build Coastguard Worker close(fd);
389*00c7fec1SAndroid Build Coastguard Worker free(device);
390*00c7fec1SAndroid Build Coastguard Worker return NULL;
391*00c7fec1SAndroid Build Coastguard Worker }
392*00c7fec1SAndroid Build Coastguard Worker
usb_device_reopen_writeable(struct usb_device * device)393*00c7fec1SAndroid Build Coastguard Worker static int usb_device_reopen_writeable(struct usb_device *device)
394*00c7fec1SAndroid Build Coastguard Worker {
395*00c7fec1SAndroid Build Coastguard Worker if (device->writeable)
396*00c7fec1SAndroid Build Coastguard Worker return 1;
397*00c7fec1SAndroid Build Coastguard Worker
398*00c7fec1SAndroid Build Coastguard Worker int fd = open(device->dev_name, O_RDWR);
399*00c7fec1SAndroid Build Coastguard Worker if (fd >= 0) {
400*00c7fec1SAndroid Build Coastguard Worker close(device->fd);
401*00c7fec1SAndroid Build Coastguard Worker device->fd = fd;
402*00c7fec1SAndroid Build Coastguard Worker device->writeable = 1;
403*00c7fec1SAndroid Build Coastguard Worker return 1;
404*00c7fec1SAndroid Build Coastguard Worker }
405*00c7fec1SAndroid Build Coastguard Worker D("usb_device_reopen_writeable failed errno %d\n", errno);
406*00c7fec1SAndroid Build Coastguard Worker return 0;
407*00c7fec1SAndroid Build Coastguard Worker }
408*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_fd(struct usb_device * device)409*00c7fec1SAndroid Build Coastguard Worker int usb_device_get_fd(struct usb_device *device)
410*00c7fec1SAndroid Build Coastguard Worker {
411*00c7fec1SAndroid Build Coastguard Worker if (!usb_device_reopen_writeable(device))
412*00c7fec1SAndroid Build Coastguard Worker return -1;
413*00c7fec1SAndroid Build Coastguard Worker return device->fd;
414*00c7fec1SAndroid Build Coastguard Worker }
415*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_name(struct usb_device * device)416*00c7fec1SAndroid Build Coastguard Worker const char* usb_device_get_name(struct usb_device *device)
417*00c7fec1SAndroid Build Coastguard Worker {
418*00c7fec1SAndroid Build Coastguard Worker return device->dev_name;
419*00c7fec1SAndroid Build Coastguard Worker }
420*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_unique_id(struct usb_device * device)421*00c7fec1SAndroid Build Coastguard Worker int usb_device_get_unique_id(struct usb_device *device)
422*00c7fec1SAndroid Build Coastguard Worker {
423*00c7fec1SAndroid Build Coastguard Worker int bus = 0, dev = 0;
424*00c7fec1SAndroid Build Coastguard Worker sscanf(device->dev_name, USB_FS_ID_SCANNER, &bus, &dev);
425*00c7fec1SAndroid Build Coastguard Worker return bus * 1000 + dev;
426*00c7fec1SAndroid Build Coastguard Worker }
427*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_unique_id_from_name(const char * name)428*00c7fec1SAndroid Build Coastguard Worker int usb_device_get_unique_id_from_name(const char* name)
429*00c7fec1SAndroid Build Coastguard Worker {
430*00c7fec1SAndroid Build Coastguard Worker int bus = 0, dev = 0;
431*00c7fec1SAndroid Build Coastguard Worker sscanf(name, USB_FS_ID_SCANNER, &bus, &dev);
432*00c7fec1SAndroid Build Coastguard Worker return bus * 1000 + dev;
433*00c7fec1SAndroid Build Coastguard Worker }
434*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_name_from_unique_id(int id)435*00c7fec1SAndroid Build Coastguard Worker char* usb_device_get_name_from_unique_id(int id)
436*00c7fec1SAndroid Build Coastguard Worker {
437*00c7fec1SAndroid Build Coastguard Worker int bus = id / 1000;
438*00c7fec1SAndroid Build Coastguard Worker int dev = id % 1000;
439*00c7fec1SAndroid Build Coastguard Worker char* result = (char *)calloc(1, strlen(USB_FS_ID_FORMAT));
440*00c7fec1SAndroid Build Coastguard Worker snprintf(result, strlen(USB_FS_ID_FORMAT) - 1, USB_FS_ID_FORMAT, bus, dev);
441*00c7fec1SAndroid Build Coastguard Worker return result;
442*00c7fec1SAndroid Build Coastguard Worker }
443*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_vendor_id(struct usb_device * device)444*00c7fec1SAndroid Build Coastguard Worker uint16_t usb_device_get_vendor_id(struct usb_device *device)
445*00c7fec1SAndroid Build Coastguard Worker {
446*00c7fec1SAndroid Build Coastguard Worker struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc;
447*00c7fec1SAndroid Build Coastguard Worker return __le16_to_cpu(desc->idVendor);
448*00c7fec1SAndroid Build Coastguard Worker }
449*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_product_id(struct usb_device * device)450*00c7fec1SAndroid Build Coastguard Worker uint16_t usb_device_get_product_id(struct usb_device *device)
451*00c7fec1SAndroid Build Coastguard Worker {
452*00c7fec1SAndroid Build Coastguard Worker struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc;
453*00c7fec1SAndroid Build Coastguard Worker return __le16_to_cpu(desc->idProduct);
454*00c7fec1SAndroid Build Coastguard Worker }
455*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_device_descriptor(struct usb_device * device)456*00c7fec1SAndroid Build Coastguard Worker const struct usb_device_descriptor* usb_device_get_device_descriptor(struct usb_device* device) {
457*00c7fec1SAndroid Build Coastguard Worker return (struct usb_device_descriptor*)device->desc;
458*00c7fec1SAndroid Build Coastguard Worker }
459*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_descriptors_length(const struct usb_device * device)460*00c7fec1SAndroid Build Coastguard Worker size_t usb_device_get_descriptors_length(const struct usb_device* device) {
461*00c7fec1SAndroid Build Coastguard Worker return device->desc_length;
462*00c7fec1SAndroid Build Coastguard Worker }
463*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_raw_descriptors(const struct usb_device * device)464*00c7fec1SAndroid Build Coastguard Worker const unsigned char* usb_device_get_raw_descriptors(const struct usb_device* device) {
465*00c7fec1SAndroid Build Coastguard Worker return device->desc;
466*00c7fec1SAndroid Build Coastguard Worker }
467*00c7fec1SAndroid Build Coastguard Worker
468*00c7fec1SAndroid Build Coastguard Worker /* Returns a USB descriptor string for the given string ID.
469*00c7fec1SAndroid Build Coastguard Worker * Return value: < 0 on error. 0 on success.
470*00c7fec1SAndroid Build Coastguard Worker * The string is returned in ucs2_out in USB-native UCS-2 encoding.
471*00c7fec1SAndroid Build Coastguard Worker *
472*00c7fec1SAndroid Build Coastguard Worker * parameters:
473*00c7fec1SAndroid Build Coastguard Worker * id - the string descriptor index.
474*00c7fec1SAndroid Build Coastguard Worker * timeout - in milliseconds (see Documentation/driver-api/usb/usb.rst)
475*00c7fec1SAndroid Build Coastguard Worker * ucs2_out - Must point to null on call.
476*00c7fec1SAndroid Build Coastguard Worker * Will be filled in with a buffer on success.
477*00c7fec1SAndroid Build Coastguard Worker * If this is non-null on return, it must be free()d.
478*00c7fec1SAndroid Build Coastguard Worker * response_size - size, in bytes, of ucs-2 string in ucs2_out.
479*00c7fec1SAndroid Build Coastguard Worker * The size isn't guaranteed to include null termination.
480*00c7fec1SAndroid Build Coastguard Worker * Call free() to free the result when you are done with it.
481*00c7fec1SAndroid Build Coastguard Worker */
usb_device_get_string_ucs2(struct usb_device * device,int id,int timeout,void ** ucs2_out,size_t * response_size)482*00c7fec1SAndroid Build Coastguard Worker int usb_device_get_string_ucs2(struct usb_device* device, int id, int timeout, void** ucs2_out,
483*00c7fec1SAndroid Build Coastguard Worker size_t* response_size) {
484*00c7fec1SAndroid Build Coastguard Worker __u16 languages[MAX_STRING_DESCRIPTOR_LENGTH / sizeof(__u16)];
485*00c7fec1SAndroid Build Coastguard Worker char response[MAX_STRING_DESCRIPTOR_LENGTH];
486*00c7fec1SAndroid Build Coastguard Worker int result;
487*00c7fec1SAndroid Build Coastguard Worker int languageCount = 0;
488*00c7fec1SAndroid Build Coastguard Worker
489*00c7fec1SAndroid Build Coastguard Worker if (id == 0) return -1;
490*00c7fec1SAndroid Build Coastguard Worker if (*ucs2_out != NULL) return -1;
491*00c7fec1SAndroid Build Coastguard Worker
492*00c7fec1SAndroid Build Coastguard Worker memset(languages, 0, sizeof(languages));
493*00c7fec1SAndroid Build Coastguard Worker
494*00c7fec1SAndroid Build Coastguard Worker // read list of supported languages
495*00c7fec1SAndroid Build Coastguard Worker result = usb_device_control_transfer(device,
496*00c7fec1SAndroid Build Coastguard Worker USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR,
497*00c7fec1SAndroid Build Coastguard Worker (USB_DT_STRING << 8) | 0, 0, languages, sizeof(languages),
498*00c7fec1SAndroid Build Coastguard Worker timeout);
499*00c7fec1SAndroid Build Coastguard Worker if (result > 0)
500*00c7fec1SAndroid Build Coastguard Worker languageCount = (result - 2) / 2;
501*00c7fec1SAndroid Build Coastguard Worker
502*00c7fec1SAndroid Build Coastguard Worker for (int i = 1; i <= languageCount; i++) {
503*00c7fec1SAndroid Build Coastguard Worker memset(response, 0, sizeof(response));
504*00c7fec1SAndroid Build Coastguard Worker
505*00c7fec1SAndroid Build Coastguard Worker result = usb_device_control_transfer(
506*00c7fec1SAndroid Build Coastguard Worker device, USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR,
507*00c7fec1SAndroid Build Coastguard Worker (USB_DT_STRING << 8) | id, languages[i], response, sizeof(response), timeout);
508*00c7fec1SAndroid Build Coastguard Worker if (result >= 2) { // string contents begin at offset 2.
509*00c7fec1SAndroid Build Coastguard Worker int descriptor_len = result - 2;
510*00c7fec1SAndroid Build Coastguard Worker char* out = malloc(descriptor_len + 3);
511*00c7fec1SAndroid Build Coastguard Worker if (out == NULL) {
512*00c7fec1SAndroid Build Coastguard Worker return -1;
513*00c7fec1SAndroid Build Coastguard Worker }
514*00c7fec1SAndroid Build Coastguard Worker memcpy(out, response + 2, descriptor_len);
515*00c7fec1SAndroid Build Coastguard Worker // trail with three additional NULLs, so that there's guaranteed
516*00c7fec1SAndroid Build Coastguard Worker // to be a UCS-2 NULL character beyond whatever USB returned.
517*00c7fec1SAndroid Build Coastguard Worker // The returned string length is still just what USB returned.
518*00c7fec1SAndroid Build Coastguard Worker memset(out + descriptor_len, '\0', 3);
519*00c7fec1SAndroid Build Coastguard Worker *ucs2_out = (void*)out;
520*00c7fec1SAndroid Build Coastguard Worker *response_size = descriptor_len;
521*00c7fec1SAndroid Build Coastguard Worker return 0;
522*00c7fec1SAndroid Build Coastguard Worker }
523*00c7fec1SAndroid Build Coastguard Worker }
524*00c7fec1SAndroid Build Coastguard Worker return -1;
525*00c7fec1SAndroid Build Coastguard Worker }
526*00c7fec1SAndroid Build Coastguard Worker
527*00c7fec1SAndroid Build Coastguard Worker /* Warning: previously this blindly returned the lower 8 bits of
528*00c7fec1SAndroid Build Coastguard Worker * every UCS-2 character in a USB descriptor. Now it will replace
529*00c7fec1SAndroid Build Coastguard Worker * values > 127 with ascii '?'.
530*00c7fec1SAndroid Build Coastguard Worker */
usb_device_get_string(struct usb_device * device,int id,int timeout)531*00c7fec1SAndroid Build Coastguard Worker char* usb_device_get_string(struct usb_device* device, int id, int timeout) {
532*00c7fec1SAndroid Build Coastguard Worker char* ascii_string = NULL;
533*00c7fec1SAndroid Build Coastguard Worker size_t raw_string_len = 0;
534*00c7fec1SAndroid Build Coastguard Worker size_t i;
535*00c7fec1SAndroid Build Coastguard Worker if (usb_device_get_string_ucs2(device, id, timeout, (void**)&ascii_string, &raw_string_len) < 0)
536*00c7fec1SAndroid Build Coastguard Worker return NULL;
537*00c7fec1SAndroid Build Coastguard Worker if (ascii_string == NULL) return NULL;
538*00c7fec1SAndroid Build Coastguard Worker for (i = 0; i < raw_string_len / 2; ++i) {
539*00c7fec1SAndroid Build Coastguard Worker // wire format for USB is always little-endian.
540*00c7fec1SAndroid Build Coastguard Worker char lower = ascii_string[2 * i];
541*00c7fec1SAndroid Build Coastguard Worker char upper = ascii_string[2 * i + 1];
542*00c7fec1SAndroid Build Coastguard Worker if (upper || (lower & 0x80)) {
543*00c7fec1SAndroid Build Coastguard Worker ascii_string[i] = '?';
544*00c7fec1SAndroid Build Coastguard Worker } else {
545*00c7fec1SAndroid Build Coastguard Worker ascii_string[i] = lower;
546*00c7fec1SAndroid Build Coastguard Worker }
547*00c7fec1SAndroid Build Coastguard Worker }
548*00c7fec1SAndroid Build Coastguard Worker ascii_string[i] = '\0';
549*00c7fec1SAndroid Build Coastguard Worker return ascii_string;
550*00c7fec1SAndroid Build Coastguard Worker }
551*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_manufacturer_name(struct usb_device * device,int timeout)552*00c7fec1SAndroid Build Coastguard Worker char* usb_device_get_manufacturer_name(struct usb_device *device, int timeout)
553*00c7fec1SAndroid Build Coastguard Worker {
554*00c7fec1SAndroid Build Coastguard Worker struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
555*00c7fec1SAndroid Build Coastguard Worker return usb_device_get_string(device, desc->iManufacturer, timeout);
556*00c7fec1SAndroid Build Coastguard Worker }
557*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_product_name(struct usb_device * device,int timeout)558*00c7fec1SAndroid Build Coastguard Worker char* usb_device_get_product_name(struct usb_device *device, int timeout)
559*00c7fec1SAndroid Build Coastguard Worker {
560*00c7fec1SAndroid Build Coastguard Worker struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
561*00c7fec1SAndroid Build Coastguard Worker return usb_device_get_string(device, desc->iProduct, timeout);
562*00c7fec1SAndroid Build Coastguard Worker }
563*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_version(struct usb_device * device)564*00c7fec1SAndroid Build Coastguard Worker int usb_device_get_version(struct usb_device *device)
565*00c7fec1SAndroid Build Coastguard Worker {
566*00c7fec1SAndroid Build Coastguard Worker struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
567*00c7fec1SAndroid Build Coastguard Worker return desc->bcdUSB;
568*00c7fec1SAndroid Build Coastguard Worker }
569*00c7fec1SAndroid Build Coastguard Worker
usb_device_get_serial(struct usb_device * device,int timeout)570*00c7fec1SAndroid Build Coastguard Worker char* usb_device_get_serial(struct usb_device *device, int timeout)
571*00c7fec1SAndroid Build Coastguard Worker {
572*00c7fec1SAndroid Build Coastguard Worker struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc;
573*00c7fec1SAndroid Build Coastguard Worker return usb_device_get_string(device, desc->iSerialNumber, timeout);
574*00c7fec1SAndroid Build Coastguard Worker }
575*00c7fec1SAndroid Build Coastguard Worker
usb_device_is_writeable(struct usb_device * device)576*00c7fec1SAndroid Build Coastguard Worker int usb_device_is_writeable(struct usb_device *device)
577*00c7fec1SAndroid Build Coastguard Worker {
578*00c7fec1SAndroid Build Coastguard Worker return device->writeable;
579*00c7fec1SAndroid Build Coastguard Worker }
580*00c7fec1SAndroid Build Coastguard Worker
usb_descriptor_iter_init(struct usb_device * device,struct usb_descriptor_iter * iter)581*00c7fec1SAndroid Build Coastguard Worker void usb_descriptor_iter_init(struct usb_device *device, struct usb_descriptor_iter *iter)
582*00c7fec1SAndroid Build Coastguard Worker {
583*00c7fec1SAndroid Build Coastguard Worker iter->config = device->desc;
584*00c7fec1SAndroid Build Coastguard Worker iter->config_end = device->desc + device->desc_length;
585*00c7fec1SAndroid Build Coastguard Worker iter->curr_desc = device->desc;
586*00c7fec1SAndroid Build Coastguard Worker }
587*00c7fec1SAndroid Build Coastguard Worker
usb_descriptor_iter_next(struct usb_descriptor_iter * iter)588*00c7fec1SAndroid Build Coastguard Worker struct usb_descriptor_header *usb_descriptor_iter_next(struct usb_descriptor_iter *iter)
589*00c7fec1SAndroid Build Coastguard Worker {
590*00c7fec1SAndroid Build Coastguard Worker struct usb_descriptor_header* next;
591*00c7fec1SAndroid Build Coastguard Worker if (iter->curr_desc >= iter->config_end)
592*00c7fec1SAndroid Build Coastguard Worker return NULL;
593*00c7fec1SAndroid Build Coastguard Worker next = (struct usb_descriptor_header*)iter->curr_desc;
594*00c7fec1SAndroid Build Coastguard Worker // Corrupt descriptor with zero length, cannot continue iterating
595*00c7fec1SAndroid Build Coastguard Worker if (next->bLength == 0) {
596*00c7fec1SAndroid Build Coastguard Worker D("usb_descriptor_iter_next got zero length USB descriptor, ending iteration\n");
597*00c7fec1SAndroid Build Coastguard Worker return NULL;
598*00c7fec1SAndroid Build Coastguard Worker }
599*00c7fec1SAndroid Build Coastguard Worker iter->curr_desc += next->bLength;
600*00c7fec1SAndroid Build Coastguard Worker return next;
601*00c7fec1SAndroid Build Coastguard Worker }
602*00c7fec1SAndroid Build Coastguard Worker
usb_device_claim_interface(struct usb_device * device,unsigned int interface)603*00c7fec1SAndroid Build Coastguard Worker int usb_device_claim_interface(struct usb_device *device, unsigned int interface)
604*00c7fec1SAndroid Build Coastguard Worker {
605*00c7fec1SAndroid Build Coastguard Worker return ioctl(device->fd, USBDEVFS_CLAIMINTERFACE, &interface);
606*00c7fec1SAndroid Build Coastguard Worker }
607*00c7fec1SAndroid Build Coastguard Worker
usb_device_release_interface(struct usb_device * device,unsigned int interface)608*00c7fec1SAndroid Build Coastguard Worker int usb_device_release_interface(struct usb_device *device, unsigned int interface)
609*00c7fec1SAndroid Build Coastguard Worker {
610*00c7fec1SAndroid Build Coastguard Worker return ioctl(device->fd, USBDEVFS_RELEASEINTERFACE, &interface);
611*00c7fec1SAndroid Build Coastguard Worker }
612*00c7fec1SAndroid Build Coastguard Worker
usb_device_connect_kernel_driver(struct usb_device * device,unsigned int interface,int connect)613*00c7fec1SAndroid Build Coastguard Worker int usb_device_connect_kernel_driver(struct usb_device *device,
614*00c7fec1SAndroid Build Coastguard Worker unsigned int interface, int connect)
615*00c7fec1SAndroid Build Coastguard Worker {
616*00c7fec1SAndroid Build Coastguard Worker struct usbdevfs_ioctl ctl;
617*00c7fec1SAndroid Build Coastguard Worker
618*00c7fec1SAndroid Build Coastguard Worker ctl.ifno = interface;
619*00c7fec1SAndroid Build Coastguard Worker ctl.ioctl_code = (connect ? USBDEVFS_CONNECT : USBDEVFS_DISCONNECT);
620*00c7fec1SAndroid Build Coastguard Worker ctl.data = NULL;
621*00c7fec1SAndroid Build Coastguard Worker return ioctl(device->fd, USBDEVFS_IOCTL, &ctl);
622*00c7fec1SAndroid Build Coastguard Worker }
623*00c7fec1SAndroid Build Coastguard Worker
usb_device_set_configuration(struct usb_device * device,int configuration)624*00c7fec1SAndroid Build Coastguard Worker int usb_device_set_configuration(struct usb_device *device, int configuration)
625*00c7fec1SAndroid Build Coastguard Worker {
626*00c7fec1SAndroid Build Coastguard Worker return ioctl(device->fd, USBDEVFS_SETCONFIGURATION, &configuration);
627*00c7fec1SAndroid Build Coastguard Worker }
628*00c7fec1SAndroid Build Coastguard Worker
usb_device_set_interface(struct usb_device * device,unsigned int interface,unsigned int alt_setting)629*00c7fec1SAndroid Build Coastguard Worker int usb_device_set_interface(struct usb_device *device, unsigned int interface,
630*00c7fec1SAndroid Build Coastguard Worker unsigned int alt_setting)
631*00c7fec1SAndroid Build Coastguard Worker {
632*00c7fec1SAndroid Build Coastguard Worker struct usbdevfs_setinterface ctl;
633*00c7fec1SAndroid Build Coastguard Worker
634*00c7fec1SAndroid Build Coastguard Worker ctl.interface = interface;
635*00c7fec1SAndroid Build Coastguard Worker ctl.altsetting = alt_setting;
636*00c7fec1SAndroid Build Coastguard Worker return ioctl(device->fd, USBDEVFS_SETINTERFACE, &ctl);
637*00c7fec1SAndroid Build Coastguard Worker }
638*00c7fec1SAndroid Build Coastguard Worker
usb_device_control_transfer(struct usb_device * device,int requestType,int request,int value,int index,void * buffer,int length,unsigned int timeout)639*00c7fec1SAndroid Build Coastguard Worker int usb_device_control_transfer(struct usb_device *device,
640*00c7fec1SAndroid Build Coastguard Worker int requestType,
641*00c7fec1SAndroid Build Coastguard Worker int request,
642*00c7fec1SAndroid Build Coastguard Worker int value,
643*00c7fec1SAndroid Build Coastguard Worker int index,
644*00c7fec1SAndroid Build Coastguard Worker void* buffer,
645*00c7fec1SAndroid Build Coastguard Worker int length,
646*00c7fec1SAndroid Build Coastguard Worker unsigned int timeout)
647*00c7fec1SAndroid Build Coastguard Worker {
648*00c7fec1SAndroid Build Coastguard Worker struct usbdevfs_ctrltransfer ctrl;
649*00c7fec1SAndroid Build Coastguard Worker
650*00c7fec1SAndroid Build Coastguard Worker // this usually requires read/write permission
651*00c7fec1SAndroid Build Coastguard Worker if (!usb_device_reopen_writeable(device))
652*00c7fec1SAndroid Build Coastguard Worker return -1;
653*00c7fec1SAndroid Build Coastguard Worker
654*00c7fec1SAndroid Build Coastguard Worker memset(&ctrl, 0, sizeof(ctrl));
655*00c7fec1SAndroid Build Coastguard Worker ctrl.bRequestType = requestType;
656*00c7fec1SAndroid Build Coastguard Worker ctrl.bRequest = request;
657*00c7fec1SAndroid Build Coastguard Worker ctrl.wValue = value;
658*00c7fec1SAndroid Build Coastguard Worker ctrl.wIndex = index;
659*00c7fec1SAndroid Build Coastguard Worker ctrl.wLength = length;
660*00c7fec1SAndroid Build Coastguard Worker ctrl.data = buffer;
661*00c7fec1SAndroid Build Coastguard Worker ctrl.timeout = timeout;
662*00c7fec1SAndroid Build Coastguard Worker return ioctl(device->fd, USBDEVFS_CONTROL, &ctrl);
663*00c7fec1SAndroid Build Coastguard Worker }
664*00c7fec1SAndroid Build Coastguard Worker
usb_device_bulk_transfer(struct usb_device * device,int endpoint,void * buffer,unsigned int length,unsigned int timeout)665*00c7fec1SAndroid Build Coastguard Worker int usb_device_bulk_transfer(struct usb_device *device,
666*00c7fec1SAndroid Build Coastguard Worker int endpoint,
667*00c7fec1SAndroid Build Coastguard Worker void* buffer,
668*00c7fec1SAndroid Build Coastguard Worker unsigned int length,
669*00c7fec1SAndroid Build Coastguard Worker unsigned int timeout)
670*00c7fec1SAndroid Build Coastguard Worker {
671*00c7fec1SAndroid Build Coastguard Worker struct usbdevfs_bulktransfer ctrl;
672*00c7fec1SAndroid Build Coastguard Worker
673*00c7fec1SAndroid Build Coastguard Worker memset(&ctrl, 0, sizeof(ctrl));
674*00c7fec1SAndroid Build Coastguard Worker ctrl.ep = endpoint;
675*00c7fec1SAndroid Build Coastguard Worker ctrl.len = length;
676*00c7fec1SAndroid Build Coastguard Worker ctrl.data = buffer;
677*00c7fec1SAndroid Build Coastguard Worker ctrl.timeout = timeout;
678*00c7fec1SAndroid Build Coastguard Worker return ioctl(device->fd, USBDEVFS_BULK, &ctrl);
679*00c7fec1SAndroid Build Coastguard Worker }
680*00c7fec1SAndroid Build Coastguard Worker
usb_device_reset(struct usb_device * device)681*00c7fec1SAndroid Build Coastguard Worker int usb_device_reset(struct usb_device *device)
682*00c7fec1SAndroid Build Coastguard Worker {
683*00c7fec1SAndroid Build Coastguard Worker return ioctl(device->fd, USBDEVFS_RESET);
684*00c7fec1SAndroid Build Coastguard Worker }
685*00c7fec1SAndroid Build Coastguard Worker
usb_request_new(struct usb_device * dev,const struct usb_endpoint_descriptor * ep_desc)686*00c7fec1SAndroid Build Coastguard Worker struct usb_request *usb_request_new(struct usb_device *dev,
687*00c7fec1SAndroid Build Coastguard Worker const struct usb_endpoint_descriptor *ep_desc)
688*00c7fec1SAndroid Build Coastguard Worker {
689*00c7fec1SAndroid Build Coastguard Worker struct usbdevfs_urb *urb = calloc(1, sizeof(struct usbdevfs_urb));
690*00c7fec1SAndroid Build Coastguard Worker if (!urb)
691*00c7fec1SAndroid Build Coastguard Worker return NULL;
692*00c7fec1SAndroid Build Coastguard Worker
693*00c7fec1SAndroid Build Coastguard Worker if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
694*00c7fec1SAndroid Build Coastguard Worker urb->type = USBDEVFS_URB_TYPE_BULK;
695*00c7fec1SAndroid Build Coastguard Worker else if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
696*00c7fec1SAndroid Build Coastguard Worker urb->type = USBDEVFS_URB_TYPE_INTERRUPT;
697*00c7fec1SAndroid Build Coastguard Worker else {
698*00c7fec1SAndroid Build Coastguard Worker D("Unsupported endpoint type %d", ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
699*00c7fec1SAndroid Build Coastguard Worker free(urb);
700*00c7fec1SAndroid Build Coastguard Worker return NULL;
701*00c7fec1SAndroid Build Coastguard Worker }
702*00c7fec1SAndroid Build Coastguard Worker urb->endpoint = ep_desc->bEndpointAddress;
703*00c7fec1SAndroid Build Coastguard Worker
704*00c7fec1SAndroid Build Coastguard Worker struct usb_request *req = calloc(1, sizeof(struct usb_request));
705*00c7fec1SAndroid Build Coastguard Worker if (!req) {
706*00c7fec1SAndroid Build Coastguard Worker free(urb);
707*00c7fec1SAndroid Build Coastguard Worker return NULL;
708*00c7fec1SAndroid Build Coastguard Worker }
709*00c7fec1SAndroid Build Coastguard Worker
710*00c7fec1SAndroid Build Coastguard Worker req->dev = dev;
711*00c7fec1SAndroid Build Coastguard Worker req->max_packet_size = __le16_to_cpu(ep_desc->wMaxPacketSize);
712*00c7fec1SAndroid Build Coastguard Worker req->private_data = urb;
713*00c7fec1SAndroid Build Coastguard Worker req->endpoint = urb->endpoint;
714*00c7fec1SAndroid Build Coastguard Worker urb->usercontext = req;
715*00c7fec1SAndroid Build Coastguard Worker
716*00c7fec1SAndroid Build Coastguard Worker return req;
717*00c7fec1SAndroid Build Coastguard Worker }
718*00c7fec1SAndroid Build Coastguard Worker
usb_request_free(struct usb_request * req)719*00c7fec1SAndroid Build Coastguard Worker void usb_request_free(struct usb_request *req)
720*00c7fec1SAndroid Build Coastguard Worker {
721*00c7fec1SAndroid Build Coastguard Worker free(req->private_data);
722*00c7fec1SAndroid Build Coastguard Worker free(req);
723*00c7fec1SAndroid Build Coastguard Worker }
724*00c7fec1SAndroid Build Coastguard Worker
usb_request_queue(struct usb_request * req)725*00c7fec1SAndroid Build Coastguard Worker int usb_request_queue(struct usb_request *req)
726*00c7fec1SAndroid Build Coastguard Worker {
727*00c7fec1SAndroid Build Coastguard Worker struct usbdevfs_urb *urb = (struct usbdevfs_urb*)req->private_data;
728*00c7fec1SAndroid Build Coastguard Worker int res;
729*00c7fec1SAndroid Build Coastguard Worker
730*00c7fec1SAndroid Build Coastguard Worker urb->status = -1;
731*00c7fec1SAndroid Build Coastguard Worker urb->buffer = req->buffer;
732*00c7fec1SAndroid Build Coastguard Worker urb->buffer_length = req->buffer_length;
733*00c7fec1SAndroid Build Coastguard Worker
734*00c7fec1SAndroid Build Coastguard Worker do {
735*00c7fec1SAndroid Build Coastguard Worker res = ioctl(req->dev->fd, USBDEVFS_SUBMITURB, urb);
736*00c7fec1SAndroid Build Coastguard Worker } while((res < 0) && (errno == EINTR));
737*00c7fec1SAndroid Build Coastguard Worker
738*00c7fec1SAndroid Build Coastguard Worker return res;
739*00c7fec1SAndroid Build Coastguard Worker }
740*00c7fec1SAndroid Build Coastguard Worker
usb_request_wait(struct usb_device * dev,int timeoutMillis)741*00c7fec1SAndroid Build Coastguard Worker struct usb_request *usb_request_wait(struct usb_device *dev, int timeoutMillis)
742*00c7fec1SAndroid Build Coastguard Worker {
743*00c7fec1SAndroid Build Coastguard Worker // Poll until a request becomes available if there is a timeout
744*00c7fec1SAndroid Build Coastguard Worker if (timeoutMillis > 0) {
745*00c7fec1SAndroid Build Coastguard Worker struct pollfd p = {.fd = dev->fd, .events = POLLOUT, .revents = 0};
746*00c7fec1SAndroid Build Coastguard Worker
747*00c7fec1SAndroid Build Coastguard Worker int res = poll(&p, 1, timeoutMillis);
748*00c7fec1SAndroid Build Coastguard Worker
749*00c7fec1SAndroid Build Coastguard Worker if (res != 1 || p.revents != POLLOUT) {
750*00c7fec1SAndroid Build Coastguard Worker D("[ poll - event %d, error %d]\n", p.revents, errno);
751*00c7fec1SAndroid Build Coastguard Worker return NULL;
752*00c7fec1SAndroid Build Coastguard Worker }
753*00c7fec1SAndroid Build Coastguard Worker }
754*00c7fec1SAndroid Build Coastguard Worker
755*00c7fec1SAndroid Build Coastguard Worker // Read the request. This should usually succeed as we polled before, but it can fail e.g. when
756*00c7fec1SAndroid Build Coastguard Worker // two threads are reading usb requests at the same time and only a single request is available.
757*00c7fec1SAndroid Build Coastguard Worker struct usbdevfs_urb *urb = NULL;
758*00c7fec1SAndroid Build Coastguard Worker int res = TEMP_FAILURE_RETRY(ioctl(dev->fd, timeoutMillis == -1 ? USBDEVFS_REAPURB :
759*00c7fec1SAndroid Build Coastguard Worker USBDEVFS_REAPURBNDELAY, &urb));
760*00c7fec1SAndroid Build Coastguard Worker D("%s returned %d\n", timeoutMillis == -1 ? "USBDEVFS_REAPURB" : "USBDEVFS_REAPURBNDELAY", res);
761*00c7fec1SAndroid Build Coastguard Worker
762*00c7fec1SAndroid Build Coastguard Worker if (res < 0) {
763*00c7fec1SAndroid Build Coastguard Worker D("[ reap urb - error %d]\n", errno);
764*00c7fec1SAndroid Build Coastguard Worker return NULL;
765*00c7fec1SAndroid Build Coastguard Worker } else {
766*00c7fec1SAndroid Build Coastguard Worker D("[ urb @%p status = %d, actual = %d ]\n", urb, urb->status, urb->actual_length);
767*00c7fec1SAndroid Build Coastguard Worker
768*00c7fec1SAndroid Build Coastguard Worker struct usb_request *req = (struct usb_request*)urb->usercontext;
769*00c7fec1SAndroid Build Coastguard Worker req->actual_length = urb->actual_length;
770*00c7fec1SAndroid Build Coastguard Worker
771*00c7fec1SAndroid Build Coastguard Worker return req;
772*00c7fec1SAndroid Build Coastguard Worker }
773*00c7fec1SAndroid Build Coastguard Worker }
774*00c7fec1SAndroid Build Coastguard Worker
usb_request_cancel(struct usb_request * req)775*00c7fec1SAndroid Build Coastguard Worker int usb_request_cancel(struct usb_request *req)
776*00c7fec1SAndroid Build Coastguard Worker {
777*00c7fec1SAndroid Build Coastguard Worker struct usbdevfs_urb *urb = ((struct usbdevfs_urb*)req->private_data);
778*00c7fec1SAndroid Build Coastguard Worker return ioctl(req->dev->fd, USBDEVFS_DISCARDURB, urb);
779*00c7fec1SAndroid Build Coastguard Worker }
780