usb_windows.c revision b4add9b74525210478bac702d27fdaf9cf7ab18f
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
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    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
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 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
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/** Structure usb_handle describes our connection to the usb device via
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  AdbWinApi.dll. This structure is returned from usb_open() routine and
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  is expected in each subsequent call that is accessing the device.
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct usb_handle {
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /// Handle to USB interface
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADBAPIHANDLE  adb_interface;
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /// Handle to USB read pipe (endpoint)
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADBAPIHANDLE  adb_read_pipe;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /// Handle to USB write pipe (endpoint)
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADBAPIHANDLE  adb_write_pipe;
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /// Interface name
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char*         interface_name;
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Class ID assigned to the device by androidusb.sys
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic const GUID usb_class_id = ANDROID_USB_CLASS_ID;
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Checks if interface (device) matches certain criteria
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint recognized_device(usb_handle* handle, ifc_match_func callback);
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Opens usb interface (device) by interface (device) name.
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectusb_handle* do_usb_open(const wchar_t* interface_name);
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Writes data to the opened usb handle
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_write(usb_handle* handle, const void* data, int len);
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Reads data using the opened usb handle
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_read(usb_handle *handle, void* data, int len);
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Cleans up opened usb handle
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_cleanup_handle(usb_handle* handle);
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Cleans up (but don't close) opened usb handle
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_kick(usb_handle* handle);
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/// Closes opened usb handle
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_close(usb_handle* handle);
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectusb_handle* do_usb_open(const wchar_t* interface_name) {
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Allocate our handle
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle));
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == ret)
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Create interface.
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ret->adb_interface = AdbCreateInterfaceByName(interface_name);
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == ret->adb_interface) {
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(ret);
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        errno = GetLastError();
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Open read pipe (endpoint)
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ret->adb_read_pipe =
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        AdbOpenDefaultBulkReadEndpoint(ret->adb_interface,
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                   AdbOpenAccessTypeReadWrite,
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                   AdbOpenSharingModeReadWrite);
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL != ret->adb_read_pipe) {
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Open write pipe (endpoint)
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret->adb_write_pipe =
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface,
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                      AdbOpenAccessTypeReadWrite,
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                      AdbOpenSharingModeReadWrite);
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (NULL != ret->adb_write_pipe) {
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // Save interface name
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            unsigned long name_len = 0;
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // First get expected name length
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            AdbGetInterfaceName(ret->adb_interface,
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                          NULL,
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                          &name_len,
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                          true);
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (0 != name_len) {
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                ret->interface_name = (char*)malloc(name_len);
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (NULL != ret->interface_name) {
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    // Now save the name
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (AdbGetInterfaceName(ret->adb_interface,
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                  ret->interface_name,
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                  &name_len,
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                  true)) {
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        // We're done at this point
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        return ret;
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    }
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else {
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    SetLastError(ERROR_OUTOFMEMORY);
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
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    // Something went wrong.
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    errno = GetLastError();
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_cleanup_handle(ret);
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(ret);
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SetLastError(errno);
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return NULL;
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_write(usb_handle* handle, const void* data, int len) {
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long time_out = 500 + len * 8;
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long written = 0;
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned count = 0;
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ret;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_write %d\n", len);
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL != handle) {
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Perform write
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while(len > 0) {
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int xfer = (len > 4096) ? 4096 : len;
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ret = AdbWriteEndpointSync(handle->adb_write_pipe,
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                   (void*)data,
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                   (unsigned long)xfer,
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                   &written,
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                   time_out);
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            errno = GetLastError();
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("AdbWriteEndpointSync returned %d, errno: %d\n", ret, errno);
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (ret == 0) {
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // assume ERROR_INVALID_HANDLE indicates we are disconnected
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (errno == ERROR_INVALID_HANDLE)
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                usb_kick(handle);
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return -1;
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            count += written;
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            len -= written;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            data += written;
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (len == 0)
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return count;
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("usb_write NULL handle\n");
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SetLastError(ERROR_INVALID_HANDLE);
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_write failed: %d\n", errno);
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_read(usb_handle *handle, void* data, int len) {
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long time_out = 500 + len * 8;
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long read = 0;
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ret;
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_read %d\n", len);
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL != handle) {
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        while (1) {
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int xfer = (len > 4096) ? 4096 : len;
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	        ret = AdbReadEndpointSync(handle->adb_read_pipe,
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	                              (void*)data,
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	                              (unsigned long)xfer,
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	                              &read,
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	                              time_out);
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            errno = GetLastError();
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("usb_read got: %ld, expected: %d, errno: %d\n", read, xfer, errno);
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (ret) {
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return read;
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else if (errno != ERROR_SEM_TIMEOUT) {
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // assume ERROR_INVALID_HANDLE indicates we are disconnected
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (errno == ERROR_INVALID_HANDLE)
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    usb_kick(handle);
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // else we timed out - try again
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("usb_read NULL handle\n");
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SetLastError(ERROR_INVALID_HANDLE);
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_read failed: %d\n", errno);
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_cleanup_handle(usb_handle* handle) {
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL != handle) {
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (NULL != handle->interface_name)
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            free(handle->interface_name);
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (NULL != handle->adb_write_pipe)
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            AdbCloseHandle(handle->adb_write_pipe);
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (NULL != handle->adb_read_pipe)
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            AdbCloseHandle(handle->adb_read_pipe);
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (NULL != handle->adb_interface)
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            AdbCloseHandle(handle->adb_interface);
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle->interface_name = NULL;
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle->adb_write_pipe = NULL;
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle->adb_read_pipe = NULL;
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle->adb_interface = NULL;
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_kick(usb_handle* handle) {
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL != handle) {
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb_cleanup_handle(handle);
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SetLastError(ERROR_INVALID_HANDLE);
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        errno = ERROR_INVALID_HANDLE;
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_close(usb_handle* handle) {
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_close\n");
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL != handle) {
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Cleanup handle
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb_cleanup_handle(handle);
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(handle);
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint recognized_device(usb_handle* handle, ifc_match_func callback) {
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct usb_ifc_info info;
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    USB_DEVICE_DESCRIPTOR device_desc;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    USB_INTERFACE_DESCRIPTOR interf_desc;
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == handle)
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Check vendor and product id first
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!AdbGetUsbDeviceDescriptor(handle->adb_interface,
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                 &device_desc)) {
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Then check interface properties
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface,
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                    &interf_desc)) {
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Must have two endpoints
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (2 != interf_desc.bNumEndpoints) {
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.dev_vendor = device_desc.idVendor;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.dev_product = device_desc.idProduct;
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.dev_class = device_desc.bDeviceClass;
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.dev_subclass = device_desc.bDeviceSubClass;
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.dev_protocol = device_desc.bDeviceProtocol;
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.ifc_class = interf_desc.bInterfaceClass;
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.ifc_subclass = interf_desc.bInterfaceSubClass;
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    info.ifc_protocol = interf_desc.bInterfaceProtocol;
304b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes    info.writable = 1;
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // read serial number (if there is one)
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long serial_number_len = sizeof(info.serial_number);
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!AdbGetSerialNumber(handle->adb_interface, info.serial_number,
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    &serial_number_len, true)) {
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        info.serial_number[0] = 0;
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (callback(&info) == 0) {
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 1;
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic usb_handle *find_usb_device(ifc_match_func callback) {
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	usb_handle* handle = NULL;
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char entry_buffer[2048];
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char interf_name[2048];
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]);
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned long entry_buffer_size = sizeof(entry_buffer);
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char* copy_name;
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Enumerate all present and active interfaces.
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ADBAPIHANDLE enum_handle =
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        AdbEnumInterfaces(usb_class_id, true, true, true);
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == enum_handle)
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) {
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // TODO(vchtchetkine): FIXME - temp hack converting wchar_t into char.
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // It would be better to change AdbNextInterface so it will return
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // interface name as single char string.
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const wchar_t* wchar_name = next_interface->device_name;
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for(copy_name = interf_name;
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                L'\0' != *wchar_name;
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                wchar_name++, copy_name++) {
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *copy_name = (char)(*wchar_name);
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *copy_name = '\0';
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle = do_usb_open(next_interface->device_name);
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (NULL != handle) {
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            // Lets see if this interface (device) belongs to us
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (recognized_device(handle, callback)) {
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // found it!
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                usb_cleanup_handle(handle);
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                free(handle);
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                handle = NULL;
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        entry_buffer_size = sizeof(entry_buffer);
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    AdbCloseHandle(enum_handle);
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return handle;
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectusb_handle *usb_open(ifc_match_func callback)
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return find_usb_device(callback);
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// called from fastboot.c
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid sleep(int seconds)
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    Sleep(seconds * 1000);
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
377