Home | History | Annotate | Download | only in winusb
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /** \file
     18   This file consists of implementation of class AdbWinUsbInterfaceObject
     19   that encapsulates an interface on our USB device that is accessible
     20   via WinUsb API.
     21 */
     22 
     23 #include "stdafx.h"
     24 #include "adb_winusb_interface.h"
     25 #include "adb_winusb_endpoint_object.h"
     26 
     27 AdbWinUsbInterfaceObject::AdbWinUsbInterfaceObject(const wchar_t* interf_name)
     28     : AdbInterfaceObject(interf_name),
     29       usb_device_handle_(INVALID_HANDLE_VALUE),
     30       winusb_handle_(NULL),
     31       interface_number_(0xFF),
     32       def_read_endpoint_(0xFF),
     33       read_endpoint_id_(0xFF),
     34       def_write_endpoint_(0xFF),
     35       write_endpoint_id_(0xFF) {
     36 }
     37 
     38 AdbWinUsbInterfaceObject::~AdbWinUsbInterfaceObject() {
     39   ATLASSERT(NULL == winusb_handle_);
     40   ATLASSERT(INVALID_HANDLE_VALUE == usb_device_handle_);
     41 }
     42 
     43 LONG AdbWinUsbInterfaceObject::Release() {
     44   ATLASSERT(ref_count_ > 0);
     45   LONG ret = InterlockedDecrement(&ref_count_);
     46   ATLASSERT(ret >= 0);
     47   if (0 == ret) {
     48     LastReferenceReleased();
     49     delete this;
     50   }
     51   return ret;
     52 }
     53 
     54 ADBAPIHANDLE AdbWinUsbInterfaceObject::CreateHandle() {
     55   // Open USB device for this inteface Note that WinUsb API
     56   // requires the handle to be opened for overlapped I/O.
     57   usb_device_handle_ = CreateFile(interface_name().c_str(),
     58                                   GENERIC_READ | GENERIC_WRITE,
     59                                   FILE_SHARE_READ | FILE_SHARE_WRITE,
     60                                   NULL, OPEN_EXISTING,
     61                                   FILE_FLAG_OVERLAPPED, NULL);
     62   if (INVALID_HANDLE_VALUE == usb_device_handle_)
     63     return NULL;
     64 
     65   // Initialize WinUSB API for this interface
     66   if (!WinUsb_Initialize(usb_device_handle_, &winusb_handle_))
     67     return NULL;
     68 
     69   // Cache current interface number that will be used in
     70   // WinUsb_Xxx calls performed on this interface.
     71   if (!WinUsb_GetCurrentAlternateSetting(winusb_handle(), &interface_number_))
     72     return false;
     73 
     74   // Cache interface properties
     75   unsigned long bytes_written;
     76 
     77   // Cache USB device descriptor
     78   if (!WinUsb_GetDescriptor(winusb_handle(), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0,
     79                             reinterpret_cast<PUCHAR>(&usb_device_descriptor_),
     80                             sizeof(usb_device_descriptor_), &bytes_written)) {
     81     return false;
     82   }
     83 
     84   // Cache USB configuration descriptor
     85   if (!WinUsb_GetDescriptor(winusb_handle(), USB_CONFIGURATION_DESCRIPTOR_TYPE,
     86                             0, 0,
     87                             reinterpret_cast<PUCHAR>(&usb_config_descriptor_),
     88                             sizeof(usb_config_descriptor_), &bytes_written)) {
     89     return false;
     90   }
     91 
     92   // Cache USB interface descriptor
     93   if (!WinUsb_QueryInterfaceSettings(winusb_handle(), interface_number(),
     94                                      &usb_interface_descriptor_)) {
     95     return false;
     96   }
     97 
     98   // Save indexes and IDs for bulk read / write endpoints. We will use them to
     99   // convert ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX and
    100   // ADB_QUERY_BULK_READ_ENDPOINT_INDEX into actual endpoint indexes and IDs.
    101   for (UCHAR endpoint = 0; endpoint < usb_interface_descriptor_.bNumEndpoints;
    102        endpoint++) {
    103     // Get endpoint information
    104     WINUSB_PIPE_INFORMATION pipe_info;
    105     if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint,
    106                           &pipe_info)) {
    107       return false;
    108     }
    109 
    110     if (UsbdPipeTypeBulk == pipe_info.PipeType) {
    111       // This is a bulk endpoint. Cache its index and ID.
    112       if (0 != (pipe_info.PipeId & USB_ENDPOINT_DIRECTION_MASK)) {
    113         // Use this endpoint as default bulk read endpoint
    114         ATLASSERT(0xFF == def_read_endpoint_);
    115         def_read_endpoint_ = endpoint;
    116         read_endpoint_id_ = pipe_info.PipeId;
    117       } else {
    118         // Use this endpoint as default bulk write endpoint
    119         ATLASSERT(0xFF == def_write_endpoint_);
    120         def_write_endpoint_ = endpoint;
    121         write_endpoint_id_ = pipe_info.PipeId;
    122       }
    123     }
    124   }
    125 
    126   return AdbInterfaceObject::CreateHandle();
    127 }
    128 
    129 bool AdbWinUsbInterfaceObject::CloseHandle() {
    130   if (NULL != winusb_handle_) {
    131     WinUsb_Free(winusb_handle_);
    132     winusb_handle_ = NULL;
    133   }
    134   if (INVALID_HANDLE_VALUE != usb_device_handle_) {
    135     ::CloseHandle(usb_device_handle_);
    136     usb_device_handle_ = INVALID_HANDLE_VALUE;
    137   }
    138 
    139   return AdbInterfaceObject::CloseHandle();
    140 }
    141 
    142 bool AdbWinUsbInterfaceObject::GetSerialNumber(void* buffer,
    143                                                unsigned long* buffer_char_size,
    144                                                bool ansi) {
    145   if (!IsOpened()) {
    146     SetLastError(ERROR_INVALID_HANDLE);
    147     return false;
    148   }
    149 
    150   if (NULL == buffer_char_size) {
    151     SetLastError(ERROR_INVALID_PARAMETER);
    152     return false;
    153   }
    154 
    155   // Calculate serial number string size. Note that WinUsb_GetDescriptor
    156   // API will not return number of bytes needed to store serial number
    157   // string. So we will have to start with a reasonably large preallocated
    158   // buffer and then loop through WinUsb_GetDescriptor calls, doubling up
    159   // string buffer size every time ERROR_INSUFFICIENT_BUFFER is returned.
    160   union {
    161     // Preallocate reasonably sized buffer on the stack.
    162     char small_buffer[64];
    163     USB_STRING_DESCRIPTOR initial_ser_num;
    164   };
    165   USB_STRING_DESCRIPTOR* ser_num = &initial_ser_num;
    166   // Buffer byte size
    167   unsigned long ser_num_size = sizeof(small_buffer);
    168   // After successful call to WinUsb_GetDescriptor will contain serial
    169   // number descriptor size.
    170   unsigned long bytes_written;
    171   while (!WinUsb_GetDescriptor(winusb_handle(), USB_STRING_DESCRIPTOR_TYPE,
    172                                usb_device_descriptor_.iSerialNumber,
    173                                0x0409, // English (US)
    174                                reinterpret_cast<PUCHAR>(ser_num),
    175                                ser_num_size, &bytes_written)) {
    176     // Any error other than ERROR_INSUFFICIENT_BUFFER is terminal here.
    177     if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
    178       if (ser_num != &initial_ser_num)
    179         delete[] reinterpret_cast<char*>(ser_num);
    180       return false;
    181     }
    182 
    183     // Double up buffer size and reallocate string buffer
    184     ser_num_size *= 2;
    185     if (ser_num != &initial_ser_num)
    186       delete[] reinterpret_cast<char*>(ser_num);
    187     try {
    188       ser_num =
    189           reinterpret_cast<USB_STRING_DESCRIPTOR*>(new char[ser_num_size]);
    190     } catch (...) {
    191       SetLastError(ERROR_OUTOFMEMORY);
    192       return false;
    193     }
    194   }
    195 
    196   // Serial number string length
    197   unsigned long str_len = (ser_num->bLength -
    198                            FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)) /
    199                           sizeof(wchar_t);
    200 
    201   // Lets see if requested buffer is big enough to fit the string
    202   if ((NULL == buffer) || (*buffer_char_size < (str_len + 1))) {
    203     // Requested buffer is too small.
    204     if (ser_num != &initial_ser_num)
    205       delete[] reinterpret_cast<char*>(ser_num);
    206     *buffer_char_size = str_len + 1;
    207     SetLastError(ERROR_INSUFFICIENT_BUFFER);
    208     return false;
    209   }
    210 
    211   bool ret = true;
    212   if (ansi) {
    213     // We need to convert name from wide char to ansi string
    214     if (0 != WideCharToMultiByte(CP_ACP, 0, ser_num->bString,
    215                                  static_cast<int>(str_len),
    216                                  reinterpret_cast<PSTR>(buffer),
    217                                  static_cast<int>(*buffer_char_size),
    218                                  NULL, NULL)) {
    219       // Zero-terminate output string.
    220       reinterpret_cast<char*>(buffer)[str_len] = '\0';
    221     } else {
    222       ret = false;
    223     }
    224   } else {
    225     // For wide char output just copy string buffer,
    226     // and zero-terminate output string.
    227     CopyMemory(buffer, ser_num->bString, bytes_written);
    228     reinterpret_cast<wchar_t*>(buffer)[str_len] = L'\0';
    229   }
    230 
    231   if (ser_num != &initial_ser_num)
    232     delete[] reinterpret_cast<char*>(ser_num);
    233 
    234   return ret;
    235 }
    236 
    237 bool AdbWinUsbInterfaceObject::GetEndpointInformation(
    238     UCHAR endpoint_index,
    239     AdbEndpointInformation* info) {
    240   if (!IsOpened()) {
    241     SetLastError(ERROR_INVALID_HANDLE);
    242     return false;
    243   }
    244 
    245   if (NULL == info) {
    246     SetLastError(ERROR_INVALID_PARAMETER);
    247     return false;
    248   }
    249 
    250   // Get actual endpoint index for predefined read / write endpoints.
    251   if (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) {
    252     endpoint_index = def_read_endpoint_;
    253   } else if (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) {
    254     endpoint_index = def_write_endpoint_;
    255   }
    256 
    257   // Query endpoint information
    258   WINUSB_PIPE_INFORMATION pipe_info;
    259   if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint_index,
    260                         &pipe_info)) {
    261     return false;
    262   }
    263 
    264   // Save endpoint information into output.
    265   info->max_packet_size = pipe_info.MaximumPacketSize;
    266   info->max_transfer_size = 0xFFFFFFFF;
    267   info->endpoint_address = pipe_info.PipeId;
    268   info->polling_interval = pipe_info.Interval;
    269   info->setting_index = interface_number();
    270   switch (pipe_info.PipeType) {
    271     case UsbdPipeTypeControl:
    272       info->endpoint_type = AdbEndpointTypeControl;
    273       break;
    274 
    275     case UsbdPipeTypeIsochronous:
    276       info->endpoint_type = AdbEndpointTypeIsochronous;
    277       break;
    278 
    279     case UsbdPipeTypeBulk:
    280       info->endpoint_type = AdbEndpointTypeBulk;
    281       break;
    282 
    283     case UsbdPipeTypeInterrupt:
    284       info->endpoint_type = AdbEndpointTypeInterrupt;
    285       break;
    286 
    287     default:
    288       info->endpoint_type = AdbEndpointTypeInvalid;
    289       break;
    290   }
    291 
    292   return true;
    293 }
    294 
    295 ADBAPIHANDLE AdbWinUsbInterfaceObject::OpenEndpoint(
    296     UCHAR endpoint_index,
    297     AdbOpenAccessType access_type,
    298     AdbOpenSharingMode sharing_mode) {
    299   // Convert index into id
    300   UCHAR endpoint_id;
    301 
    302   if ((ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) ||
    303       (def_read_endpoint_ == endpoint_index)) {
    304     endpoint_id = read_endpoint_id_;
    305     endpoint_index = def_read_endpoint_;
    306   } else if ((ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) ||
    307              (def_write_endpoint_ == endpoint_index)) {
    308     endpoint_id = write_endpoint_id_;
    309     endpoint_index = def_write_endpoint_;
    310   } else {
    311     SetLastError(ERROR_INVALID_PARAMETER);
    312     return false;
    313   }
    314 
    315   return OpenEndpoint(endpoint_id, endpoint_index);
    316 }
    317 
    318 ADBAPIHANDLE AdbWinUsbInterfaceObject::OpenEndpoint(UCHAR endpoint_id,
    319                                                     UCHAR endpoint_index) {
    320   if (!IsOpened()) {
    321     SetLastError(ERROR_INVALID_HANDLE);
    322     return false;
    323   }
    324 
    325   AdbEndpointObject* adb_endpoint = NULL;
    326 
    327   try {
    328     adb_endpoint =
    329         new AdbWinUsbEndpointObject(this, endpoint_id, endpoint_index);
    330   } catch (...) {
    331     SetLastError(ERROR_OUTOFMEMORY);
    332     return NULL;
    333   }
    334 
    335   ADBAPIHANDLE ret = adb_endpoint->CreateHandle();
    336 
    337   adb_endpoint->Release();
    338 
    339   return ret;
    340 }
    341