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