Home | History | Annotate | Download | only in api
      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 helper routines used
     19   in the API.
     20 */
     21 
     22 #include "stdafx.h"
     23 #include "adb_api.h"
     24 #include "adb_api_legacy.h"
     25 #include "adb_helper_routines.h"
     26 #include "adb_interface_enum.h"
     27 
     28 bool GetSDKComplientParam(AdbOpenAccessType access_type,
     29                           AdbOpenSharingMode sharing_mode,
     30                           ULONG* desired_access,
     31                           ULONG* desired_sharing) {
     32   if (NULL != desired_access) {
     33     switch (access_type) {
     34       case AdbOpenAccessTypeReadWrite:
     35         *desired_access = GENERIC_READ | GENERIC_WRITE;
     36         break;
     37 
     38       case AdbOpenAccessTypeRead:
     39         *desired_access = GENERIC_READ;
     40         break;
     41 
     42       case AdbOpenAccessTypeWrite:
     43         *desired_access = GENERIC_WRITE;
     44         break;
     45 
     46       case AdbOpenAccessTypeQueryInfo:
     47         *desired_access = FILE_READ_ATTRIBUTES | FILE_READ_EA;
     48         break;
     49 
     50       default:
     51         SetLastError(ERROR_INVALID_ACCESS);
     52         return false;
     53     }
     54   }
     55 
     56   if (NULL != desired_sharing) {
     57     switch (sharing_mode) {
     58       case AdbOpenSharingModeReadWrite:
     59         *desired_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
     60         break;
     61 
     62       case AdbOpenSharingModeRead:
     63         *desired_sharing = FILE_SHARE_READ;
     64         break;
     65 
     66       case AdbOpenSharingModeWrite:
     67         *desired_sharing = FILE_SHARE_WRITE;
     68         break;
     69 
     70       case AdbOpenSharingModeExclusive:
     71         *desired_sharing = 0;
     72         break;
     73 
     74       default:
     75         SetLastError(ERROR_INVALID_PARAMETER);
     76         return false;
     77     }
     78   }
     79 
     80   return true;
     81 }
     82 
     83 bool EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info,
     84                                GUID class_id,
     85                                bool exclude_removed,
     86                                bool active_only,
     87                                AdbEnumInterfaceArray* interfaces) {
     88   AdbEnumInterfaceArray tmp;
     89   bool ret = false;
     90 
     91   // Enumerate interfaces on this device
     92   for (ULONG index = 0; ; index++) {
     93     SP_DEVICE_INTERFACE_DATA interface_data;
     94     interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
     95 
     96     // SetupDiEnumDeviceInterfaces() returns information about device
     97     // interfaces exposed by one or more devices defined by our interface
     98     // class. Each call returns information about one interface. The routine
     99     // can be called repeatedly to get information about several interfaces
    100     // exposed by one or more devices.
    101     if (SetupDiEnumDeviceInterfaces(hardware_dev_info,
    102                                     0,
    103                                     &class_id,
    104                                     index,
    105                                     &interface_data)) {
    106       // Satisfy "exclude removed" and "active only" filters.
    107       if ((!exclude_removed || (0 == (interface_data.Flags & SPINT_REMOVED))) &&
    108           (!active_only || (interface_data.Flags & SPINT_ACTIVE))) {
    109         std::wstring dev_name;
    110 
    111         if (GetUsbDeviceName(hardware_dev_info, &interface_data, &dev_name)) {
    112           try {
    113             // Add new entry to the array
    114             tmp.push_back(AdbInstanceEnumEntry(dev_name.c_str(),
    115                                                interface_data.InterfaceClassGuid,
    116                                                interface_data.Flags));
    117           } catch (... ) {
    118             SetLastError(ERROR_OUTOFMEMORY);
    119             break;
    120           }
    121         } else {
    122           // Something went wrong in getting device name
    123           break;
    124         }
    125       }
    126     } else {
    127       if (ERROR_NO_MORE_ITEMS == GetLastError()) {
    128         // There are no more items in the list. Enum is completed.
    129         ret = true;
    130         break;
    131       } else {
    132         // Something went wrong in SDK enum
    133         break;
    134       }
    135     }
    136   }
    137 
    138   // On success, swap temp array with the returning one
    139   if (ret)
    140     interfaces->swap(tmp);
    141 
    142   return ret;
    143 }
    144 
    145 bool EnumerateDeviceInterfaces(GUID class_id,
    146                                ULONG flags,
    147                                bool exclude_removed,
    148                                bool active_only,
    149                                AdbEnumInterfaceArray* interfaces) {
    150   // Open a handle to the plug and play dev node.
    151   // SetupDiGetClassDevs() returns a device information set that
    152   // contains info on all installed devices of a specified class.
    153   HDEVINFO hardware_dev_info =
    154     SetupDiGetClassDevs(&class_id, NULL, NULL, flags);
    155 
    156   bool ret = false;
    157 
    158   if (INVALID_HANDLE_VALUE != hardware_dev_info) {
    159     // Do the enum
    160     ret = EnumerateDeviceInterfaces(hardware_dev_info,
    161                                     class_id,
    162                                     exclude_removed,
    163                                     active_only,
    164                                     interfaces);
    165 
    166     // Preserve last error accross hardware_dev_info destruction
    167     ULONG error_to_report = ret ? NO_ERROR : GetLastError();
    168 
    169     SetupDiDestroyDeviceInfoList(hardware_dev_info);
    170 
    171     if (NO_ERROR != error_to_report)
    172       SetLastError(error_to_report);
    173   }
    174 
    175   return ret;
    176 }
    177 
    178 bool GetUsbDeviceDetails(
    179     HDEVINFO hardware_dev_info,
    180     PSP_DEVICE_INTERFACE_DATA dev_info_data,
    181     PSP_DEVICE_INTERFACE_DETAIL_DATA* dev_info_detail_data) {
    182   ULONG required_len = 0;
    183 
    184   // First query for the structure size. At this point we expect this call
    185   // to fail with ERROR_INSUFFICIENT_BUFFER error code.
    186   if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info,
    187                                       dev_info_data,
    188                                       NULL,
    189                                       0,
    190                                       &required_len,
    191                                       NULL)) {
    192     return false;
    193   }
    194 
    195   if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
    196     return false;
    197 
    198   // Allocate buffer for the structure
    199   PSP_DEVICE_INTERFACE_DETAIL_DATA buffer =
    200     reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(required_len));
    201 
    202   if (NULL == buffer) {
    203     SetLastError(ERROR_OUTOFMEMORY);
    204     return false;
    205   }
    206 
    207   buffer->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
    208 
    209   // Retrieve the information from Plug and Play.
    210   if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info,
    211                                       dev_info_data,
    212                                       buffer,
    213                                       required_len,
    214                                       &required_len,
    215                                       NULL)) {
    216     *dev_info_detail_data = buffer;
    217     return true;
    218   } else {
    219     // Free the buffer if this call failed
    220     free(buffer);
    221 
    222     return false;
    223   }
    224 }
    225 
    226 bool GetUsbDeviceName(HDEVINFO hardware_dev_info,
    227                       PSP_DEVICE_INTERFACE_DATA dev_info_data,
    228                       std::wstring* name) {
    229   PSP_DEVICE_INTERFACE_DETAIL_DATA func_class_dev_data = NULL;
    230   if (!GetUsbDeviceDetails(hardware_dev_info,
    231                            dev_info_data,
    232                            &func_class_dev_data)) {
    233     return false;
    234   }
    235 
    236   try {
    237     *name = func_class_dev_data->DevicePath;
    238   } catch (...) {
    239     SetLastError(ERROR_OUTOFMEMORY);
    240   }
    241 
    242   free(func_class_dev_data);
    243 
    244   return !name->empty();
    245 }
    246 
    247 bool IsLegacyInterface(const wchar_t* interface_name) {
    248   // Open USB device for this intefface
    249   HANDLE usb_device_handle = CreateFile(interface_name,
    250                                         GENERIC_READ | GENERIC_WRITE,
    251                                         FILE_SHARE_READ | FILE_SHARE_WRITE,
    252                                         NULL,
    253                                         OPEN_EXISTING,
    254                                         0,
    255                                         NULL);
    256   if (INVALID_HANDLE_VALUE == usb_device_handle)
    257     return NULL;
    258 
    259   // Try to issue ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR IOCTL that is supported
    260   // by the legacy driver, but is not implemented in the WinUsb driver.
    261   DWORD ret_bytes = 0;
    262   USB_DEVICE_DESCRIPTOR descriptor;
    263   BOOL ret = DeviceIoControl(usb_device_handle,
    264                              ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR,
    265                              NULL, 0,
    266                              &descriptor,
    267                              sizeof(descriptor),
    268                              &ret_bytes,
    269                              NULL);
    270   ::CloseHandle(usb_device_handle);
    271 
    272   // If IOCTL succeeded we've got legacy driver underneath.
    273   return ret ? true : false;
    274 }
    275