| /* | |
| * 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; | |
| } |