/* * 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 class AdbLegacyInterfaceObject that encapsulates an interface on our USB device that is accessible */ #include "stdafx.h" #include "adb_api_legacy.h" #include "adb_legacy_interface.h" #include "adb_legacy_endpoint_object.h" AdbLegacyInterfaceObject::AdbLegacyInterfaceObject(const wchar_t* interf_name) : AdbInterfaceObject(interf_name), def_read_endpoint_(0xFF), read_endpoint_id_(0xFF), def_write_endpoint_(0xFF), write_endpoint_id_(0xFF) { } AdbLegacyInterfaceObject::~AdbLegacyInterfaceObject() { } ADBAPIHANDLE AdbLegacyInterfaceObject::CreateHandle() { // Open USB device for this intefface HANDLE usb_device_handle = CreateFile(interface_name().c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == usb_device_handle) { return NULL; } // Now, we ensured that our usb device / interface is up and running. // Lets collect device, interface and pipe information bool ok = true; if (!CacheUsbDeviceDescriptor(usb_device_handle) || !CacheUsbConfigurationDescriptor(usb_device_handle) || !CacheUsbInterfaceDescriptor(usb_device_handle)) { ok = false; } // Preserve error accross handle close ULONG error = ok ? NO_ERROR : GetLastError(); ::CloseHandle(usb_device_handle); if (NO_ERROR != error) { SetLastError(error); } if (!ok) { return false; } // Save indexes and IDs for bulk read / write endpoints. We will use them to // convert ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX and // ADB_QUERY_BULK_READ_ENDPOINT_INDEX into actual endpoint indexes and IDs. for (UCHAR endpoint = 0; endpoint < usb_interface_descriptor_.bNumEndpoints; endpoint++) { // Get endpoint information AdbEndpointInformation pipe_info; if (!GetEndpointInformation(endpoint, &pipe_info)) { return false; } if (AdbEndpointTypeBulk == pipe_info.endpoint_type) { // This is a bulk endpoint. Cache its index and ID. if (0 != (pipe_info.endpoint_address & USB_ENDPOINT_DIRECTION_MASK)) { // Use this endpoint as default bulk read endpoint ATLASSERT(0xFF == def_read_endpoint_); def_read_endpoint_ = endpoint; read_endpoint_id_ = pipe_info.endpoint_address; } else { // Use this endpoint as default bulk write endpoint ATLASSERT(0xFF == def_write_endpoint_); def_write_endpoint_ = endpoint; write_endpoint_id_ = pipe_info.endpoint_address; } } } return AdbObjectHandle::CreateHandle(); } bool AdbLegacyInterfaceObject::GetSerialNumber(void* buffer, unsigned long* buffer_char_size, bool ansi) { if (!IsOpened()) { SetLastError(ERROR_INVALID_HANDLE); return false; } // Open USB device for this intefface HANDLE usb_device_handle = CreateFile(interface_name().c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == usb_device_handle) { return NULL; } WCHAR serial_number[512]; // Send IOCTL DWORD ret_bytes = 0; BOOL ret = DeviceIoControl(usb_device_handle, ADB_IOCTL_GET_SERIAL_NUMBER, NULL, 0, serial_number, sizeof(serial_number), &ret_bytes, NULL); // Preserve error accross CloseHandle ULONG error = ret ? NO_ERROR : GetLastError(); ::CloseHandle(usb_device_handle); if (NO_ERROR != error) { SetLastError(error); return false; } unsigned long str_len = static_cast<unsigned long>(wcslen(serial_number) + 1); if ((NULL == buffer) || (*buffer_char_size < str_len)) { *buffer_char_size = str_len; SetLastError(ERROR_INSUFFICIENT_BUFFER); return false; } if (!ansi) { // If user asked for wide char name just return it wcscpy(reinterpret_cast<wchar_t*>(buffer), serial_number); return true; } // We need to convert name from wide char to ansi string int res = WideCharToMultiByte(CP_ACP, 0, serial_number, static_cast<int>(str_len), reinterpret_cast<PSTR>(buffer), static_cast<int>(*buffer_char_size), NULL, NULL); return (res != 0); } bool AdbLegacyInterfaceObject::GetEndpointInformation( UCHAR endpoint_index, AdbEndpointInformation* info) { // Open USB device for this intefface HANDLE usb_device_handle = CreateFile(interface_name().c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == usb_device_handle) { return NULL; } // Init ICTL param AdbQueryEndpointInformation param; param.endpoint_index = endpoint_index; // Send IOCTL DWORD ret_bytes = 0; BOOL ret = DeviceIoControl(usb_device_handle, ADB_IOCTL_GET_ENDPOINT_INFORMATION, ¶m, sizeof(param), info, sizeof(AdbEndpointInformation), &ret_bytes, NULL); ATLASSERT(!ret || (sizeof(AdbEndpointInformation) == ret_bytes)); // Preserve error accross CloseHandle ULONG error = ret ? NO_ERROR : GetLastError(); ::CloseHandle(usb_device_handle); if (NO_ERROR != error) { SetLastError(error); } return ret ? true : false; } ADBAPIHANDLE AdbLegacyInterfaceObject::OpenEndpoint( UCHAR endpoint_index, AdbOpenAccessType access_type, AdbOpenSharingMode sharing_mode) { // Convert index into name and ID. std::wstring endpoint_name; UCHAR endpoint_id; try { if ((ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) || (def_read_endpoint_ == endpoint_index)) { endpoint_name = DEVICE_BULK_READ_PIPE_NAME; endpoint_id = read_endpoint_id_; endpoint_index = def_read_endpoint_; } else if ((ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) || (def_write_endpoint_ == endpoint_index)) { endpoint_name = DEVICE_BULK_WRITE_PIPE_NAME; endpoint_id = write_endpoint_id_; endpoint_index = def_write_endpoint_; } else { SetLastError(ERROR_INVALID_PARAMETER); return false; } } catch (...) { // We don't expect exceptions other than OOM thrown here. SetLastError(ERROR_OUTOFMEMORY); return NULL; } return OpenEndpoint(endpoint_name.c_str(), endpoint_id, endpoint_index, access_type, sharing_mode); } ADBAPIHANDLE AdbLegacyInterfaceObject::OpenEndpoint( const wchar_t* endpoint_name, UCHAR endpoint_id, UCHAR endpoint_index, AdbOpenAccessType access_type, AdbOpenSharingMode sharing_mode) { if (!IsOpened()) { SetLastError(ERROR_INVALID_HANDLE); return false; } AdbLegacyEndpointObject* adb_endpoint = NULL; try { adb_endpoint = new AdbLegacyEndpointObject(this, endpoint_id, endpoint_index); } catch (...) { // We don't expect exceptions other than OOM thrown here. SetLastError(ERROR_OUTOFMEMORY); return NULL; } // Build full path to the object std::wstring endpoint_path = interface_name(); endpoint_path += L"\\"; endpoint_path += endpoint_name; ADBAPIHANDLE ret = adb_endpoint->CreateHandle(endpoint_path.c_str(), access_type, sharing_mode); adb_endpoint->Release(); return ret; } bool AdbLegacyInterfaceObject::CacheUsbDeviceDescriptor( HANDLE usb_device_handle) { DWORD ret_bytes = 0; BOOL ret = DeviceIoControl(usb_device_handle, ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR, NULL, 0, &usb_device_descriptor_, sizeof(usb_device_descriptor_), &ret_bytes, NULL); ATLASSERT(!ret || (sizeof(USB_DEVICE_DESCRIPTOR) == ret_bytes)); return ret ? true : false; } bool AdbLegacyInterfaceObject::CacheUsbConfigurationDescriptor( HANDLE usb_device_handle) { DWORD ret_bytes = 0; BOOL ret = DeviceIoControl(usb_device_handle, ADB_IOCTL_GET_USB_CONFIGURATION_DESCRIPTOR, NULL, 0, &usb_config_descriptor_, sizeof(usb_config_descriptor_), &ret_bytes, NULL); ATLASSERT(!ret || (sizeof(USB_CONFIGURATION_DESCRIPTOR) == ret_bytes)); return ret ? true : false; } bool AdbLegacyInterfaceObject::CacheUsbInterfaceDescriptor( HANDLE usb_device_handle) { DWORD ret_bytes = 0; BOOL ret = DeviceIoControl(usb_device_handle, ADB_IOCTL_GET_USB_INTERFACE_DESCRIPTOR, NULL, 0, &usb_interface_descriptor_, sizeof(usb_interface_descriptor_), &ret_bytes, NULL); ATLASSERT(!ret || (sizeof(USB_INTERFACE_DESCRIPTOR) == ret_bytes)); return ret ? true : false; }