1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * All rights reserved.
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Redistribution and use in source and binary forms, with or without
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * modification, are permitted provided that the following conditions
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * are met:
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *  * Redistributions of source code must retain the above copyright
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *  * Redistributions in binary form must reproduce the above copyright
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer in
125ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau *    the documentation and/or other materials provided with the
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    distribution.
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
225ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * SUCH DAMAGE.
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <windows.h>
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <winerror.h>
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <usb100.h>
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <adb_api.h>
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "usb.h"
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project//#define TRACE_USB 1
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if TRACE_USB
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG(x...) fprintf(stderr, x)
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG(x...)
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
45913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause#define MAX_USBFS_BULK_SIZE (1024 * 1024)
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Structure usb_handle describes our connection to the usb device via
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  AdbWinApi.dll. This structure is returned from usb_open() routine and
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  is expected in each subsequent call that is accessing the device.
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct usb_handle {
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /// Handle to USB interface
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADBAPIHANDLE  adb_interface;
545ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /// Handle to USB read pipe (endpoint)
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADBAPIHANDLE  adb_read_pipe;
575ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /// Handle to USB write pipe (endpoint)
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADBAPIHANDLE  adb_write_pipe;
605ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /// Interface name
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char*         interface_name;
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Class ID assigned to the device by androidusb.sys
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic const GUID usb_class_id = ANDROID_USB_CLASS_ID;
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Checks if interface (device) matches certain criteria
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint recognized_device(usb_handle* handle, ifc_match_func callback);
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Opens usb interface (device) by interface (device) name.
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectusb_handle* do_usb_open(const wchar_t* interface_name);
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Writes data to the opened usb handle
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_write(usb_handle* handle, const void* data, int len);
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Reads data using the opened usb handle
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_read(usb_handle *handle, void* data, int len);
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Cleans up opened usb handle
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_cleanup_handle(usb_handle* handle);
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Cleans up (but don't close) opened usb handle
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_kick(usb_handle* handle);
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Closes opened usb handle
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_close(usb_handle* handle);
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectusb_handle* do_usb_open(const wchar_t* interface_name) {
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Allocate our handle
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle));
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == ret)
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Create interface.
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ret->adb_interface = AdbCreateInterfaceByName(interface_name);
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == ret->adb_interface) {
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(ret);
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        errno = GetLastError();
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Open read pipe (endpoint)
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ret->adb_read_pipe =
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        AdbOpenDefaultBulkReadEndpoint(ret->adb_interface,
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                   AdbOpenAccessTypeReadWrite,
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                   AdbOpenSharingModeReadWrite);
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL != ret->adb_read_pipe) {
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Open write pipe (endpoint)
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret->adb_write_pipe =
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface,
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                      AdbOpenAccessTypeReadWrite,
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                      AdbOpenSharingModeReadWrite);
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (NULL != ret->adb_write_pipe) {
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // Save interface name
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            unsigned long name_len = 0;
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // First get expected name length
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            AdbGetInterfaceName(ret->adb_interface,
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                          NULL,
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                          &name_len,
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                          true);
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (0 != name_len) {
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                ret->interface_name = (char*)malloc(name_len);
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (NULL != ret->interface_name) {
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // Now save the name
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (AdbGetInterfaceName(ret->adb_interface,
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                  ret->interface_name,
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                  &name_len,
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                  true)) {
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        // We're done at this point
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        return ret;
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    }
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else {
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    SetLastError(ERROR_OUTOFMEMORY);
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Something went wrong.
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    errno = GetLastError();
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_cleanup_handle(ret);
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(ret);
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SetLastError(errno);
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return NULL;
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_write(usb_handle* handle, const void* data, int len) {
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long time_out = 500 + len * 8;
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long written = 0;
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned count = 0;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ret;
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_write %d\n", len);
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL != handle) {
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Perform write
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while(len > 0) {
164913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause            int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ret = AdbWriteEndpointSync(handle->adb_write_pipe,
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                   (void*)data,
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                   (unsigned long)xfer,
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                   &written,
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                   time_out);
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            errno = GetLastError();
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("AdbWriteEndpointSync returned %d, errno: %d\n", ret, errno);
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (ret == 0) {
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // assume ERROR_INVALID_HANDLE indicates we are disconnected
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (errno == ERROR_INVALID_HANDLE)
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                usb_kick(handle);
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return -1;
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            count += written;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            len -= written;
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            data += written;
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (len == 0)
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return count;
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("usb_write NULL handle\n");
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SetLastError(ERROR_INVALID_HANDLE);
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_write failed: %d\n", errno);
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_read(usb_handle *handle, void* data, int len) {
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long time_out = 500 + len * 8;
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long read = 0;
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ret;
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_read %d\n", len);
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL != handle) {
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while (1) {
204913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause            int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	        ret = AdbReadEndpointSync(handle->adb_read_pipe,
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	                              (void*)data,
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	                              (unsigned long)xfer,
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	                              &read,
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	                              time_out);
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            errno = GetLastError();
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("usb_read got: %ld, expected: %d, errno: %d\n", read, xfer, errno);
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (ret) {
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return read;
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else if (errno != ERROR_SEM_TIMEOUT) {
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // assume ERROR_INVALID_HANDLE indicates we are disconnected
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (errno == ERROR_INVALID_HANDLE)
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    usb_kick(handle);
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // else we timed out - try again
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("usb_read NULL handle\n");
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SetLastError(ERROR_INVALID_HANDLE);
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_read failed: %d\n", errno);
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_cleanup_handle(usb_handle* handle) {
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL != handle) {
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (NULL != handle->interface_name)
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            free(handle->interface_name);
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (NULL != handle->adb_write_pipe)
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            AdbCloseHandle(handle->adb_write_pipe);
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (NULL != handle->adb_read_pipe)
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            AdbCloseHandle(handle->adb_read_pipe);
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (NULL != handle->adb_interface)
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            AdbCloseHandle(handle->adb_interface);
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle->interface_name = NULL;
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle->adb_write_pipe = NULL;
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle->adb_read_pipe = NULL;
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle->adb_interface = NULL;
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_kick(usb_handle* handle) {
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL != handle) {
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb_cleanup_handle(handle);
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SetLastError(ERROR_INVALID_HANDLE);
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        errno = ERROR_INVALID_HANDLE;
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_close(usb_handle* handle) {
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_close\n");
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL != handle) {
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Cleanup handle
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb_cleanup_handle(handle);
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(handle);
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint recognized_device(usb_handle* handle, ifc_match_func callback) {
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct usb_ifc_info info;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    USB_DEVICE_DESCRIPTOR device_desc;
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    USB_INTERFACE_DESCRIPTOR interf_desc;
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == handle)
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Check vendor and product id first
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!AdbGetUsbDeviceDescriptor(handle->adb_interface,
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                 &device_desc)) {
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Then check interface properties
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface,
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                    &interf_desc)) {
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Must have two endpoints
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (2 != interf_desc.bNumEndpoints) {
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.dev_vendor = device_desc.idVendor;
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.dev_product = device_desc.idProduct;
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.dev_class = device_desc.bDeviceClass;
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.dev_subclass = device_desc.bDeviceSubClass;
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.dev_protocol = device_desc.bDeviceProtocol;
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.ifc_class = interf_desc.bInterfaceClass;
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.ifc_subclass = interf_desc.bInterfaceSubClass;
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.ifc_protocol = interf_desc.bInterfaceProtocol;
305b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes    info.writable = 1;
3065ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // read serial number (if there is one)
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long serial_number_len = sizeof(info.serial_number);
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!AdbGetSerialNumber(handle->adb_interface, info.serial_number,
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    &serial_number_len, true)) {
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        info.serial_number[0] = 0;
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
31413081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson    info.device_path[0] = 0;
31513081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (callback(&info) == 0) {
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 1;
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic usb_handle *find_usb_device(ifc_match_func callback) {
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	usb_handle* handle = NULL;
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char entry_buffer[2048];
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char interf_name[2048];
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long entry_buffer_size = sizeof(entry_buffer);
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char* copy_name;
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Enumerate all present and active interfaces.
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADBAPIHANDLE enum_handle =
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        AdbEnumInterfaces(usb_class_id, true, true, true);
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == enum_handle)
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // TODO(vchtchetkine): FIXME - temp hack converting wchar_t into char.
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // It would be better to change AdbNextInterface so it will return
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // interface name as single char string.
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const wchar_t* wchar_name = next_interface->device_name;
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for(copy_name = interf_name;
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                L'\0' != *wchar_name;
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                wchar_name++, copy_name++) {
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *copy_name = (char)(*wchar_name);
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *copy_name = '\0';
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle = do_usb_open(next_interface->device_name);
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (NULL != handle) {
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // Lets see if this interface (device) belongs to us
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (recognized_device(handle, callback)) {
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // found it!
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                usb_cleanup_handle(handle);
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                free(handle);
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                handle = NULL;
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        entry_buffer_size = sizeof(entry_buffer);
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AdbCloseHandle(enum_handle);
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return handle;
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectusb_handle *usb_open(ifc_match_func callback)
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return find_usb_device(callback);
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// called from fastboot.c
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid sleep(int seconds)
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Sleep(seconds * 1000);
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
380