/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** \file This file consists of implementation of helper routines used in the API. */ #include "stdafx.h" #include "adb_api.h" #include "adb_api_legacy.h" #include "adb_helper_routines.h" #include "adb_interface_enum.h" bool GetSDKComplientParam(AdbOpenAccessType access_type, AdbOpenSharingMode sharing_mode, ULONG* desired_access, ULONG* desired_sharing) { if (NULL != desired_access) { switch (access_type) { case AdbOpenAccessTypeReadWrite: *desired_access = GENERIC_READ | GENERIC_WRITE; break; case AdbOpenAccessTypeRead: *desired_access = GENERIC_READ; break; case AdbOpenAccessTypeWrite: *desired_access = GENERIC_WRITE; break; case AdbOpenAccessTypeQueryInfo: *desired_access = FILE_READ_ATTRIBUTES | FILE_READ_EA; break; default: SetLastError(ERROR_INVALID_ACCESS); return false; } } if (NULL != desired_sharing) { switch (sharing_mode) { case AdbOpenSharingModeReadWrite: *desired_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; break; case AdbOpenSharingModeRead: *desired_sharing = FILE_SHARE_READ; break; case AdbOpenSharingModeWrite: *desired_sharing = FILE_SHARE_WRITE; break; case AdbOpenSharingModeExclusive: *desired_sharing = 0; break; default: SetLastError(ERROR_INVALID_PARAMETER); return false; } } return true; } bool EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info, GUID class_id, bool exclude_removed, bool active_only, AdbEnumInterfaceArray* interfaces) { AdbEnumInterfaceArray tmp; bool ret = false; // Enumerate interfaces on this device for (ULONG index = 0; ; index++) { SP_DEVICE_INTERFACE_DATA interface_data; interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); // SetupDiEnumDeviceInterfaces() returns information about device // interfaces exposed by one or more devices defined by our interface // class. Each call returns information about one interface. The routine // can be called repeatedly to get information about several interfaces // exposed by one or more devices. if (SetupDiEnumDeviceInterfaces(hardware_dev_info, 0, &class_id, index, &interface_data)) { // Satisfy "exclude removed" and "active only" filters. if ((!exclude_removed || (0 == (interface_data.Flags & SPINT_REMOVED))) && (!active_only || (interface_data.Flags & SPINT_ACTIVE))) { std::wstring dev_name; if (GetUsbDeviceName(hardware_dev_info, &interface_data, &dev_name)) { try { // Add new entry to the array tmp.push_back(AdbInstanceEnumEntry(dev_name.c_str(), interface_data.InterfaceClassGuid, interface_data.Flags)); } catch (... ) { SetLastError(ERROR_OUTOFMEMORY); break; } } else { // Something went wrong in getting device name break; } } } else { if (ERROR_NO_MORE_ITEMS == GetLastError()) { // There are no more items in the list. Enum is completed. ret = true; break; } else { // Something went wrong in SDK enum break; } } } // On success, swap temp array with the returning one if (ret) interfaces->swap(tmp); return ret; } bool EnumerateDeviceInterfaces(GUID class_id, ULONG flags, bool exclude_removed, bool active_only, AdbEnumInterfaceArray* interfaces) { // Open a handle to the plug and play dev node. // SetupDiGetClassDevs() returns a device information set that // contains info on all installed devices of a specified class. HDEVINFO hardware_dev_info = SetupDiGetClassDevs(&class_id, NULL, NULL, flags); bool ret = false; if (INVALID_HANDLE_VALUE != hardware_dev_info) { // Do the enum ret = EnumerateDeviceInterfaces(hardware_dev_info, class_id, exclude_removed, active_only, interfaces); // Preserve last error accross hardware_dev_info destruction ULONG error_to_report = ret ? NO_ERROR : GetLastError(); SetupDiDestroyDeviceInfoList(hardware_dev_info); if (NO_ERROR != error_to_report) SetLastError(error_to_report); } return ret; } bool GetUsbDeviceDetails( HDEVINFO hardware_dev_info, PSP_DEVICE_INTERFACE_DATA dev_info_data, PSP_DEVICE_INTERFACE_DETAIL_DATA* dev_info_detail_data) { ULONG required_len = 0; // First query for the structure size. At this point we expect this call // to fail with ERROR_INSUFFICIENT_BUFFER error code. if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info, dev_info_data, NULL, 0, &required_len, NULL)) { return false; } if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) return false; // Allocate buffer for the structure PSP_DEVICE_INTERFACE_DETAIL_DATA buffer = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(required_len)); if (NULL == buffer) { SetLastError(ERROR_OUTOFMEMORY); return false; } buffer->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // Retrieve the information from Plug and Play. if (SetupDiGetDeviceInterfaceDetail(hardware_dev_info, dev_info_data, buffer, required_len, &required_len, NULL)) { *dev_info_detail_data = buffer; return true; } else { // Free the buffer if this call failed free(buffer); return false; } } bool GetUsbDeviceName(HDEVINFO hardware_dev_info, PSP_DEVICE_INTERFACE_DATA dev_info_data, std::wstring* name) { PSP_DEVICE_INTERFACE_DETAIL_DATA func_class_dev_data = NULL; if (!GetUsbDeviceDetails(hardware_dev_info, dev_info_data, &func_class_dev_data)) { return false; } try { *name = func_class_dev_data->DevicePath; } catch (...) { SetLastError(ERROR_OUTOFMEMORY); } free(func_class_dev_data); return !name->empty(); } bool IsLegacyInterface(const wchar_t* interface_name) { // Open USB device for this intefface HANDLE usb_device_handle = CreateFile(interface_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == usb_device_handle) return NULL; // Try to issue ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR IOCTL that is supported // by the legacy driver, but is not implemented in the WinUsb driver. DWORD ret_bytes = 0; USB_DEVICE_DESCRIPTOR descriptor; BOOL ret = DeviceIoControl(usb_device_handle, ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR, NULL, 0, &descriptor, sizeof(descriptor), &ret_bytes, NULL); ::CloseHandle(usb_device_handle); // If IOCTL succeeded we've got legacy driver underneath. return ret ? true : false; }