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