blob: 60de53c3fb6919e123aeedc8fffd175b9c720784 [file] [log] [blame]
The Android Open Source Project4f6e8d72008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define _GNU_SOURCE
18#include <stdio.h>
19
20#include <stdlib.h>
21#include <unistd.h>
22#include <string.h>
23
24#include <sys/ioctl.h>
25#include <sys/types.h>
26#include <dirent.h>
27#include <fcntl.h>
28#include <errno.h>
29#include <pthread.h>
30#include <ctype.h>
31
32#include <linux/usbdevice_fs.h>
33#include <linux/version.h>
34#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
35#include <linux/usb/ch9.h>
36#else
37#include <linux/usb_ch9.h>
38#endif
39#include <asm/byteorder.h>
40
41#include <cutils/fdevent.h>
42#include "adb.h"
43
44
45#define TRACE_USB 0
46
47#if TRACE_USB
48#define DBG1(x...) fprintf(stderr, x)
49#define DBG(x...) fprintf(stderr, x)
50#else
51#define DBG(x...)
52#define DBG1(x...)
53#endif
54
55struct usb_handle
56{
57 struct usb_handle *next;
58 char fname[32];
59 int desc;
60 unsigned char ep_in;
61 unsigned char ep_out;
62 unsigned int interface;
63};
64
65static struct usb_handle *g_first_usb_device;
66static struct usb_handle *g_last_usb_device;
67
68static void new_device(char *dev_name, unsigned char ep_in, unsigned char ep_out, unsigned int interface)
69{
70 struct usb_handle* usb;
71
72 DBG("New device being added %s \n", dev_name);
73
74 usb = (struct usb_handle *)calloc(1, sizeof(struct usb_handle));
75 strcpy(usb->fname, dev_name);
76 usb->ep_in = ep_in;
77 usb->ep_out = ep_out;
78 usb->interface = interface;
79 usb->next = NULL;
80 if(g_last_usb_device)
81 g_last_usb_device->next = usb;
82 else
83 g_first_usb_device = usb;
84 g_last_usb_device = usb;
85}
86
87
88static inline int badname(const char *name)
89{
90 if(!isdigit(name[0])) return 1;
91 if(!isdigit(name[1])) return 1;
92 if(!isdigit(name[2])) return 1;
93 if(name[3] != 0) return 1;
94 return 0;
95}
96
97static int find_usb_devices(const char *base, unsigned vendor, unsigned product1, unsigned product2,
98 unsigned ifclass, unsigned ifsubclass,
99 unsigned ifprotocol, unsigned numendpoints)
100{
101 char busname[32], devname[32];
102 unsigned char local_ep_in, local_ep_out;
103 DIR *busdir , *devdir ;
104 struct dirent *de;
105 int fd ;
106 int ret_val = -1;
107 int found_device = 0;
108
109 busdir = opendir(base);
110 if(busdir == 0) return 0;
111
112 while((de = readdir(busdir)) != 0) {
113 if(badname(de->d_name)) continue;
114
115 snprintf(busname, sizeof busname, "%s/%s", base, de->d_name);
116 devdir = opendir(busname);
117 if(devdir == 0) continue;
118
119 DBG("[ scanning %s ]\n", busname);
120 while((de = readdir(devdir))) {
121 if(badname(de->d_name)) continue;
122 snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name);
123
124 DBG("[ scanning %s ]\n", devname);
125 fd = open(devname, O_RDWR);
126 if(fd < 0) {
127 continue;
128 } else {
129 unsigned char devdesc[256];
130 unsigned char* bufptr = devdesc;
131 struct usb_device_descriptor* device;
132 struct usb_config_descriptor* config;
133 struct usb_interface_descriptor* interface;
134 struct usb_endpoint_descriptor *ep1, *ep2;
135 unsigned vid, pid;
136 int i, interfaces;
137
138 size_t desclength = read(fd, devdesc, sizeof(devdesc));
139
140 // should have device and configuration descriptors, and atleast two endpoints
141 if (desclength < USB_DT_DEVICE_SIZE + USB_DT_CONFIG_SIZE) {
142 DBG("desclength %d is too small\n", desclength);
143 close(fd);
144 continue;
145 }
146
147 device = (struct usb_device_descriptor*)bufptr;
148 bufptr += USB_DT_DEVICE_SIZE;
149 if(device->bLength == USB_DT_DEVICE_SIZE && device->bDescriptorType == USB_DT_DEVICE) {
150 vid = __le16_to_cpu(device->idVendor);
151 pid = __le16_to_cpu(device->idProduct);
152 pid = devdesc[10] | (devdesc[11] << 8);
153 DBG("[ %s is V:%04x P:%04x ]\n", devname, vid, pid);
154 if((vendor == vid) && (product1 == pid || product2 == pid)){
155
156 // should have config descriptor next
157 config = (struct usb_config_descriptor *)bufptr;
158 bufptr += USB_DT_CONFIG_SIZE;
159 if (config->bLength != USB_DT_CONFIG_SIZE || config->bDescriptorType != USB_DT_CONFIG) {
160 DBG("usb_config_descriptor not found\n");
161 close(fd);
162 continue;
163 }
164
165 // loop through all the interfaces and look for the ADB interface
166 interfaces = config->bNumInterfaces;
167 for (i = 0; i < interfaces; i++) {
168 if (bufptr + USB_DT_ENDPOINT_SIZE > devdesc + desclength)
169 break;
170
171 interface = (struct usb_interface_descriptor *)bufptr;
172 bufptr += USB_DT_INTERFACE_SIZE;
173 if (interface->bLength != USB_DT_INTERFACE_SIZE ||
174 interface->bDescriptorType != USB_DT_INTERFACE) {
175 DBG("usb_interface_descriptor not found\n");
176 break;
177 }
178
179 DBG("bInterfaceClass: %d, bInterfaceSubClass: %d,\
180 bInterfaceProtocol: %d, bNumEndpoints: %d\n",
181 interface->bInterfaceClass, interface->bInterfaceSubClass,
182 interface->bInterfaceProtocol, interface->bNumEndpoints);
183 // Sooner bootloader has zero for bInterfaceClass, while adb has USB_CLASS_CDC_DATA
184 if (interface->bInterfaceClass == ifclass &&
185 interface->bInterfaceSubClass == ifsubclass &&
186 interface->bInterfaceProtocol == ifprotocol &&
187 interface->bNumEndpoints == numendpoints) {
188
189 DBG("looking for bulk endpoints\n");
190 // looks like ADB...
191 ep1 = (struct usb_endpoint_descriptor *)bufptr;
192 bufptr += USB_DT_ENDPOINT_SIZE;
193 ep2 = (struct usb_endpoint_descriptor *)bufptr;
194 bufptr += USB_DT_ENDPOINT_SIZE;
195
196 if (bufptr > devdesc + desclength ||
197 ep1->bLength != USB_DT_ENDPOINT_SIZE ||
198 ep1->bDescriptorType != USB_DT_ENDPOINT ||
199 ep2->bLength != USB_DT_ENDPOINT_SIZE ||
200 ep2->bDescriptorType != USB_DT_ENDPOINT) {
201 DBG("endpoints not found\n");
202 break;
203 }
204
205 // both endpoints should be bulk
206 if (ep1->bmAttributes != USB_ENDPOINT_XFER_BULK ||
207 ep2->bmAttributes != USB_ENDPOINT_XFER_BULK) {
208 DBG("bulk endpoints not found\n");
209 continue;
210 }
211
212 // we have a match. now we just need to figure out which is in and which is out.
213 if (ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
214 local_ep_in = ep1->bEndpointAddress;
215 local_ep_out = ep2->bEndpointAddress;
216 } else {
217 local_ep_in = ep2->bEndpointAddress;
218 local_ep_out = ep1->bEndpointAddress;
219 }
220
221 new_device(devname, local_ep_in, local_ep_out, i);
222 found_device = 1;
223 close(fd);
224 } else {
225 // skip to next interface
226 bufptr += (interface->bNumEndpoints * USB_DT_ENDPOINT_SIZE);
227 }
228 } // end of for
229 } //end of productid if
230 }
231 close(fd);
232 } // end of if
233 } // end of devdir while
234 closedir(devdir);
235 } //end of busdir while
236 closedir(busdir);
237
238 return found_device;
239}
240
241
242static void find_devices(unsigned vendor, unsigned product1, unsigned product2)
243{
244 // don't scan /proc/bus/usb if we find something in /dev/bus/usb, to avoid duplication of devices.
245 if (!find_usb_devices("/dev/bus/usb", vendor, product1, product2, USB_CLASS_VENDOR_SPEC, 1, 0, 2)) {
246 find_usb_devices("/proc/bus/usb", vendor, product1, product2, USB_CLASS_VENDOR_SPEC, 1, 0, 2);
247 }
248}
249
250void usb_open_device(struct usb_handle *h)
251{
252 int n = 0;
253
254 h->desc = open(h->fname, O_RDWR);
255 //DBG("[ usb open %s fd = %d]\n", h->fname, h->desc);
256 n = ioctl(h->desc, USBDEVFS_CLAIMINTERFACE, &h->interface);
257 if(n != 0) goto fail;
258// t->usb_is_open = 1;
259 return;
260
261
262fail:
263 DBG("[ usb open %s error=%d, err_str = %s]\n",
264 h->fname, errno, strerror(errno));
265 if(h->desc >= 0) {
266 close(h->desc);
267 h->desc = -1;
268 }
269// t->usb_is_open = 0;
270}
271
272int usb_write(struct usb_handle *h, const void *_data, int len)
273{
274 unsigned char *data = (unsigned char*) _data;
275 struct usbdevfs_bulktransfer bulk;
276 int n;
277
278 while(len >= 0) {
279 int xfer = (len > 4096) ? 4096 : len;
280
281 bulk.ep = h->ep_out;
282 bulk.len = xfer;
283 bulk.data = data;
284 bulk.timeout = 500 + xfer * 8;
285
286 bulk.timeout *= 10;
287
288 n = ioctl(h->desc, USBDEVFS_BULK, &bulk);
289 if(n != xfer) {
290 DBG("ERROR: n = %d, errno = %d (%s)\n",
291 n, errno, strerror(errno));
292 return -1;
293 }
294 if(len == 0)
295 break;
296
297 len -= xfer;
298 data += xfer;
299 if(len == 0)
300 break;
301 }
302
303 return 0;
304}
305
306int usb_read(struct usb_handle *h, void *_data, int len)
307{
308 unsigned char *data_start = (unsigned char*) _data;
309 unsigned char *data = (unsigned char*) _data;
310 struct usbdevfs_bulktransfer bulk;
311 int n;
312
313 while(len > 0) {
314 int xfer = (len > 4096) ? 4096 : len;
315
316 bulk.ep = h->ep_in;
317 bulk.len = xfer;
318 bulk.data = data;
319
320 // adjust timeout based on the data we're transferring,
321 // otherwise the timeout interrupts us partway through
322 // and we get out of sync...
323 bulk.timeout = 500 + xfer * 8;
324
325 bulk.timeout = 500 + xfer / 128;
326
327// bulk.timeout *= 10;
328 DBG1("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname);
329 n = ioctl(h->desc, USBDEVFS_BULK, &bulk);
330 DBG1("[ usb read %d ] = %d, fname=%s\n", xfer, n, h->fname);
331 if(n < 0) {
332 if((errno == ETIMEDOUT) && (h->desc != -1)) {
333 DBG("[ timeout ]\n");
334 if(n > 0){
335 data += n;
336 len -= n;
337 }
338 continue;
339 }
340 DBG1("ERROR: n = %d, errno = %d (%s)\n",
341 n, errno, strerror(errno));
342 return -1;
343 }
344
345 len -= n;
346 data += n;
347 if(n != xfer)
348 break;
349 }
350
351 return data - data_start;
352}
353
354void usb_kick(struct usb_handle *h)
355{
356 close(h->desc);
357 h->desc = -1;
358}
359
360int usb_close(struct usb_handle *h)
361{
362 close(h->desc);
363 h->desc = -1;
364 return 0;
365}
366
367void list_devices()
368{
369 int i = 0;
370 struct usb_handle *h = g_first_usb_device;
371 while(h) {
372 printf("%d: %s\n", i, h->fname);
373 i++;
374 h = h->next;
375 }
376}
377
378int main(int argc, char **argv)
379{
380 char buffer[4096/*-64*/];
381 int len;
382 int c;
383 char *arg;
384 int device_index = 0;
385 struct usb_handle *h;
386 int i;
387
388 find_devices(VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER, PRODUCT_ID_SOONER_COMP);
389 while(1) {
390 c = getopt(argc, argv, "d:l");
391 if (c == EOF)
392 break;
393 switch(c) {
394 case 'd':
395 device_index = strtol(optarg, NULL, 0);
396 break;
397 case 'l':
398 list_devices();
399 return 0;
400 case '?':
401 fprintf(stderr, "%s: invalid option -%c\n",
402 argv[0], optopt);
403 return 1;
404 }
405 }
406
407 argc -= optind - 1;
408 argv += optind - 1;
409
410 h = g_first_usb_device;
411 i = device_index;
412 while(i-- > 0 && h) {
413 h = h->next;
414 }
415 if(h == NULL) {
416 fprintf(stderr, "no device %d\n", device_index);
417 return 1;
418 }
419
420 usb_open_device(h);
421 if(g_first_usb_device->desc < 0) {
422 fprintf(stderr, "could not open device (%s), %s\n", h->fname, strerror(errno));
423 return 1;
424 }
425 len = 0;
426 if(argc == 1) {
427 char *line = NULL;
428 size_t line_size = 0;
429 while((len = getline(&line, &line_size, stdin)) >= 0) {
430 //if(len > 0 && line[len - 1] == '\n')
431 // len--;
432 usb_write(h, line, len);
433 while(1) {
434 len = usb_read(h, buffer, sizeof(buffer));
435 if(len < 0)
436 break;
437 write(STDOUT_FILENO, buffer, len);
438 if(len < (int)sizeof(buffer))
439 break;
440 }
441 }
442 return 0;
443 }
444 while(argc > 1) {
445 argc--;
446 argv++;
447 arg = *argv;
448 while(arg) {
449 if(*arg)
450 buffer[len++] = *arg++;
451 else {
452 arg = NULL;
453 if(argc > 1)
454 buffer[len++] = ' ';
455 else
456 break;
457 }
458 if(len == sizeof(buffer)) {
459 usb_write(h, buffer, len);
460 len = 0;
461 }
462 }
463 }
464 usb_write(h, buffer, len);
465 while(1) {
466 len = usb_read(h, buffer, sizeof(buffer));
467 if(len < 0)
468 break;
469 write(STDOUT_FILENO, buffer, len);
470 if(len < (int)sizeof(buffer))
471 break;
472 }
473 return 0;
474}