usb_libusb.c revision 3b226f9e3b893a3e088d7b854b0e7c523e79063f
13b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov/* 23b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * Copyright (C) 2009 bsdroid project 33b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * Alexey Tarasov <tarasov@dodologics.com> 43b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * 53b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * Copyright (C) 2007 The Android Open Source Project 63b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * 73b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * Licensed under the Apache License, Version 2.0 (the "License"); 83b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * you may not use this file except in compliance with the License. 93b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * You may obtain a copy of the License at 103b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * 113b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * http://www.apache.org/licenses/LICENSE-2.0 123b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * 133b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * Unless required by applicable law or agreed to in writing, software 143b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * distributed under the License is distributed on an "AS IS" BASIS, 153b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * See the License for the specific language governing permissions and 173b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov * limitations under the License. 183b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov */ 193b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 203b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <sys/endian.h> 213b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <sys/ioctl.h> 223b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <sys/types.h> 233b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <sys/uio.h> 243b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 253b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <err.h> 263b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <errno.h> 273b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <poll.h> 283b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <stdio.h> 293b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <stdlib.h> 303b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <strings.h> 313b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <string.h> 323b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <sysexits.h> 333b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <unistd.h> 343b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include <libusb.h> 353b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include "sysdeps.h" 363b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 373b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#define TRACE_TAG TRACE_USB 383b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov#include "adb.h" 393b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 403b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovstatic adb_mutex_t usb_lock = ADB_MUTEX_INITIALIZER; 413b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovstatic libusb_context *ctx = NULL; 423b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 433b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovstruct usb_handle 443b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 453b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov usb_handle *prev; 463b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov usb_handle *next; 473b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 483b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_device *dev; 493b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_device_handle *devh; 503b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int interface; 513b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uint8_t dev_bus; 523b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uint8_t dev_addr; 533b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 543b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int zero_mask; 553b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov unsigned char end_point_address[2]; 563b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov char serial[128]; 573b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 583b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_cond_t notify; 593b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_mutex_t lock; 603b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov}; 613b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 623b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovstatic struct usb_handle handle_list = { 633b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov .prev = &handle_list, 643b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov .next = &handle_list, 653b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov}; 663b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 673b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovvoid 683b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovusb_cleanup() 693b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 703b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_exit(ctx); 713b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 723b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 733b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovvoid 743b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovreport_bulk_libusb_error(int r) 753b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 763b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov switch (r) { 773b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov case LIBUSB_ERROR_TIMEOUT: 783b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("Transfer timeout\n"); 793b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov break; 803b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 813b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov case LIBUSB_ERROR_PIPE: 823b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("Control request is not supported\n"); 833b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov break; 843b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 853b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov case LIBUSB_ERROR_OVERFLOW: 863b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("Device offered more data\n"); 873b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov break; 883b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 893b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov case LIBUSB_ERROR_NO_DEVICE : 903b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("Device was disconnected\n"); 913b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov break; 923b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 933b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov default: 943b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("Error %d during transfer\n", r); 953b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov break; 963b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov }; 973b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 983b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 993b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovstatic int 1003b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovusb_bulk_write(usb_handle *uh, const void *data, int len) 1013b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 1023b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int r = 0; 1033b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int transferred = 0; 1043b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1053b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov r = libusb_bulk_transfer(uh->devh, uh->end_point_address[1], (void *)data, len, 1063b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov &transferred, 0); 1073b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1083b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (r != 0) { 1093b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("usb_bulk_write(): "); 1103b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov report_bulk_libusb_error(r); 1113b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return r; 1123b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 1133b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1143b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return (transferred); 1153b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 1163b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1173b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovstatic int 1183b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovusb_bulk_read(usb_handle *uh, void *data, int len) 1193b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 1203b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int r = 0; 1213b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int transferred = 0; 1223b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1233b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov r = libusb_bulk_transfer(uh->devh, uh->end_point_address[0], data, len, 1243b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov &transferred, 0); 1253b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1263b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (r != 0) { 1273b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("usb_bulk_read(): "); 1283b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov report_bulk_libusb_error(r); 1293b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return r; 1303b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 1313b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1323b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return (transferred); 1333b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 1343b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1353b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovint 1363b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovusb_write(struct usb_handle *uh, const void *_data, int len) 1373b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 1383b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov unsigned char *data = (unsigned char*) _data; 1393b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int n; 1403b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int need_zero = 0; 1413b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1423b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (uh->zero_mask == 1) { 1433b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (!(len & uh->zero_mask)) { 1443b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov need_zero = 1; 1453b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 1463b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 1473b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1483b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("usb_write(): %p:%d -> transport %p\n", _data, len, uh); 1493b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1503b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov while (len > 0) { 1513b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int xfer = (len > 4096) ? 4096 : len; 1523b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1533b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov n = usb_bulk_write(uh, data, xfer); 1543b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1553b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (n != xfer) { 1563b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("usb_write(): failed for transport %p (%d bytes left)\n", uh, len); 1573b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return -1; 1583b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 1593b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1603b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov len -= xfer; 1613b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov data += xfer; 1623b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 1633b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1643b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (need_zero){ 1653b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov n = usb_bulk_write(uh, _data, 0); 1663b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1673b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (n < 0) { 1683b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("usb_write(): failed to finish operation for transport %p\n", uh); 1693b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 1703b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return n; 1713b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 1723b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1733b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return 0; 1743b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 1753b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1763b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovint 1773b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovusb_read(struct usb_handle *uh, void *_data, int len) 1783b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 1793b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov unsigned char *data = (unsigned char*) _data; 1803b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int n; 1813b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1823b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("usb_read(): %p:%d <- transport %p\n", _data, len, uh); 1833b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1843b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov while (len > 0) { 1853b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int xfer = (len > 4096) ? 4096 : len; 1863b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1873b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov n = usb_bulk_read(uh, data, xfer); 1883b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1893b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (n != xfer) { 1903b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (n > 0) { 1913b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov data += n; 1923b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov len -= n; 1933b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov continue; 1943b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 1953b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 1963b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("usb_read(): failed for transport %p (%d bytes left)\n", uh, len); 1973b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return -1; 1983b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 1993b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2003b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov len -= xfer; 2013b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov data += xfer; 2023b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 2033b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2043b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return 0; 2053b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 2063b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2073b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovint 2083b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovusb_close(struct usb_handle *h) 2093b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 2103b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("usb_close(): closing transport %p\n", h); 2113b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_mutex_lock(&usb_lock); 2123b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2133b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov h->next->prev = h->prev; 2143b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov h->prev->next = h->next; 2153b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov h->prev = NULL; 2163b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov h->next = NULL; 2173b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2183b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_release_interface(h->devh, h->interface); 2193b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_close(h->devh); 2203b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_unref_device(h->dev); 2213b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2223b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_mutex_unlock(&usb_lock); 2233b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2243b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov free(h); 2253b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2263b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return (0); 2273b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 2283b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2293b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovvoid usb_kick(struct usb_handle *h) 2303b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 2313b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("usb_cick(): kicking transport %p\n", h); 2323b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2333b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_mutex_lock(&h->lock); 2343b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov unregister_usb_transport(h); 2353b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_mutex_unlock(&h->lock); 2363b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2373b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov h->next->prev = h->prev; 2383b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov h->prev->next = h->next; 2393b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov h->prev = NULL; 2403b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov h->next = NULL; 2413b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2423b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_release_interface(h->devh, h->interface); 2433b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_close(h->devh); 2443b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_unref_device(h->dev); 2453b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov free(h); 2463b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 2473b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2483b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovint 2493b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovcheck_usb_interface(libusb_interface *interface, 2503b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_device_descriptor *desc, 2513b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov struct usb_handle *uh) 2523b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 2533b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int e; 2543b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2553b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (interface->num_altsetting == 0) { 2563b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_usb_interface(): No interface settings\n"); 2573b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return -1; 2583b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 2593b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2603b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_interface_descriptor *idesc = &interface->altsetting[0]; 2613b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2623b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (idesc->bNumEndpoints != 2) { 2633b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_usb_interface(): Interface have not 2 endpoints, ignoring\n"); 2643b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return -1; 2653b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 2663b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2673b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov for (e = 0; e < idesc->bNumEndpoints; e++) { 2683b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_endpoint_descriptor *edesc = &idesc->endpoint[e]; 2693b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2703b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (edesc->bmAttributes != LIBUSB_TRANSFER_TYPE_BULK) { 2713b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_usb_interface(): Endpoint (%u) is not bulk (%u), ignoring\n", 2723b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov edesc->bmAttributes, LIBUSB_TRANSFER_TYPE_BULK); 2733b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return -1; 2743b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 2753b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2763b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (edesc->bEndpointAddress & LIBUSB_ENDPOINT_IN) 2773b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uh->end_point_address[0] = edesc->bEndpointAddress; 2783b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov else 2793b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uh->end_point_address[1] = edesc->bEndpointAddress; 2803b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2813b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov /* aproto 01 needs 0 termination */ 2823b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (idesc->bInterfaceProtocol == 0x01) { 2833b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uh->zero_mask = edesc->wMaxPacketSize - 1; 2843b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_usb_interface(): Forced Android interface protocol v.1\n"); 2853b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 2863b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 2873b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2883b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_usb_interface(): Device: %04x:%04x " 2893b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov "iclass: %x, isclass: %x, iproto: %x ep: %x/%x-> ", 2903b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov desc->idVendor, desc->idProduct, idesc->bInterfaceClass, 2913b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov idesc->bInterfaceSubClass, idesc->bInterfaceProtocol, 2923b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uh->end_point_address[0], uh->end_point_address[1]); 2933b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 2943b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (!is_adb_interface(desc->idVendor, desc->idProduct, 2953b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov idesc->bInterfaceClass, idesc->bInterfaceSubClass, 2963b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov idesc->bInterfaceProtocol)) 2973b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov { 2983b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("not matches\n"); 2993b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return -1; 3003b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 3013b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3023b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("matches\n"); 3033b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return 1; 3043b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 3053b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3063b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovint 3073b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovcheck_usb_interfaces(libusb_config_descriptor *config, 3083b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_device_descriptor *desc, struct usb_handle *uh) 3093b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 3103b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int i; 3113b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3123b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov for (i = 0; i < config->bNumInterfaces; ++i) { 3133b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (check_usb_interface(&config->interface[i], desc, uh) != -1) { 3143b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov /* found some interface and saved information about it */ 3153b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_usb_interfaces(): Interface %d of %04x:%04x " 3163b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov "matches Android device\n", i, desc->idVendor, 3173b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov desc->idProduct); 3183b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3193b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return i; 3203b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 3213b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 3223b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3233b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return -1; 3243b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 3253b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3263b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovint 3273b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovregister_device(struct usb_handle *uh, const char *serial) 3283b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 3293b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("register_device(): Registering %p [%s] as USB transport\n", 3303b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uh, serial); 3313b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3323b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov struct usb_handle *usb= NULL; 3333b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3343b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov usb = calloc(1, sizeof(struct usb_handle)); 3353b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov memcpy(usb, uh, sizeof(struct usb_handle)); 3363b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov strcpy(usb->serial, uh->serial); 3373b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3383b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_cond_init(&usb->notify, 0); 3393b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_mutex_init(&usb->lock, 0); 3403b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3413b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_mutex_lock(&usb_lock); 3423b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3433b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov usb->next = &handle_list; 3443b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov usb->prev = handle_list.prev; 3453b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov usb->prev->next = usb; 3463b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov usb->next->prev = usb; 3473b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3483b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_mutex_unlock(&usb_lock); 3493b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3503b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov register_usb_transport(usb, serial, 1); 3513b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3523b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return (1); 3533b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 3543b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3553b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovint 3563b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovalready_registered(usb_handle *uh) 3573b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 3583b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov struct usb_handle *usb= NULL; 3593b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int exists = 0; 3603b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3613b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_mutex_lock(&usb_lock); 3623b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3633b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov for (usb = handle_list.next; usb != &handle_list; usb = usb->next) { 3643b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if ((usb->dev_bus == uh->dev_bus) && 3653b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov (usb->dev_addr == uh->dev_addr)) 3663b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov { 3673b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov exists = 1; 3683b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov break; 3693b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 3703b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 3713b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3723b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_mutex_unlock(&usb_lock); 3733b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3743b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return exists; 3753b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 3763b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3773b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovvoid 3783b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovcheck_device(libusb_device *dev) 3793b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 3803b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov struct usb_handle uh; 3813b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int i = 0; 3823b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int found = -1; 3833b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov char serial[256] = {0}; 3843b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3853b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_device_descriptor desc; 3863b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_config_descriptor *config = NULL; 3873b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3883b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int r = libusb_get_device_descriptor(dev, &desc); 3893b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3903b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (r != LIBUSB_SUCCESS) { 3913b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Failed to get device descriptor\n"); 3923b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return; 3933b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 3943b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3953b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if ((desc.idVendor == 0) && (desc.idProduct == 0)) 3963b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return; 3973b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 3983b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Probing usb device %04x:%04x\n", 3993b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov desc.idVendor, desc.idProduct); 4003b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4013b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (!is_adb_interface (desc.idVendor, desc.idProduct, 4023b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov ADB_CLASS, ADB_SUBCLASS, ADB_PROTOCOL)) 4033b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov { 4043b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Ignored due unknown vendor id\n"); 4053b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return; 4063b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 4073b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4083b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uh.dev_bus = libusb_get_bus_number(dev); 4093b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uh.dev_addr = libusb_get_device_address(dev); 4103b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4113b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (already_registered(&uh)) { 4123b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Device (bus: %d, address: %d) " 4133b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov "is already registered\n", uh.dev_bus, uh.dev_addr); 4143b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return; 4153b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 4163b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4173b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Device bus: %d, address: %d\n", 4183b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uh.dev_bus, uh.dev_addr); 4193b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4203b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov r = libusb_get_active_config_descriptor(dev, &config); 4213b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4223b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (r != 0) { 4233b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (r == LIBUSB_ERROR_NOT_FOUND) { 4243b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Device %4x:%4x is unconfigured\n", 4253b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov desc.idVendor, desc.idProduct); 4263b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return; 4273b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 4283b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4293b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Failed to get configuration for %4x:%4x\n", 4303b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov desc.idVendor, desc.idProduct); 4313b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return; 4323b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 4333b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4343b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (config == NULL) { 4353b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Sanity check failed after " 4363b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov "getting active config\n"); 4373b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return; 4383b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 4393b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4403b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (config->interface != NULL) { 4413b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov found = check_usb_interfaces(config, &desc, &uh); 4423b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 4433b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4443b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov /* not needed anymore */ 4453b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_free_config_descriptor(config); 4463b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4473b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov r = libusb_open(dev, &uh.devh); 4483b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uh.dev = dev; 4493b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4503b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (r != 0) { 4513b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov switch (r) { 4523b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov case LIBUSB_ERROR_NO_MEM: 4533b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Memory allocation problem\n"); 4543b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov break; 4553b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4563b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov case LIBUSB_ERROR_ACCESS: 4573b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Permissions problem, " 4583b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov "current user priveleges are messed up?\n"); 4593b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov break; 4603b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4613b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov case LIBUSB_ERROR_NO_DEVICE: 4623b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Device disconected, bad cable?\n"); 4633b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov break; 4643b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4653b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov default: 4663b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): libusb triggered error %d\n", r); 4673b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 4683b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov // skip rest 4693b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov found = -1; 4703b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 4713b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4723b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (found >= 0) { 4733b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Device matches Android interface\n"); 4743b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov // read the device's serial number 4753b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov memset(serial, 0, sizeof(serial)); 4763b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uh.interface = found; 4773b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4783b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov r = libusb_claim_interface(uh.devh, uh.interface); 4793b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4803b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (r < 0) { 4813b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Failed to claim interface %d\n", 4823b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uh.interface); 4833b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4843b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov goto fail; 4853b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 4863b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4873b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (desc.iSerialNumber) { 4883b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov // reading serial 4893b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uint16_t buffer[128] = {0}; 4903b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uint16_t languages[128] = {0}; 4913b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int languageCount = 0; 4923b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4933b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov memset(languages, 0, sizeof(languages)); 4943b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov r = libusb_control_transfer(uh.devh, 4953b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, 4963b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_STRING << 8, 4973b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 0, (uint8_t *)languages, sizeof(languages), 0); 4983b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 4993b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (r <= 0) { 5003b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Failed to get languages count\n"); 5013b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov goto fail; 5023b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 5033b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5043b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov languageCount = (r - 2) / 2; 5053b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5063b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov for (i = 1; i <= languageCount; ++i) { 5073b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov memset(buffer, 0, sizeof(buffer)); 5083b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5093b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov r = libusb_control_transfer(uh.devh, 5103b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, 5113b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc.iSerialNumber, 5123b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov languages[i], (uint8_t *)buffer, sizeof(buffer), 0); 5133b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5143b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (r > 0) { /* converting serial */ 5153b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int j = 0; 5163b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov r /= 2; 5173b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5183b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov for (j = 1; j < r; ++j) 5193b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov serial[j - 1] = buffer[j]; 5203b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5213b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov serial[j - 1] = '\0'; 5223b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov break; /* languagesCount cycle */ 5233b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 5243b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 5253b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5263b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (register_device(&uh, serial) == 0) { 5273b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("check_device(): Failed to register device\n"); 5283b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov goto fail_interface; 5293b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 5303b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5313b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_ref_device(dev); 5323b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 5333b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 5343b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5353b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return; 5363b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5373b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovfail_interface: 5383b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_release_interface(uh.devh, uh.interface); 5393b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5403b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovfail: 5413b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_close(uh.devh); 5423b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov uh.devh = NULL; 5433b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 5443b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5453b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovint 5463b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovcheck_device_connected(struct usb_handle *uh) 5473b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 5483b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int r = libusb_kernel_driver_active(uh->devh, uh->interface); 5493b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5503b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (r == LIBUSB_ERROR_NO_DEVICE) 5513b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return 0; 5523b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5533b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (r < 0) 5543b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return -1; 5553b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5563b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return 1; 5573b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 5583b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5593b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovvoid 5603b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovkick_disconnected() 5613b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 5623b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov struct usb_handle *usb= NULL; 5633b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5643b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_mutex_lock(&usb_lock); 5653b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5663b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov for (usb = handle_list.next; usb != &handle_list; usb = usb->next) { 5673b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5683b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (check_device_connected(usb) == 0) { 5693b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("kick_disconnected(): Transport %p is not online anymore\n", 5703b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov usb); 5713b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5723b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov usb_kick(usb); 5733b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 5743b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 5753b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5763b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_mutex_unlock(&usb_lock); 5773b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 5783b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5793b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovvoid 5803b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovscan_usb_devices() 5813b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 5823b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("scan_usb_devices(): started\n"); 5833b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5843b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_device **devs= NULL; 5853b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_device *dev= NULL; 5863b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov ssize_t cnt = libusb_get_device_list(ctx, &devs); 5873b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5883b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (cnt < 0) { 5893b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("scan_usb_devices(): Failed to get device list (error: %d)\n", 5903b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov cnt); 5913b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5923b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return; 5933b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 5943b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5953b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int i = 0; 5963b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 5973b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov while ((dev = devs[i++]) != NULL) { 5983b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov check_device(dev); 5993b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 6003b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6013b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov libusb_free_device_list(devs, 1); 6023b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 6033b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6043b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovvoid * 6053b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovdevice_poll_thread(void* unused) 6063b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 6073b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("device_poll_thread(): Created USB scan thread\n"); 6083b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6093b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov for (;;) { 6103b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov sleep(5); 6113b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov kick_disconnected(); 6123b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov scan_usb_devices(); 6133b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 6143b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6153b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov /* never reaching this point */ 6163b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov return (NULL); 6173b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 6183b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6193b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovstatic void 6203b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovsigalrm_handler(int signo) 6213b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 6223b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov /* nothing */ 6233b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 6243b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6253b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovvoid 6263b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasovusb_init() 6273b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov{ 6283b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("usb_init(): started\n"); 6293b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov adb_thread_t tid; 6303b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov struct sigaction actions; 6313b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6323b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov int r = libusb_init(&ctx); 6333b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6343b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (r != LIBUSB_SUCCESS) { 6353b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov err(EX_IOERR, "Failed to init libusb\n"); 6363b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 6373b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6383b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov memset(&actions, 0, sizeof(actions)); 6393b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6403b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov sigemptyset(&actions.sa_mask); 6413b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6423b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov actions.sa_flags = 0; 6433b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov actions.sa_handler = sigalrm_handler; 6443b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6453b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov sigaction(SIGALRM, &actions, NULL); 6463b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6473b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov /* initial device scan */ 6483b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov scan_usb_devices(); 6493b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6503b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov /* starting USB event polling thread */ 6513b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov if (adb_thread_create(&tid, device_poll_thread, NULL)) { 6523b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov err(EX_IOERR, "cannot create USB scan thread\n"); 6533b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov } 6543b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 6553b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov D("usb_init(): finished\n"); 6563b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov} 6573b226f9e3b893a3e088d7b854b0e7c523e79063fAlexey Tarasov 658