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
350e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson    register_usb_transport(usb, serial, NULL, 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;
516