adb_helper_routines.cpp revision 59fc68ba26dca2543bd96a71254e6b124243fb66
1/* 2 * Copyright (C) 2006 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 28bool EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info, 29 GUID class_id, 30 bool exclude_removed, 31 bool active_only, 32 AdbEnumInterfaceArray* interfaces) { 33 AdbEnumInterfaceArray tmp; 34 bool ret = false; 35 36 // Enumerate interfaces on this device 37 for (ULONG index = 0; ; index++) { 38 SP_DEVICE_INTERFACE_DATA interface_data; 39 interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 40 41 // SetupDiEnumDeviceInterfaces() returns information about device 42 // interfaces exposed by one or more devices defined by our interface 43 // class. Each call returns information about one interface. The routine 44 // can be called repeatedly to get information about several interfaces 45 // exposed by one or more devices. 46 if (SetupDiEnumDeviceInterfaces(hardware_dev_info, 47 0, 48 &class_id, 49 index, 50 &interface_data)) { 51 // Satisfy "exclude removed" and "active only" filters. 52 if ((!exclude_removed || (0 == (interface_data.Flags & SPINT_REMOVED))) && 53 (!active_only || (interface_data.Flags & SPINT_ACTIVE))) { 54 std::wstring dev_name; 55 56 if (GetUsbDeviceName(hardware_dev_info, &interface_data, &dev_name)) { 57 try { 58 // Add new entry to the array 59 tmp.push_back(AdbInstanceEnumEntry(dev_name.c_str(), 60 interface_data.InterfaceClassGuid, 61 interface_data.Flags)); 62 } catch (... ) { 63 SetLastError(ERROR_OUTOFMEMORY); 64 break; 65 } 66 } else { 67 // Something went wrong in getting device name 68 break; 69 } 70 } 71 } else { 72 if (ERROR_NO_MORE_ITEMS == GetLastError()) { 73 // There are no more items in the list. Enum is completed. 74 ret = true; 75 break; 76 } else { 77 // Something went wrong in SDK enum 78 break; 79 } 80 } 81 } 82 83 // On success, swap temp array with the returning one 84 if (ret) 85 interfaces->swap(tmp); 86 87 return ret; 88} 89 90bool EnumerateDeviceInterfaces(GUID class_id, 91 ULONG flags, 92 bool exclude_removed, 93 bool active_only, 94 AdbEnumInterfaceArray* interfaces) { 95 // Open a handle to the plug and play dev node. 96 // SetupDiGetClassDevs() returns a device information set that 97 // contains info on all installed devices of a specified class. 98 HDEVINFO hardware_dev_info = 99 SetupDiGetClassDevs(&class_id, NULL, NULL, flags); 100 101 bool ret = false; 102 103 if (INVALID_HANDLE_VALUE != hardware_dev_info) { 104 // Do the enum 105 ret = EnumerateDeviceInterfaces(hardware_dev_info, 106 class_id, 107 exclude_removed, 108 active_only, 109 interfaces); 110 111 // Preserve last error accross hardware_dev_info destruction 112 ULONG error_to_report = ret ? NO_ERROR : GetLastError(); 113 114 SetupDiDestroyDeviceInfoList(hardware_dev_info); 115 116 if (NO_ERROR != error_to_report) 117 SetLastError(error_to_report); 118 } 119 120 return ret; 121} 122 123bool GetUsbDeviceDetails( 124 HDEVINFO hardware_dev_info, 125 PSP_DEVICE_INTERFACE_DATA dev_info_data, 126 PSP_DEVICE_INTERFACE_DETAIL_DATA* dev_info_detail_data) { 127 ULONG required_len = 0; 128 129 // First query for the structure size. At this point we expect this call 130 // to fail with ERROR_INSUFFICIENT_BUFFER error code. 131 if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info, 132 dev_info_data, 133 NULL, 134 0, 135 &required_len, 136 NULL)) { 137 return false; 138 } 139 140 if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) 141 return false; 142 143 // Allocate buffer for the structure 144 PSP_DEVICE_INTERFACE_DETAIL_DATA buffer = 145 reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(required_len)); 146 147 if (NULL == buffer) { 148 SetLastError(ERROR_OUTOFMEMORY); 149 return false; 150 } 151 152 buffer->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); 153 154 // Retrieve the information from Plug and Play. 155 if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info, 156 dev_info_data, 157 buffer, 158 required_len, 159 &required_len, 160 NULL)) { 161 *dev_info_detail_data = buffer; 162 return true; 163 } else { 164 // Free the buffer if this call failed 165 free(buffer); 166 167 return false; 168 } 169} 170 171bool GetUsbDeviceName(HDEVINFO hardware_dev_info, 172 PSP_DEVICE_INTERFACE_DATA dev_info_data, 173 std::wstring* name) { 174 PSP_DEVICE_INTERFACE_DETAIL_DATA func_class_dev_data = NULL; 175 if (!GetUsbDeviceDetails(hardware_dev_info, 176 dev_info_data, 177 &func_class_dev_data)) { 178 return false; 179 } 180 181 try { 182 *name = func_class_dev_data->DevicePath; 183 } catch (...) { 184 SetLastError(ERROR_OUTOFMEMORY); 185 } 186 187 free(func_class_dev_data); 188 189 return !name->empty(); 190} 191 192bool IsLegacyInterface(const wchar_t* interface_name) { 193 // Open USB device for this intefface 194 HANDLE usb_device_handle = CreateFile(interface_name, 195 GENERIC_READ | GENERIC_WRITE, 196 FILE_SHARE_READ | FILE_SHARE_WRITE, 197 NULL, 198 OPEN_EXISTING, 199 0, 200 NULL); 201 if (INVALID_HANDLE_VALUE == usb_device_handle) 202 return NULL; 203 204 // Try to issue ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR IOCTL that is supported 205 // by the legacy driver, but is not implemented in the WinUsb driver. 206 DWORD ret_bytes = 0; 207 USB_DEVICE_DESCRIPTOR descriptor; 208 BOOL ret = DeviceIoControl(usb_device_handle, 209 ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR, 210 NULL, 0, 211 &descriptor, 212 sizeof(descriptor), 213 &ret_bytes, 214 NULL); 215 ::CloseHandle(usb_device_handle); 216 217 // If IOCTL succeeded we've got legacy driver underneath. 218 return ret ? true : false; 219} 220