xref: /aosp_15_r20/system/core/libusbhost/usbhost.c (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
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