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