diff --git a/host/windows/usb/api/SOURCES b/host/windows/usb/api/SOURCES index fcca80288..4b9d3605b 100755 --- a/host/windows/usb/api/SOURCES +++ b/host/windows/usb/api/SOURCES @@ -85,12 +85,16 @@ PRECOMPILED_INCLUDE = stdafx.h PRECOMPILED_SOURCEFILE = stdafx.cpp # Define source files for AdbWinApi.dll -SOURCES = adb_api.cpp \ - adb_endpoint_object.cpp \ - adb_helper_routines.cpp \ - adb_interface.cpp \ - adb_interface_enum.cpp \ - adb_io_completion.cpp \ - adb_object_handle.cpp \ - AdbWinApi.cpp \ +SOURCES = adb_api.cpp \ + adb_endpoint_object.cpp \ + adb_winusb_endpoint_object.cpp \ + adb_helper_routines.cpp \ + adb_interface.cpp \ + adb_winusb_interface.cpp \ + adb_legacy_interface.cpp \ + adb_interface_enum.cpp \ + adb_io_completion.cpp \ + adb_winusb_io_completion.cpp \ + adb_object_handle.cpp \ + AdbWinApi.cpp \ AdbWinApi.rc diff --git a/host/windows/usb/api/adb_api.cpp b/host/windows/usb/api/adb_api.cpp index eadf07abc..f9bd94e6c 100644 --- a/host/windows/usb/api/adb_api.cpp +++ b/host/windows/usb/api/adb_api.cpp @@ -24,6 +24,8 @@ #include "adb_object_handle.h" #include "adb_interface_enum.h" #include "adb_interface.h" +#include "adb_winusb_interface.h" +#include "adb_legacy_interface.h" #include "adb_endpoint_object.h" #include "adb_io_completion.h" #include "adb_helper_routines.h" @@ -100,7 +102,11 @@ ADBAPIHANDLE __cdecl AdbCreateInterfaceByName( try { // Instantiate object - obj = new AdbInterfaceObject(interface_name); + if (IsLegacyInterface(interface_name)) { + obj = new AdbLegacyInterfaceObject(interface_name); + } else { + obj = new AdbWinUsbInterfaceObject(interface_name); + } // Create handle for it ret = obj->CreateHandle(); diff --git a/host/windows/usb/api/adb_api.h b/host/windows/usb/api/adb_api.h index e503238da..900ea40cd 100644 --- a/host/windows/usb/api/adb_api.h +++ b/host/windows/usb/api/adb_api.h @@ -16,11 +16,14 @@ #ifndef ANDROID_USB_API_ADBWINAPI_H__ #define ANDROID_USB_API_ADBWINAPI_H__ + /** \file This file consists of declarations of routines exported by the API as well as types, structures, and constants definitions used in the API. */ +#include "adb_api_legacy.h" + // Enables compillation for "straight" C #ifdef __cplusplus #define EXTERN_C extern "C" diff --git a/host/windows/usb/api/adb_api_legacy.h b/host/windows/usb/api/adb_api_legacy.h new file mode 100755 index 000000000..d6a62d843 --- /dev/null +++ b/host/windows/usb/api/adb_api_legacy.h @@ -0,0 +1,190 @@ +/* + * 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. + */ + +#ifndef ANDROID_USB_API_ADB_API_LEGACY_H_ +#define ANDROID_USB_API_ADB_API_LEGACY_H_ +/** \file + This file consists of declarations of constants and structures required + for supporting communications of this API with a legacy (custom) USB + driver. +*/ + +// Enables compillation for "straight" C +#ifdef __cplusplus + #define EXTERN_C extern "C" +#else + #define EXTERN_C extern + typedef int bool; + #define true 1 + #define false 0 +#endif + +/// Name for the default bulk read pipe +#define DEVICE_BULK_READ_PIPE_NAME L"BulkRead" + +/// Name for the default bulk write pipe +#define DEVICE_BULK_WRITE_PIPE_NAME L"BulkWrite" + +/// Prefix for an index-based pipe name +#define DEVICE_PIPE_NAME_PREFIX L"PIPE_" + +/** \name IOCTL codes for the driver +*/ +///@{ + +/// Control code for IOCTL that gets USB_DEVICE_DESCRIPTOR +#define ADB_CTL_GET_USB_DEVICE_DESCRIPTOR 10 + +/// Control code for IOCTL that gets USB_CONFIGURATION_DESCRIPTOR +#define ADB_CTL_GET_USB_CONFIGURATION_DESCRIPTOR 11 + +/// Control code for IOCTL that gets USB_INTERFACE_DESCRIPTOR +#define ADB_CTL_GET_USB_INTERFACE_DESCRIPTOR 12 + +/// Control code for IOCTL that gets endpoint information +#define ADB_CTL_GET_ENDPOINT_INFORMATION 13 + +/// Control code for bulk read IOCTL +#define ADB_CTL_BULK_READ 14 + +/// Control code for bulk write IOCTL +#define ADB_CTL_BULK_WRITE 15 + +/// Control code for IOCTL that gets device serial number +#define ADB_CTL_GET_SERIAL_NUMBER 16 + +/// IOCTL that gets USB_DEVICE_DESCRIPTOR +#define ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR \ + CTL_CODE(FILE_DEVICE_UNKNOWN, \ + ADB_CTL_GET_USB_DEVICE_DESCRIPTOR, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +/// IOCTL that gets USB_CONFIGURATION_DESCRIPTOR +#define ADB_IOCTL_GET_USB_CONFIGURATION_DESCRIPTOR \ + CTL_CODE(FILE_DEVICE_UNKNOWN, \ + ADB_CTL_GET_USB_CONFIGURATION_DESCRIPTOR, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +/// IOCTL that gets USB_INTERFACE_DESCRIPTOR +#define ADB_IOCTL_GET_USB_INTERFACE_DESCRIPTOR \ + CTL_CODE(FILE_DEVICE_UNKNOWN, \ + ADB_CTL_GET_USB_INTERFACE_DESCRIPTOR, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +/// IOCTL that gets endpoint information +#define ADB_IOCTL_GET_ENDPOINT_INFORMATION \ + CTL_CODE(FILE_DEVICE_UNKNOWN, \ + ADB_CTL_GET_ENDPOINT_INFORMATION, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +/// Bulk read IOCTL +#define ADB_IOCTL_BULK_READ \ + CTL_CODE(FILE_DEVICE_UNKNOWN, \ + ADB_CTL_BULK_READ, \ + METHOD_OUT_DIRECT, \ + FILE_READ_ACCESS) + +// For bulk write IOCTL we send request data in the form of AdbBulkTransfer +// structure and output buffer is just ULONG that receives number of bytes +// actually written. Since both of these are tiny we can use buffered I/O +// for this IOCTL. +/// Bulk write IOCTL +#define ADB_IOCTL_BULK_WRITE \ + CTL_CODE(FILE_DEVICE_UNKNOWN, \ + ADB_CTL_BULK_WRITE, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL that gets device serial number +#define ADB_IOCTL_GET_SERIAL_NUMBER \ + CTL_CODE(FILE_DEVICE_UNKNOWN, \ + ADB_CTL_GET_SERIAL_NUMBER, \ + METHOD_BUFFERED, \ + FILE_READ_ACCESS) + +///@} + +/** Structure AdbQueryEndpointInformation formats input for + ADB_IOCTL_GET_ENDPOINT_INFORMATION IOCTL request +*/ +struct AdbQueryEndpointInformation { + /// Zero-based endpoint index for which information is queried. + /// See ADB_QUERY_BULK_xxx_ENDPOINT_INDEX for shortcuts. + UCHAR endpoint_index; +}; + +/** Structure AdbBulkTransfer formats parameters for ADB_CTL_BULK_READ and + ADB_CTL_BULK_WRITE IOCTL requests. +*/ +struct AdbBulkTransfer { + /// Time in milliseconds to complete this request + ULONG time_out; + + /// Size of the data to transfer. This parameter is used only for + /// ADB_CTL_BULK_WRITE request. For ADB_CTL_BULK_READ requests transfer + /// size is defined by the output buffer size. + ULONG transfer_size; + + /// Initializes statically allocated structure + __forceinline AdbBulkTransfer() { + time_out = 0; + transfer_size = 0; + for_x64 = 0; + } + + /// Provides access to protected write_buffer field + void* GetWriteBuffer() { + return write_buffer; + } + + /// Provides access to protected write_buffer field + const void* GetWriteBuffer() const { + return write_buffer; + } + + /// Sets write_buffer field. + void SetWriteBuffer(void* buffer) { + // For 32-bit we must zero out high 32 bit of the address, so 64-bit + // driver will see valid address when accessing 64-bit write_buffer. + for_x64 = 0; + write_buffer = buffer; + } + +protected: + /// Pointer to the actual buffer for ADB_CTL_BULK_WRITE request. This field + /// is not used in ADB_CTL_BULK_READ request. Note that in order to support + /// compatibility between 32-bit and 64-bit versions of both, driver and + /// application we must sizeof this field to the max pointer sizeof (which + /// is 64 bit in our case). The idea is that if IOCTL was issued by a 64-bit + /// process to a 64-bit driver, write_buffer will be valid 64-bit pointer to + /// the write buffer. Same is true for 32-bit app talking to 32-bit driver. + /// If, however, a 32-bit app is talking to 64-bit driver, then write_buffer + /// initialized by 32-bit app will contain 32-bit address, which will be + /// correctly picked up ("extended") by 64-bit driver. Since when setting + /// this field by a 32-bit app requires some extra work (see SetWriteBuffer) + /// we hide this field, making it accessible only throug the accessor + /// methods (Get/SetWriteBuffer). + union { + void* write_buffer; + __int64 for_x64; + }; +}; + +#endif // ANDROID_USB_API_ADB_API_LEGACY_H_ diff --git a/host/windows/usb/api/adb_endpoint_object.cpp b/host/windows/usb/api/adb_endpoint_object.cpp index 9237a6021..6e093e2ae 100644 --- a/host/windows/usb/api/adb_endpoint_object.cpp +++ b/host/windows/usb/api/adb_endpoint_object.cpp @@ -15,14 +15,12 @@ */ /** \file - This file consists of implementation of class AdbIOObject that - encapsulates an interface on our USB device. + This file consists of implementation of class AdbEndpointObject that + encapsulates a handle opened to an endpoint on our device. */ #include "stdafx.h" #include "adb_endpoint_object.h" -#include "adb_io_completion.h" -#include "adb_helper_routines.h" AdbEndpointObject::AdbEndpointObject(AdbInterfaceObject* parent_interf, UCHAR endpoint_id, @@ -96,126 +94,3 @@ bool AdbEndpointObject::SyncWrite(void* buffer, bytes_written, time_out); } - -ADBAPIHANDLE AdbEndpointObject::CommonAsyncReadWrite(bool is_read, - void* buffer, - ULONG bytes_to_transfer, - ULONG* bytes_transferred, - HANDLE event_handle, - ULONG time_out) { - if (!SetTimeout(time_out)) - return false; - - // Create completion i/o object - AdbIOCompletion* adb_io_completion = NULL; - - try { - adb_io_completion = new AdbIOCompletion(this, - bytes_to_transfer, - event_handle); - } catch (... ) { - SetLastError(ERROR_OUTOFMEMORY); - return NULL; - } - - // Create a handle for it - ADBAPIHANDLE ret = adb_io_completion->CreateHandle(); - ULONG transferred = 0; - if (NULL != ret) { - BOOL res = TRUE; - // Go the read / write file way - res = is_read ? - WinUsb_ReadPipe(parent_interface()->winusb_handle(), - endpoint_id(), - reinterpret_cast(buffer), - bytes_to_transfer, - &transferred, - adb_io_completion->overlapped()) : - WinUsb_WritePipe(parent_interface()->winusb_handle(), - endpoint_id(), - reinterpret_cast(buffer), - bytes_to_transfer, - &transferred, - adb_io_completion->overlapped()); - - if (NULL != bytes_transferred) - *bytes_transferred = transferred; - - ULONG error = GetLastError(); - if (!res && (ERROR_IO_PENDING != error)) { - // I/O failed immediatelly. We need to close i/o completion object - // before we return NULL to the caller. - adb_io_completion->CloseHandle(); - ret = NULL; - SetLastError(error); - } - } - - // Offseting 'new' - adb_io_completion->Release(); - - return ret; -} - -bool AdbEndpointObject::CommonSyncReadWrite(bool is_read, - void* buffer, - ULONG bytes_to_transfer, - ULONG* bytes_transferred, - ULONG time_out) { - if (!SetTimeout(time_out)) - return false; - - // This is synchronous I/O. Since we always open I/O items for - // overlapped I/O we're obligated to always provide OVERLAPPED - // structure to read / write routines. Prepare it now. - OVERLAPPED overlapped; - ZeroMemory(&overlapped, sizeof(overlapped)); - overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - - BOOL ret = TRUE; - ULONG transferred = 0; - // Go the read / write file way - ret = is_read ? - WinUsb_ReadPipe(parent_interface()->winusb_handle(), - endpoint_id(), - reinterpret_cast(buffer), - bytes_to_transfer, - &transferred, - &overlapped) : - WinUsb_WritePipe(parent_interface()->winusb_handle(), - endpoint_id(), - reinterpret_cast(buffer), - bytes_to_transfer, - &transferred, - &overlapped); - - // Lets see the result - if (!ret && (ERROR_IO_PENDING != GetLastError())) { - // I/O failed. - if (NULL != overlapped.hEvent) - ::CloseHandle(overlapped.hEvent); - return false; - } - - // Lets wait till I/O completes - ret = WinUsb_GetOverlappedResult(parent_interface()->winusb_handle(), &overlapped, - &transferred, TRUE); - if (ret && (NULL != bytes_transferred)) { - *bytes_transferred = transferred; - } - - if (NULL != overlapped.hEvent) - ::CloseHandle(overlapped.hEvent); - - return ret ? true : false; -} - -bool AdbEndpointObject::SetTimeout(ULONG timeout) { - if (!WinUsb_SetPipePolicy(parent_interface()->winusb_handle(), - endpoint_id(), PIPE_TRANSFER_TIMEOUT, - sizeof(ULONG), &timeout)) { - return false; - } - - return true; -} diff --git a/host/windows/usb/api/adb_endpoint_object.h b/host/windows/usb/api/adb_endpoint_object.h index d4d1a6a08..295eb46f2 100644 --- a/host/windows/usb/api/adb_endpoint_object.h +++ b/host/windows/usb/api/adb_endpoint_object.h @@ -17,14 +17,17 @@ #ifndef ANDROID_USB_API_ADB_ENDPOINT_OBJECT_H__ #define ANDROID_USB_API_ADB_ENDPOINT_OBJECT_H__ /** \file - This file consists of declaration of class AdbIOObject that encapsulates a - handle opened to an endpoint on our device. + This file consists of declaration of class AdbEndpointObject that + encapsulates a handle opened to an endpoint on our device. */ #include "adb_interface.h" /** Class AdbEndpointObject encapsulates a handle opened to an endpoint on our device. + + This class implement functionality that is common for both, WinUsb and + legacy APIs. */ class AdbEndpointObject : public AdbObjectHandle { public: @@ -49,6 +52,55 @@ class AdbEndpointObject : public AdbObjectHandle { */ virtual ~AdbEndpointObject(); + // + // Abstract + // + + protected: + /** \brief Common code for async read / write + + @param[in] is_read Read or write selector. + @param[in,out] buffer Pointer to the buffer for read / write. + @param[in] bytes_to_transfer Number of bytes to be read / written. + @param[out] bytes_transferred Number of bytes read / written. Can be NULL. + @param[in] event_handle Event handle that should be signaled when async I/O + completes. Can be NULL. If it's not NULL this handle will be used to + initialize OVERLAPPED structure for this I/O. + @param[in] time_out A timeout (in milliseconds) required for this I/O to + complete. Zero value in this parameter means that there is no + timeout set for this I/O. + @return A handle to IO completion object or NULL on failure. If NULL is + returned GetLastError() provides extended error information. + */ + virtual ADBAPIHANDLE CommonAsyncReadWrite(bool is_read, + void* buffer, + ULONG bytes_to_transfer, + ULONG* bytes_transferred, + HANDLE event_handle, + ULONG time_out) = 0; + + /** \brief Common code for sync read / write + + @param[in] is_read Read or write selector. + @param[in,out] buffer Pointer to the buffer for read / write. + @param[in] bytes_to_transfer Number of bytes to be read / written. + @param[out] bytes_transferred Number of bytes read / written. Can be NULL. + @param[in] time_out A timeout (in milliseconds) required for this I/O to + complete. Zero value in this parameter means that there is no + timeout set for this I/O. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool CommonSyncReadWrite(bool is_read, + void* buffer, + ULONG bytes_to_transfer, + ULONG* bytes_transferred, + ULONG time_out) = 0; + + // + // Operations + // + public: /** \brief Gets information about this endpoint. @@ -56,7 +108,7 @@ class AdbEndpointObject : public AdbObjectHandle { @return true on success, false on failure. If false is returned GetLastError() provides extended error information. */ - bool GetEndpointInformation(AdbEndpointInformation* info); + virtual bool GetEndpointInformation(AdbEndpointInformation* info); /** \brief Reads from opened I/O object asynchronously @@ -130,64 +182,6 @@ class AdbEndpointObject : public AdbObjectHandle { ULONG* bytes_written, ULONG time_out); - protected: - /** \brief Common code for async read / write - - @param[in] is_read Read or write selector. - @param[in,out] buffer Pointer to the buffer for read / write. - @param[in] bytes_to_transfer Number of bytes to be read / written. - @param[out] bytes_transferred Number of bytes read / written. Can be NULL. - @param[in] event_handle Event handle that should be signaled when async I/O - completes. Can be NULL. If it's not NULL this handle will be used to - initialize OVERLAPPED structure for this I/O. - @param[in] time_out A timeout (in milliseconds) required for this I/O to - complete. Zero value in this parameter means that there is no - timeout set for this I/O. - @return A handle to IO completion object or NULL on failure. If NULL is - returned GetLastError() provides extended error information. - */ - virtual ADBAPIHANDLE CommonAsyncReadWrite(bool is_read, - void* buffer, - ULONG bytes_to_transfer, - ULONG* bytes_transferred, - HANDLE event_handle, - ULONG time_out); - - /** \brief Common code for sync read / write - - @param[in] is_read Read or write selector. - @param[in,out] buffer Pointer to the buffer for read / write. - @param[in] bytes_to_transfer Number of bytes to be read / written. - @param[out] bytes_transferred Number of bytes read / written. Can be NULL. - @param[in] time_out A timeout (in milliseconds) required for this I/O to - complete. Zero value in this parameter means that there is no - timeout set for this I/O. - @return true on success, false on failure. If false is returned - GetLastError() provides extended error information. - */ - virtual bool CommonSyncReadWrite(bool is_read, - void* buffer, - ULONG bytes_to_transfer, - ULONG* bytes_transferred, - ULONG time_out); - /** \brief Sets read / write operation timeout. - - @param[in] timeout Timeout value in milliseconds to use for current read - or write operation. Zero value passed in this parameters indicate - not timeout at all. Note that timeout that is set with this method is - global per endpoint (pipe). I.e. once set, it will be used against - all read / write operations performed on this endpoint, untill - another call to this method modifies it. This is a WinUsb design - flaw. Microsoft is aware of this and (hopefuly) future versions of - WinUsb framework will accept a timeout parameter in WinUsb_Read/Write - routines. For the purposes of ADB this flaw doesn't apperar to be an - issue, since we use single-threaded synchronous read / writes, so - there is no conflict in setting per-endpoint timeouts. - @return true on success, false on failure. If false is returned - GetLastError() provides extended error information. - */ - virtual bool SetTimeout(ULONG timeout); - public: /// This is a helper for extracting object from the AdbObjectHandleMap static AdbObjectType Type() { @@ -214,11 +208,6 @@ class AdbEndpointObject : public AdbObjectHandle { NULL; } - /// Gets parent interface WinUsb handle - WINUSB_INTERFACE_HANDLE winusb_handle() const { - return parent_interface()->winusb_handle(); - } - protected: /// Parent interface AdbInterfaceObject* parent_interface_; diff --git a/host/windows/usb/api/adb_helper_routines.cpp b/host/windows/usb/api/adb_helper_routines.cpp index 3a7748bbc..0bc44df4b 100644 --- a/host/windows/usb/api/adb_helper_routines.cpp +++ b/host/windows/usb/api/adb_helper_routines.cpp @@ -187,3 +187,32 @@ bool GetUsbDeviceName(HDEVINFO hardware_dev_info, 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; +} diff --git a/host/windows/usb/api/adb_helper_routines.h b/host/windows/usb/api/adb_helper_routines.h index 68a20a9b7..907e638bf 100644 --- a/host/windows/usb/api/adb_helper_routines.h +++ b/host/windows/usb/api/adb_helper_routines.h @@ -106,4 +106,15 @@ bool GetUsbDeviceName(HDEVINFO hardware_dev_info, PSP_DEVICE_INTERFACE_DATA dev_info_data, std::wstring* name); +/** \brief Checks if given interface is available via custom USB driver. + + In this routine we will query the given interface with an IOCTL that should + be supported by the custom driver. If IOCTL fails, we make a conclusion that + this interface is available via WinUsb, and not via custom USB driver. + @param[in] interface_name Name of the interface to check. + @return true if interface is available via custom USB driver, or false + otherwise. +*/ +bool IsLegacyInterface(const wchar_t* interface_name); + #endif // ANDROID_USB_API_ADB_HELPER_ROUTINES_H__ diff --git a/host/windows/usb/api/adb_interface.cpp b/host/windows/usb/api/adb_interface.cpp index 9b073a4df..a0803aa83 100644 --- a/host/windows/usb/api/adb_interface.cpp +++ b/host/windows/usb/api/adb_interface.cpp @@ -16,117 +16,19 @@ /** \file This file consists of implementation of class AdbInterfaceObject that - encapsulates an interface on our USB device. + encapsulates a generic interface on our USB device. */ #include "stdafx.h" #include "adb_interface.h" -#include "adb_endpoint_object.h" AdbInterfaceObject::AdbInterfaceObject(const wchar_t* interf_name) : AdbObjectHandle(AdbObjectTypeInterface), - interface_name_(interf_name), - usb_device_handle_(INVALID_HANDLE_VALUE), - winusb_handle_(NULL), - interface_number_(0xFF), - def_read_endpoint_(0xFF), - read_endpoint_id_(0xFF), - def_write_endpoint_(0xFF), - write_endpoint_id_(0xFF) { + interface_name_(interf_name) { ATLASSERT(NULL != interf_name); } AdbInterfaceObject::~AdbInterfaceObject() { - ATLASSERT(NULL == winusb_handle_); - ATLASSERT(INVALID_HANDLE_VALUE == usb_device_handle_); -} - -ADBAPIHANDLE AdbInterfaceObject::CreateHandle() { - // Open USB device for this inteface Note that WinUsb API - // requires the handle to be opened for overlapped I/O. - usb_device_handle_ = CreateFile(interface_name().c_str(), - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, NULL); - if (INVALID_HANDLE_VALUE == usb_device_handle_) - return NULL; - - // Initialize WinUSB API for this interface - if (!WinUsb_Initialize(usb_device_handle_, &winusb_handle_)) - return NULL; - - // Cache current interface number that will be used in - // WinUsb_Xxx calls performed on this interface. - if (!WinUsb_GetCurrentAlternateSetting(winusb_handle(), &interface_number_)) - return false; - - // Cache interface properties - unsigned long bytes_written; - - // Cache USB device descriptor - if (!WinUsb_GetDescriptor(winusb_handle(), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, - reinterpret_cast(&usb_device_descriptor_), - sizeof(usb_device_descriptor_), &bytes_written)) { - return false; - } - - // Cache USB configuration descriptor - if (!WinUsb_GetDescriptor(winusb_handle(), USB_CONFIGURATION_DESCRIPTOR_TYPE, - 0, 0, - reinterpret_cast(&usb_config_descriptor_), - sizeof(usb_config_descriptor_), &bytes_written)) { - return false; - } - - // Cache USB interface descriptor - if (!WinUsb_QueryInterfaceSettings(winusb_handle(), interface_number(), - &usb_interface_descriptor_)) { - 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 - WINUSB_PIPE_INFORMATION pipe_info; - if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint, - &pipe_info)) { - return false; - } - - if (UsbdPipeTypeBulk == pipe_info.PipeType) { - // This is a bulk endpoint. Cache its index and ID. - if (0 != (pipe_info.PipeId & 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.PipeId; - } else { - // Use this endpoint as default bulk write endpoint - ATLASSERT(0xFF == def_write_endpoint_); - def_write_endpoint_ = endpoint; - write_endpoint_id_ = pipe_info.PipeId; - } - } - } - - return AdbObjectHandle::CreateHandle(); -} - -bool AdbInterfaceObject::CloseHandle() { - if (NULL != winusb_handle_) { - WinUsb_Free(winusb_handle_); - winusb_handle_ = NULL; - } - if (INVALID_HANDLE_VALUE != usb_device_handle_) { - ::CloseHandle(usb_device_handle_); - usb_device_handle_ = INVALID_HANDLE_VALUE; - } - - return AdbObjectHandle::CloseHandle(); } bool AdbInterfaceObject::GetInterfaceName(void* buffer, @@ -163,101 +65,6 @@ bool AdbInterfaceObject::GetInterfaceName(void* buffer, return (res != 0); } -bool AdbInterfaceObject::GetSerialNumber(void* buffer, - unsigned long* buffer_char_size, - bool ansi) { - if (!IsOpened()) { - SetLastError(ERROR_INVALID_HANDLE); - return false; - } - - if (NULL == buffer_char_size) { - SetLastError(ERROR_INVALID_PARAMETER); - return false; - } - - // Calculate serial number string size. Note that WinUsb_GetDescriptor - // API will not return number of bytes needed to store serial number - // string. So we will have to start with a reasonably large preallocated - // buffer and then loop through WinUsb_GetDescriptor calls, doubling up - // string buffer size every time ERROR_INSUFFICIENT_BUFFER is returned. - union { - // Preallocate reasonably sized buffer on the stack. - char small_buffer[64]; - USB_STRING_DESCRIPTOR initial_ser_num; - }; - USB_STRING_DESCRIPTOR* ser_num = &initial_ser_num; - // Buffer byte size - unsigned long ser_num_size = sizeof(small_buffer); - // After successful call to WinUsb_GetDescriptor will contain serial - // number descriptor size. - unsigned long bytes_written; - while (!WinUsb_GetDescriptor(winusb_handle(), USB_STRING_DESCRIPTOR_TYPE, - usb_device_descriptor_.iSerialNumber, - 0x0409, // English (US) - reinterpret_cast(ser_num), - ser_num_size, &bytes_written)) { - // Any error other than ERROR_INSUFFICIENT_BUFFER is terminal here. - if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { - if (ser_num != &initial_ser_num) - delete[] reinterpret_cast(ser_num); - return false; - } - - // Double up buffer size and reallocate string buffer - ser_num_size *= 2; - if (ser_num != &initial_ser_num) - delete[] reinterpret_cast(ser_num); - try { - ser_num = - reinterpret_cast(new char[ser_num_size]); - } catch (...) { - SetLastError(ERROR_OUTOFMEMORY); - return false; - } - } - - // Serial number string length - unsigned long str_len = (ser_num->bLength - - FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)) / - sizeof(wchar_t); - - // Lets see if requested buffer is big enough to fit the string - if ((NULL == buffer) || (*buffer_char_size < (str_len + 1))) { - // Requested buffer is too small. - if (ser_num != &initial_ser_num) - delete[] reinterpret_cast(ser_num); - *buffer_char_size = str_len + 1; - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return false; - } - - bool ret = true; - if (ansi) { - // We need to convert name from wide char to ansi string - if (0 != WideCharToMultiByte(CP_ACP, 0, ser_num->bString, - static_cast(str_len), - reinterpret_cast(buffer), - static_cast(*buffer_char_size), - NULL, NULL)) { - // Zero-terminate output string. - reinterpret_cast(buffer)[str_len] = '\0'; - } else { - ret = false; - } - } else { - // For wide char output just copy string buffer, - // and zero-terminate output string. - CopyMemory(buffer, ser_num->bString, bytes_written); - reinterpret_cast(buffer)[str_len] = L'\0'; - } - - if (ser_num != &initial_ser_num) - delete[] reinterpret_cast(ser_num); - - return ret; -} - bool AdbInterfaceObject::GetUsbDeviceDescriptor(USB_DEVICE_DESCRIPTOR* desc) { if (!IsOpened()) { SetLastError(ERROR_INVALID_HANDLE); @@ -308,106 +115,3 @@ bool AdbInterfaceObject::GetUsbInterfaceDescriptor( return true; } - -bool AdbInterfaceObject::GetEndpointInformation(UCHAR endpoint_index, - AdbEndpointInformation* info) { - if (!IsOpened()) { - SetLastError(ERROR_INVALID_HANDLE); - return false; - } - - if (NULL == info) { - SetLastError(ERROR_INVALID_PARAMETER); - return false; - } - - // Get actual endpoint index for predefined read / write endpoints. - if (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) { - endpoint_index = def_read_endpoint_; - } else if (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) { - endpoint_index = def_write_endpoint_; - } - - // Query endpoint information - WINUSB_PIPE_INFORMATION pipe_info; - if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint_index, - &pipe_info)) { - return false; - } - - // Save endpoint information into output. - info->max_packet_size = pipe_info.MaximumPacketSize; - info->max_transfer_size = 0xFFFFFFFF; - info->endpoint_address = pipe_info.PipeId; - info->polling_interval = pipe_info.Interval; - info->setting_index = interface_number(); - switch (pipe_info.PipeType) { - case UsbdPipeTypeControl: - info->endpoint_type = AdbEndpointTypeControl; - break; - - case UsbdPipeTypeIsochronous: - info->endpoint_type = AdbEndpointTypeIsochronous; - break; - - case UsbdPipeTypeBulk: - info->endpoint_type = AdbEndpointTypeBulk; - break; - - case UsbdPipeTypeInterrupt: - info->endpoint_type = AdbEndpointTypeInterrupt; - break; - - default: - info->endpoint_type = AdbEndpointTypeInvalid; - break; - } - - return true; -} - -ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint( - UCHAR endpoint_index, - AdbOpenAccessType access_type, - AdbOpenSharingMode sharing_mode) { - // Convert index into id - UCHAR endpoint_id; - - if ((ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) || - (def_read_endpoint_ == endpoint_index)) { - 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_id = write_endpoint_id_; - endpoint_index = def_write_endpoint_; - } else { - SetLastError(ERROR_INVALID_PARAMETER); - return false; - } - - return OpenEndpoint(endpoint_id, endpoint_index); -} - -ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint(UCHAR endpoint_id, - UCHAR endpoint_index) { - if (!IsOpened()) { - SetLastError(ERROR_INVALID_HANDLE); - return false; - } - - AdbEndpointObject* adb_endpoint = NULL; - - try { - adb_endpoint = new AdbEndpointObject(this, endpoint_id, endpoint_index); - } catch (...) { - SetLastError(ERROR_OUTOFMEMORY); - return NULL; - } - - ADBAPIHANDLE ret = adb_endpoint->CreateHandle(); - - adb_endpoint->Release(); - - return ret; -} diff --git a/host/windows/usb/api/adb_interface.h b/host/windows/usb/api/adb_interface.h index d428d12af..4afb17da0 100644 --- a/host/windows/usb/api/adb_interface.h +++ b/host/windows/usb/api/adb_interface.h @@ -18,12 +18,15 @@ #define ANDROID_USB_API_ADB_INTERFACE_H__ /** \file This file consists of declaration of class AdbInterfaceObject that - encapsulates an interface on our USB device. + encapsulates a generic interface on our USB device. */ #include "adb_object_handle.h" /** \brief Encapsulates an interface on our USB device. + + This is an abstract class that implements functionality common for both, + legacy, and WinUsb based interfaces. */ class AdbInterfaceObject : public AdbObjectHandle { public: @@ -41,53 +44,11 @@ class AdbInterfaceObject : public AdbObjectHandle { */ virtual ~AdbInterfaceObject(); + // + // Abstract + // + public: - /** \brief Creates handle to this object. - - In this call a handle for this object is generated and object is added - to the AdbObjectHandleMap. We override this method in order to verify that - interface indeed exists and gather device, interface and pipe properties. - If this step succeeds then and only then AdbObjectHandle::CreateHandle - will be called. Note that in this method we will open a handle to the - USB device (saved in usb_device_handle_). The handle will be opened for - read and write access, and for read and write sharing mode. The handle - will be closed in CloseHandle method of this class. - @return A handle to this object on success or NULL on an error. - If NULL is returned GetLastError() provides extended error - information. ERROR_GEN_FAILURE is set if an attempt was - made to create already opened object. - */ - virtual ADBAPIHANDLE CreateHandle(); - - /** \brief This method is called when handle to this object gets closed. - - In this call object is deleted from the AdbObjectHandleMap. We override - this method in order close device and WinUsb handles created in - CreateHandle method of this class. - @return true on success or false if object is already closed. If - false is returned GetLastError() provides extended error - information. - */ - virtual bool CloseHandle(); - - /** \brief Gets interface device name. - - @param[out] buffer Buffer for the name. Can be NULL in which case - buffer_char_size will contain number of characters required to fit - the name. - @param[in,out] buffer_char_size On the way in supplies size (in characters) - of the buffer. On the way out if method failed and GetLastError - reports ERROR_INSUFFICIENT_BUFFER will contain number of characters - required to fit the name. - @param[in] ansi If true the name will be returned as single character - string. Otherwise name will be returned as wide character string. - @return true on success, false on failure. If false is returned - GetLastError() provides extended error information. - */ - bool GetInterfaceName(void* buffer, - unsigned long* buffer_char_size, - bool ansi); - /** \brief Gets serial number for interface's device. @param[out] buffer Buffer for the serail number string. Can be NULL in @@ -102,37 +63,10 @@ class AdbInterfaceObject : public AdbObjectHandle { @return true on success, false on failure. If false is returned GetLastError() provides extended error information. */ - bool GetSerialNumber(void* buffer, - unsigned long* buffer_char_size, - bool ansi); + virtual bool GetSerialNumber(void* buffer, + unsigned long* buffer_char_size, + bool ansi) = 0; - /** \brief Gets device descriptor for the USB device associated with - this interface. - - @param[out] desc Upon successful completion will have usb device - descriptor. - @return true on success, false on failure. If false is returned - GetLastError() provides extended error information. - */ - bool GetUsbDeviceDescriptor(USB_DEVICE_DESCRIPTOR* desc); - - /** \brief Gets descriptor for the selected USB device configuration. - - @param[out] desc Upon successful completion will have usb device - configuration descriptor. - @return true on success, false on failure. If false is returned - GetLastError() provides extended error information. - */ - bool GetUsbConfigurationDescriptor(USB_CONFIGURATION_DESCRIPTOR* desc); - - /** \brief Gets descriptor for this interface. - - @param[out] desc Upon successful completion will have interface - descriptor. - @return true on success, false on failure. If false is returned - GetLastError() provides extended error information. - */ - bool GetUsbInterfaceDescriptor(USB_INTERFACE_DESCRIPTOR* desc); /** \brief Gets information about an endpoint on this interface. @@ -144,8 +78,8 @@ class AdbInterfaceObject : public AdbObjectHandle { @return true on success, false on failure. If false is returned GetLastError() provides extended error information. */ - bool GetEndpointInformation(UCHAR endpoint_index, - AdbEndpointInformation* info); + virtual bool GetEndpointInformation(UCHAR endpoint_index, + AdbEndpointInformation* info) = 0; /** \brief Opens an endpoint on this interface. @@ -163,19 +97,61 @@ class AdbInterfaceObject : public AdbObjectHandle { If NULL is returned GetLastError() provides extended information about the error that occurred. */ - ADBAPIHANDLE OpenEndpoint(UCHAR endpoint_index, - AdbOpenAccessType access_type, - AdbOpenSharingMode sharing_mode); + virtual ADBAPIHANDLE OpenEndpoint(UCHAR endpoint_index, + AdbOpenAccessType access_type, + AdbOpenSharingMode sharing_mode) = 0; - /** \brief Opens an endpoint on this interface. + // + // Operations + // - @param[in] endpoint_id Endpoint (pipe) address on the device. - @param[in] endpoint_index Zero-based endpoint index. - @return Handle to the opened endpoint object or NULL on failure. - If NULL is returned GetLastError() provides extended information - about the error that occurred. + public: + /** \brief Gets interface device name. + + @param[out] buffer Buffer for the name. Can be NULL in which case + buffer_char_size will contain number of characters required to fit + the name. + @param[in,out] buffer_char_size On the way in supplies size (in characters) + of the buffer. On the way out if method failed and GetLastError + reports ERROR_INSUFFICIENT_BUFFER will contain number of characters + required to fit the name. + @param[in] ansi If true the name will be returned as single character + string. Otherwise name will be returned as wide character string. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. */ - ADBAPIHANDLE OpenEndpoint(UCHAR endpoint_id, UCHAR endpoint_index); + virtual bool GetInterfaceName(void* buffer, + unsigned long* buffer_char_size, + bool ansi); + + /** \brief Gets device descriptor for the USB device associated with + this interface. + + @param[out] desc Upon successful completion will have usb device + descriptor. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool GetUsbDeviceDescriptor(USB_DEVICE_DESCRIPTOR* desc); + + /** \brief Gets descriptor for the selected USB device configuration. + + @param[out] desc Upon successful completion will have usb device + configuration descriptor. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool GetUsbConfigurationDescriptor( + USB_CONFIGURATION_DESCRIPTOR* desc); + + /** \brief Gets descriptor for this interface. + + @param[out] desc Upon successful completion will have interface + descriptor. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool GetUsbInterfaceDescriptor(USB_INTERFACE_DESCRIPTOR* desc); public: /// Gets name of the USB interface (device name) for this object @@ -203,22 +179,7 @@ class AdbInterfaceObject : public AdbObjectHandle { return &usb_interface_descriptor_; } - /// Gets handle to the USB device - HANDLE usb_device_handle() const { - return usb_device_handle_; - } - - /// Gets interface handle used by WinUSB API - WINUSB_INTERFACE_HANDLE winusb_handle() const { - return winusb_handle_; - } - - /// Gets current interface number. - UCHAR interface_number() const { - return interface_number_; - } - -private: + protected: /// Name of the USB interface (device name) for this object std::wstring interface_name_; @@ -230,29 +191,6 @@ private: /// Cached usb interface descriptor USB_INTERFACE_DESCRIPTOR usb_interface_descriptor_; - - /// Handle to the USB device - HANDLE usb_device_handle_; - - /// Interface handle used by WinUSB API - WINUSB_INTERFACE_HANDLE winusb_handle_; - - /// Current interface number. This value is obtained via call to - /// WinUsb_GetCurrentAlternateSetting and is used in WinUsb_Xxx - /// calls that require interface number. - UCHAR interface_number_; - - /// Index for the default bulk read endpoint - UCHAR def_read_endpoint_; - - /// ID for the default bulk read endpoint - UCHAR read_endpoint_id_; - - /// Index for the default bulk write endpoint - UCHAR def_write_endpoint_; - - /// ID for the default bulk write endpoint - UCHAR write_endpoint_id_; }; #endif // ANDROID_USB_API_ADB_INTERFACE_H__ diff --git a/host/windows/usb/api/adb_io_completion.cpp b/host/windows/usb/api/adb_io_completion.cpp index 64f97fd7d..6575e0351 100644 --- a/host/windows/usb/api/adb_io_completion.cpp +++ b/host/windows/usb/api/adb_io_completion.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 The Android Open Source Project + * 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. @@ -16,8 +16,8 @@ /** \file This file consists of implementation of class AdbIOCompletion that - encapsulates a wrapper around OVERLAPPED Win32 structure returned - from asynchronous I/O requests. + encapsulates a generic wrapper around OVERLAPPED Win32 structure + returned from asynchronous I/O requests. */ #include "stdafx.h" @@ -39,54 +39,6 @@ AdbIOCompletion::~AdbIOCompletion() { parent_io_object_->Release(); } -bool AdbIOCompletion::GetOvelappedIoResult(LPOVERLAPPED ovl_data, - ULONG* bytes_transferred, - bool wait) { - if (NULL != bytes_transferred) - *bytes_transferred = 0; - - if (!IsOpened()) { - SetLastError(ERROR_INVALID_HANDLE); - return false; - } - - ULONG transfer; - bool ret = WinUsb_GetOverlappedResult(parent_io_object()->winusb_handle(), - overlapped(), - &transfer, - wait ? TRUE : FALSE) ? true : false; - - // TODO: This is bizzare but I've seen it happening - // that GetOverlappedResult with wait set to true returns "prematurely", - // with wrong transferred bytes value and GetLastError reporting - // ERROR_IO_PENDING. So, lets give it an up to a 20 ms loop! - ULONG error = GetLastError(); - - if (wait && ret && (0 == transfer) && (0 != expected_transfer_size_) && - ((ERROR_IO_INCOMPLETE == error) || (ERROR_IO_PENDING == error))) { - for (int trying = 0; trying < 10; trying++) { - Sleep(2); - ret = WinUsb_GetOverlappedResult(parent_io_object()->winusb_handle(), - overlapped(), - &transfer, - wait ? TRUE : FALSE) ? true : false; - error = GetLastError(); - if (!ret || (0 != transfer) || - ((ERROR_IO_INCOMPLETE != error) && (ERROR_IO_PENDING != error))) { - break; - } - } - } - - if (NULL != ovl_data) - CopyMemory(ovl_data, overlapped(), sizeof(OVERLAPPED)); - - if (NULL != bytes_transferred) - *bytes_transferred = transfer; - - return ret; -} - bool AdbIOCompletion::IsCompleted() { SetLastError(NO_ERROR); if (!IsOpened()) { diff --git a/host/windows/usb/api/adb_io_completion.h b/host/windows/usb/api/adb_io_completion.h index 3fea0e89b..8a7c1d91d 100644 --- a/host/windows/usb/api/adb_io_completion.h +++ b/host/windows/usb/api/adb_io_completion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006 The Android Open Source Project + * 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. @@ -18,18 +18,20 @@ #define ANDROID_USB_API_ADB_IO_COMPLETION_H__ /** \file This file consists of declaration of class AdbIOCompletion that encapsulates - a wrapper around OVERLAPPED Win32 structure returned from asynchronous I/O - requests. + a generic wrapper around OVERLAPPED Win32 structure returned from + asynchronous I/O requests. */ #include "adb_endpoint_object.h" -/** \brief Encapsulates encapsulates a wrapper around OVERLAPPED Win32 +/** \brief Encapsulates encapsulates a generic wrapper around OVERLAPPED Win32 structure returned from asynchronous I/O requests. - A handle to this object is returned to the caller of each successful - asynchronous I/O request. Just like all other handles this handle - must be closed after it's no longer needed. + This is an abstract class that implements functionality common for I/O + performed via WinUsb as well as legacy driver APIs. A handle to this object + is returned to the caller of each successful asynchronous I/O request. Just + like all other handles this handle must be closed after it's no longer + needed. */ class AdbIOCompletion : public AdbObjectHandle { public: @@ -56,6 +58,10 @@ class AdbIOCompletion : public AdbObjectHandle { */ virtual ~AdbIOCompletion(); + // + // Abstract + // + public: /** \brief Gets overlapped I/O result @@ -76,8 +82,13 @@ class AdbIOCompletion : public AdbObjectHandle { */ virtual bool GetOvelappedIoResult(LPOVERLAPPED ovl_data, ULONG* bytes_transferred, - bool wait); + bool wait) = 0; + // + // Operations + // + + public: /** \brief Checks if I/O that this object represents has completed. @return true if I/O has been completed or false if it's still diff --git a/host/windows/usb/api/adb_legacy_interface.cpp b/host/windows/usb/api/adb_legacy_interface.cpp new file mode 100755 index 000000000..95c750e69 --- /dev/null +++ b/host/windows/usb/api/adb_legacy_interface.cpp @@ -0,0 +1,64 @@ +/* + * 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 + via WinUsb API. +*/ + +#include "stdafx.h" +#include "adb_legacy_interface.h" +#include "adb_endpoint_object.h" + +AdbLegacyInterfaceObject::AdbLegacyInterfaceObject(const wchar_t* interf_name) + : AdbInterfaceObject(interf_name) { +} + +AdbLegacyInterfaceObject::~AdbLegacyInterfaceObject() { +} + +ADBAPIHANDLE AdbLegacyInterfaceObject::CreateHandle() { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return NULL; +} + +bool AdbLegacyInterfaceObject::CloseHandle() { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; +} + +bool AdbLegacyInterfaceObject::GetSerialNumber(void* buffer, + unsigned long* buffer_char_size, + bool ansi) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; +} + +bool AdbLegacyInterfaceObject::GetEndpointInformation( + UCHAR endpoint_index, + AdbEndpointInformation* info) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return false; +} + +ADBAPIHANDLE AdbLegacyInterfaceObject::OpenEndpoint( + UCHAR endpoint_index, + AdbOpenAccessType access_type, + AdbOpenSharingMode sharing_mode) { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return NULL; +} diff --git a/host/windows/usb/api/adb_legacy_interface.h b/host/windows/usb/api/adb_legacy_interface.h new file mode 100755 index 000000000..6d4b0e840 --- /dev/null +++ b/host/windows/usb/api/adb_legacy_interface.h @@ -0,0 +1,129 @@ +/* + * 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. + */ + +#ifndef ANDROID_USB_API_ADB_LEGACY_INTERFACE_H__ +#define ANDROID_USB_API_ADB_LEGACY_INTERFACE_H__ +/** \file + This file consists of declaration of class AdbLegacyInterfaceObject + that encapsulates an interface on our USB device that is accessible + via custom USB driver. +*/ + +#include "adb_interface.h" + +/** \brief Encapsulates an interface on our USB device that is accessible + via custom USB driver. +*/ +class AdbLegacyInterfaceObject : public AdbInterfaceObject { + public: + /** \brief Constructs the object. + + @param[in] interf_name Name of the interface + */ + explicit AdbLegacyInterfaceObject(const wchar_t* interf_name); + + protected: + /** \brief Destructs the object. + + We hide destructor in order to prevent ourseves from accidentaly allocating + instances on the stack. If such attemp occur, compiler will error. + */ + virtual ~AdbLegacyInterfaceObject(); + + // + // Virtual overrides + // + + public: + /** \brief Creates handle to this object. + + In this call a handle for this object is generated and object is added + to the AdbObjectHandleMap. We override this method in order to initialize + access to the custom driver. + @return A handle to this object on success or NULL on an error. + If NULL is returned GetLastError() provides extended error + information. ERROR_GEN_FAILURE is set if an attempt was + made to create already opened object. + */ + virtual ADBAPIHANDLE CreateHandle(); + + /** \brief This method is called when handle to this object gets closed. + + In this call object is deleted from the AdbObjectHandleMap. + @return true on success or false if object is already closed. If + false is returned GetLastError() provides extended error + information. + */ + virtual bool CloseHandle(); + + // + // Abstract overrides + // + + public: + /** \brief Gets serial number for interface's device. + + @param[out] buffer Buffer for the serail number string. Can be NULL in + which case buffer_char_size will contain number of characters + required for the string. + @param[in,out] buffer_char_size On the way in supplies size (in characters) + of the buffer. On the way out, if method failed and GetLastError + reports ERROR_INSUFFICIENT_BUFFER, will contain number of characters + required for the name. + @param[in] ansi If true the name will be returned as single character + string. Otherwise name will be returned as wide character string. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool GetSerialNumber(void* buffer, + unsigned long* buffer_char_size, + bool ansi); + + /** \brief Gets information about an endpoint on this interface. + + @param[in] endpoint_index Zero-based endpoint index. There are two + shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX + and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide infor about + (default?) bulk write and read endpoints respectively. + @param[out] info Upon successful completion will have endpoint information. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool GetEndpointInformation(UCHAR endpoint_index, + AdbEndpointInformation* info); + + /** \brief Opens an endpoint on this interface. + + @param[in] endpoint_index Zero-based endpoint index. There are two + shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX + and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide infor about + (default?) bulk write and read endpoints respectively. + @param[in] access_type Desired access type. In the current implementation + this parameter has no effect on the way endpoint is opened. It's + always read / write access. + @param[in] sharing_mode Desired share mode. In the current implementation + this parameter has no effect on the way endpoint is opened. It's + always shared for read / write. + @return Handle to the opened endpoint object or NULL on failure. + If NULL is returned GetLastError() provides extended information + about the error that occurred. + */ + virtual ADBAPIHANDLE OpenEndpoint(UCHAR endpoint_index, + AdbOpenAccessType access_type, + AdbOpenSharingMode sharing_mode); +}; + +#endif // ANDROID_USB_API_ADB_LEGACY_INTERFACE_H__ diff --git a/host/windows/usb/api/adb_winusb_endpoint_object.cpp b/host/windows/usb/api/adb_winusb_endpoint_object.cpp new file mode 100755 index 000000000..236de3b49 --- /dev/null +++ b/host/windows/usb/api/adb_winusb_endpoint_object.cpp @@ -0,0 +1,159 @@ +/* + * 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 AdbWinUsbEndpointObject that + encapsulates a handle opened to a WinUsb endpoint on our device. +*/ + +#include "stdafx.h" +#include "adb_winusb_endpoint_object.h" +#include "adb_winusb_io_completion.h" +#include "adb_helper_routines.h" + +AdbWinUsbEndpointObject::AdbWinUsbEndpointObject( + AdbWinUsbInterfaceObject* parent_interf, + UCHAR endpoint_id, + UCHAR endpoint_index) + : AdbEndpointObject(parent_interf, endpoint_id, endpoint_index) { +} + +AdbWinUsbEndpointObject::~AdbWinUsbEndpointObject() { +} + +ADBAPIHANDLE AdbWinUsbEndpointObject::CommonAsyncReadWrite( + bool is_read, + void* buffer, + ULONG bytes_to_transfer, + ULONG* bytes_transferred, + HANDLE event_handle, + ULONG time_out) { + if (!SetTimeout(time_out)) + return false; + + // Create completion i/o object + AdbIOCompletion* adb_io_completion = NULL; + + try { + adb_io_completion = new AdbWinUsbIOCompletion(this, + bytes_to_transfer, + event_handle); + } catch (... ) { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + + // Create a handle for it + ADBAPIHANDLE ret = adb_io_completion->CreateHandle(); + ULONG transferred = 0; + if (NULL != ret) { + BOOL res = TRUE; + // Go the read / write file way + res = is_read ? + WinUsb_ReadPipe(parent_winusb_interface()->winusb_handle(), + endpoint_id(), + reinterpret_cast(buffer), + bytes_to_transfer, + &transferred, + adb_io_completion->overlapped()) : + WinUsb_WritePipe(parent_winusb_interface()->winusb_handle(), + endpoint_id(), + reinterpret_cast(buffer), + bytes_to_transfer, + &transferred, + adb_io_completion->overlapped()); + + if (NULL != bytes_transferred) + *bytes_transferred = transferred; + + ULONG error = GetLastError(); + if (!res && (ERROR_IO_PENDING != error)) { + // I/O failed immediatelly. We need to close i/o completion object + // before we return NULL to the caller. + adb_io_completion->CloseHandle(); + ret = NULL; + SetLastError(error); + } + } + + // Offseting 'new' + adb_io_completion->Release(); + + return ret; +} + +bool AdbWinUsbEndpointObject::CommonSyncReadWrite(bool is_read, + void* buffer, + ULONG bytes_to_transfer, + ULONG* bytes_transferred, + ULONG time_out) { + if (!SetTimeout(time_out)) + return false; + + // This is synchronous I/O. Since we always open I/O items for + // overlapped I/O we're obligated to always provide OVERLAPPED + // structure to read / write routines. Prepare it now. + OVERLAPPED overlapped; + ZeroMemory(&overlapped, sizeof(overlapped)); + overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + BOOL ret = TRUE; + ULONG transferred = 0; + // Go the read / write file way + ret = is_read ? + WinUsb_ReadPipe(parent_winusb_interface()->winusb_handle(), + endpoint_id(), + reinterpret_cast(buffer), + bytes_to_transfer, + &transferred, + &overlapped) : + WinUsb_WritePipe(parent_winusb_interface()->winusb_handle(), + endpoint_id(), + reinterpret_cast(buffer), + bytes_to_transfer, + &transferred, + &overlapped); + + // Lets see the result + if (!ret && (ERROR_IO_PENDING != GetLastError())) { + // I/O failed. + if (NULL != overlapped.hEvent) + ::CloseHandle(overlapped.hEvent); + return false; + } + + // Lets wait till I/O completes + ret = WinUsb_GetOverlappedResult(parent_winusb_interface()->winusb_handle(), &overlapped, + &transferred, TRUE); + if (ret && (NULL != bytes_transferred)) { + *bytes_transferred = transferred; + } + + if (NULL != overlapped.hEvent) + ::CloseHandle(overlapped.hEvent); + + return ret ? true : false; +} + +bool AdbWinUsbEndpointObject::SetTimeout(ULONG timeout) { + if (!WinUsb_SetPipePolicy(parent_winusb_interface()->winusb_handle(), + endpoint_id(), PIPE_TRANSFER_TIMEOUT, + sizeof(ULONG), &timeout)) { + return false; + } + + return true; +} diff --git a/host/windows/usb/api/adb_winusb_endpoint_object.h b/host/windows/usb/api/adb_winusb_endpoint_object.h new file mode 100755 index 000000000..26ef53b16 --- /dev/null +++ b/host/windows/usb/api/adb_winusb_endpoint_object.h @@ -0,0 +1,131 @@ +/* + * 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. + */ + +#ifndef ANDROID_USB_API_ADB_WINUSB_ENDPOINT_OBJECT_H__ +#define ANDROID_USB_API_ADB_WINUSB_ENDPOINT_OBJECT_H__ +/** \file + This file consists of declaration of class AdbWinUsbEndpointObject that + encapsulates a handle opened to a WinUsb endpoint on our device. +*/ + +#include "adb_endpoint_object.h" +#include "adb_winusb_interface.h" + +/** Class AdbWinUsbEndpointObject encapsulates a handle opened to an endpoint on + our device. +*/ +class AdbWinUsbEndpointObject : public AdbEndpointObject { + public: + /** \brief Constructs the object + + @param[in] interface Parent WinUsb interface for this object. + @param[in] endpoint_id Endpoint ID (endpoint address) on the device. + @param[in] endpoint_index Zero-based endpoint index in the interface's + array of endpoints. + */ + AdbWinUsbEndpointObject(AdbWinUsbInterfaceObject* parent_interf, + UCHAR endpoint_id, + UCHAR endpoint_index); + + protected: + /** \brief Destructs the object. + + We hide destructor in order to prevent ourseves from accidentaly allocating + instances on the stack. If such attemp occur, compiler will error. + */ + virtual ~AdbWinUsbEndpointObject(); + + // + // Abstract overrides + // + + protected: + /** \brief Common code for async read / write + + @param[in] is_read Read or write selector. + @param[in,out] buffer Pointer to the buffer for read / write. + @param[in] bytes_to_transfer Number of bytes to be read / written. + @param[out] bytes_transferred Number of bytes read / written. Can be NULL. + @param[in] event_handle Event handle that should be signaled when async I/O + completes. Can be NULL. If it's not NULL this handle will be used to + initialize OVERLAPPED structure for this I/O. + @param[in] time_out A timeout (in milliseconds) required for this I/O to + complete. Zero value in this parameter means that there is no + timeout set for this I/O. + @return A handle to IO completion object or NULL on failure. If NULL is + returned GetLastError() provides extended error information. + */ + virtual ADBAPIHANDLE CommonAsyncReadWrite(bool is_read, + void* buffer, + ULONG bytes_to_transfer, + ULONG* bytes_transferred, + HANDLE event_handle, + ULONG time_out); + + /** \brief Common code for sync read / write + + @param[in] is_read Read or write selector. + @param[in,out] buffer Pointer to the buffer for read / write. + @param[in] bytes_to_transfer Number of bytes to be read / written. + @param[out] bytes_transferred Number of bytes read / written. Can be NULL. + @param[in] time_out A timeout (in milliseconds) required for this I/O to + complete. Zero value in this parameter means that there is no + timeout set for this I/O. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool CommonSyncReadWrite(bool is_read, + void* buffer, + ULONG bytes_to_transfer, + ULONG* bytes_transferred, + ULONG time_out); + + // + // Operations + // + + protected: + /** \brief Sets read / write operation timeout. + + @param[in] timeout Timeout value in milliseconds to use for current read + or write operation. Zero value passed in this parameters indicate + not timeout at all. Note that timeout that is set with this method is + global per endpoint (pipe). I.e. once set, it will be used against + all read / write operations performed on this endpoint, untill + another call to this method modifies it. This is a WinUsb design + flaw. Microsoft is aware of this and (hopefuly) future versions of + WinUsb framework will accept a timeout parameter in WinUsb_Read/Write + routines. For the purposes of ADB this flaw doesn't apperar to be an + issue, since we use single-threaded synchronous read / writes, so + there is no conflict in setting per-endpoint timeouts. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool SetTimeout(ULONG timeout); + + public: + /// Gets parent WinUsb interface + AdbWinUsbInterfaceObject* parent_winusb_interface() const { + return reinterpret_cast(parent_interface()); + } + + /// Gets parent interface WinUsb handle + WINUSB_INTERFACE_HANDLE winusb_handle() const { + return parent_winusb_interface()->winusb_handle(); + } +}; + +#endif // ANDROID_USB_API_ADB_WINUSB_ENDPOINT_OBJECT_H__ diff --git a/host/windows/usb/api/adb_winusb_interface.cpp b/host/windows/usb/api/adb_winusb_interface.cpp new file mode 100755 index 000000000..00e575d36 --- /dev/null +++ b/host/windows/usb/api/adb_winusb_interface.cpp @@ -0,0 +1,329 @@ +/* + * 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 AdbWinUsbInterfaceObject + that encapsulates an interface on our USB device that is accessible + via WinUsb API. +*/ + +#include "stdafx.h" +#include "adb_winusb_interface.h" +#include "adb_winusb_endpoint_object.h" + +AdbWinUsbInterfaceObject::AdbWinUsbInterfaceObject(const wchar_t* interf_name) + : AdbInterfaceObject(interf_name), + usb_device_handle_(INVALID_HANDLE_VALUE), + winusb_handle_(NULL), + interface_number_(0xFF), + def_read_endpoint_(0xFF), + read_endpoint_id_(0xFF), + def_write_endpoint_(0xFF), + write_endpoint_id_(0xFF) { +} + +AdbWinUsbInterfaceObject::~AdbWinUsbInterfaceObject() { + ATLASSERT(NULL == winusb_handle_); + ATLASSERT(INVALID_HANDLE_VALUE == usb_device_handle_); +} + +ADBAPIHANDLE AdbWinUsbInterfaceObject::CreateHandle() { + // Open USB device for this inteface Note that WinUsb API + // requires the handle to be opened for overlapped I/O. + usb_device_handle_ = CreateFile(interface_name().c_str(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, NULL); + if (INVALID_HANDLE_VALUE == usb_device_handle_) + return NULL; + + // Initialize WinUSB API for this interface + if (!WinUsb_Initialize(usb_device_handle_, &winusb_handle_)) + return NULL; + + // Cache current interface number that will be used in + // WinUsb_Xxx calls performed on this interface. + if (!WinUsb_GetCurrentAlternateSetting(winusb_handle(), &interface_number_)) + return false; + + // Cache interface properties + unsigned long bytes_written; + + // Cache USB device descriptor + if (!WinUsb_GetDescriptor(winusb_handle(), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, + reinterpret_cast(&usb_device_descriptor_), + sizeof(usb_device_descriptor_), &bytes_written)) { + return false; + } + + // Cache USB configuration descriptor + if (!WinUsb_GetDescriptor(winusb_handle(), USB_CONFIGURATION_DESCRIPTOR_TYPE, + 0, 0, + reinterpret_cast(&usb_config_descriptor_), + sizeof(usb_config_descriptor_), &bytes_written)) { + return false; + } + + // Cache USB interface descriptor + if (!WinUsb_QueryInterfaceSettings(winusb_handle(), interface_number(), + &usb_interface_descriptor_)) { + 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 + WINUSB_PIPE_INFORMATION pipe_info; + if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint, + &pipe_info)) { + return false; + } + + if (UsbdPipeTypeBulk == pipe_info.PipeType) { + // This is a bulk endpoint. Cache its index and ID. + if (0 != (pipe_info.PipeId & 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.PipeId; + } else { + // Use this endpoint as default bulk write endpoint + ATLASSERT(0xFF == def_write_endpoint_); + def_write_endpoint_ = endpoint; + write_endpoint_id_ = pipe_info.PipeId; + } + } + } + + return AdbInterfaceObject::CreateHandle(); +} + +bool AdbWinUsbInterfaceObject::CloseHandle() { + if (NULL != winusb_handle_) { + WinUsb_Free(winusb_handle_); + winusb_handle_ = NULL; + } + if (INVALID_HANDLE_VALUE != usb_device_handle_) { + ::CloseHandle(usb_device_handle_); + usb_device_handle_ = INVALID_HANDLE_VALUE; + } + + return AdbInterfaceObject::CloseHandle(); +} + +bool AdbWinUsbInterfaceObject::GetSerialNumber(void* buffer, + unsigned long* buffer_char_size, + bool ansi) { + if (!IsOpened()) { + SetLastError(ERROR_INVALID_HANDLE); + return false; + } + + if (NULL == buffer_char_size) { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + + // Calculate serial number string size. Note that WinUsb_GetDescriptor + // API will not return number of bytes needed to store serial number + // string. So we will have to start with a reasonably large preallocated + // buffer and then loop through WinUsb_GetDescriptor calls, doubling up + // string buffer size every time ERROR_INSUFFICIENT_BUFFER is returned. + union { + // Preallocate reasonably sized buffer on the stack. + char small_buffer[64]; + USB_STRING_DESCRIPTOR initial_ser_num; + }; + USB_STRING_DESCRIPTOR* ser_num = &initial_ser_num; + // Buffer byte size + unsigned long ser_num_size = sizeof(small_buffer); + // After successful call to WinUsb_GetDescriptor will contain serial + // number descriptor size. + unsigned long bytes_written; + while (!WinUsb_GetDescriptor(winusb_handle(), USB_STRING_DESCRIPTOR_TYPE, + usb_device_descriptor_.iSerialNumber, + 0x0409, // English (US) + reinterpret_cast(ser_num), + ser_num_size, &bytes_written)) { + // Any error other than ERROR_INSUFFICIENT_BUFFER is terminal here. + if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) { + if (ser_num != &initial_ser_num) + delete[] reinterpret_cast(ser_num); + return false; + } + + // Double up buffer size and reallocate string buffer + ser_num_size *= 2; + if (ser_num != &initial_ser_num) + delete[] reinterpret_cast(ser_num); + try { + ser_num = + reinterpret_cast(new char[ser_num_size]); + } catch (...) { + SetLastError(ERROR_OUTOFMEMORY); + return false; + } + } + + // Serial number string length + unsigned long str_len = (ser_num->bLength - + FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)) / + sizeof(wchar_t); + + // Lets see if requested buffer is big enough to fit the string + if ((NULL == buffer) || (*buffer_char_size < (str_len + 1))) { + // Requested buffer is too small. + if (ser_num != &initial_ser_num) + delete[] reinterpret_cast(ser_num); + *buffer_char_size = str_len + 1; + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return false; + } + + bool ret = true; + if (ansi) { + // We need to convert name from wide char to ansi string + if (0 != WideCharToMultiByte(CP_ACP, 0, ser_num->bString, + static_cast(str_len), + reinterpret_cast(buffer), + static_cast(*buffer_char_size), + NULL, NULL)) { + // Zero-terminate output string. + reinterpret_cast(buffer)[str_len] = '\0'; + } else { + ret = false; + } + } else { + // For wide char output just copy string buffer, + // and zero-terminate output string. + CopyMemory(buffer, ser_num->bString, bytes_written); + reinterpret_cast(buffer)[str_len] = L'\0'; + } + + if (ser_num != &initial_ser_num) + delete[] reinterpret_cast(ser_num); + + return ret; +} + +bool AdbWinUsbInterfaceObject::GetEndpointInformation( + UCHAR endpoint_index, + AdbEndpointInformation* info) { + if (!IsOpened()) { + SetLastError(ERROR_INVALID_HANDLE); + return false; + } + + if (NULL == info) { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + + // Get actual endpoint index for predefined read / write endpoints. + if (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) { + endpoint_index = def_read_endpoint_; + } else if (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) { + endpoint_index = def_write_endpoint_; + } + + // Query endpoint information + WINUSB_PIPE_INFORMATION pipe_info; + if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint_index, + &pipe_info)) { + return false; + } + + // Save endpoint information into output. + info->max_packet_size = pipe_info.MaximumPacketSize; + info->max_transfer_size = 0xFFFFFFFF; + info->endpoint_address = pipe_info.PipeId; + info->polling_interval = pipe_info.Interval; + info->setting_index = interface_number(); + switch (pipe_info.PipeType) { + case UsbdPipeTypeControl: + info->endpoint_type = AdbEndpointTypeControl; + break; + + case UsbdPipeTypeIsochronous: + info->endpoint_type = AdbEndpointTypeIsochronous; + break; + + case UsbdPipeTypeBulk: + info->endpoint_type = AdbEndpointTypeBulk; + break; + + case UsbdPipeTypeInterrupt: + info->endpoint_type = AdbEndpointTypeInterrupt; + break; + + default: + info->endpoint_type = AdbEndpointTypeInvalid; + break; + } + + return true; +} + +ADBAPIHANDLE AdbWinUsbInterfaceObject::OpenEndpoint( + UCHAR endpoint_index, + AdbOpenAccessType access_type, + AdbOpenSharingMode sharing_mode) { + // Convert index into id + UCHAR endpoint_id; + + if ((ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) || + (def_read_endpoint_ == endpoint_index)) { + 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_id = write_endpoint_id_; + endpoint_index = def_write_endpoint_; + } else { + SetLastError(ERROR_INVALID_PARAMETER); + return false; + } + + return OpenEndpoint(endpoint_id, endpoint_index); +} + +ADBAPIHANDLE AdbWinUsbInterfaceObject::OpenEndpoint(UCHAR endpoint_id, + UCHAR endpoint_index) { + if (!IsOpened()) { + SetLastError(ERROR_INVALID_HANDLE); + return false; + } + + AdbEndpointObject* adb_endpoint = NULL; + + try { + adb_endpoint = + new AdbWinUsbEndpointObject(this, endpoint_id, endpoint_index); + } catch (...) { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + + ADBAPIHANDLE ret = adb_endpoint->CreateHandle(); + + adb_endpoint->Release(); + + return ret; +} diff --git a/host/windows/usb/api/adb_winusb_interface.h b/host/windows/usb/api/adb_winusb_interface.h new file mode 100755 index 000000000..82f7f8985 --- /dev/null +++ b/host/windows/usb/api/adb_winusb_interface.h @@ -0,0 +1,186 @@ +/* + * 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. + */ + +#ifndef ANDROID_USB_API_ADB_WINUSB_INTERFACE_H__ +#define ANDROID_USB_API_ADB_WINUSB_INTERFACE_H__ +/** \file + This file consists of declaration of class AdbWinUsbInterfaceObject + that encapsulates an interface on our USB device that is accessible + via WinUsb API. +*/ + +#include "adb_interface.h" + +/** \brief Encapsulates an interface on our USB device that is accessible + via WinUsb API. +*/ +class AdbWinUsbInterfaceObject : public AdbInterfaceObject { + public: + /** \brief Constructs the object. + + @param[in] interf_name Name of the interface + */ + explicit AdbWinUsbInterfaceObject(const wchar_t* interf_name); + + protected: + /** \brief Destructs the object. + + We hide destructor in order to prevent ourseves from accidentaly allocating + instances on the stack. If such attemp occur, compiler will error. + */ + virtual ~AdbWinUsbInterfaceObject(); + + // + // Virtual overrides + // + + public: + /** \brief Creates handle to this object. + + In this call a handle for this object is generated and object is added + to the AdbObjectHandleMap. We override this method in order to initialize + WinUsb API for the given interface. + @return A handle to this object on success or NULL on an error. + If NULL is returned GetLastError() provides extended error + information. ERROR_GEN_FAILURE is set if an attempt was + made to create already opened object. + */ + virtual ADBAPIHANDLE CreateHandle(); + + /** \brief This method is called when handle to this object gets closed. + + In this call object is deleted from the AdbObjectHandleMap. We override + this method in order close WinUsb handle created in CreateHandle method + of this class. + @return true on success or false if object is already closed. If + false is returned GetLastError() provides extended error + information. + */ + virtual bool CloseHandle(); + + // + // Abstract overrides + // + + public: + /** \brief Gets serial number for interface's device. + + @param[out] buffer Buffer for the serail number string. Can be NULL in + which case buffer_char_size will contain number of characters + required for the string. + @param[in,out] buffer_char_size On the way in supplies size (in characters) + of the buffer. On the way out, if method failed and GetLastError + reports ERROR_INSUFFICIENT_BUFFER, will contain number of characters + required for the name. + @param[in] ansi If true the name will be returned as single character + string. Otherwise name will be returned as wide character string. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool GetSerialNumber(void* buffer, + unsigned long* buffer_char_size, + bool ansi); + + /** \brief Gets information about an endpoint on this interface. + + @param[in] endpoint_index Zero-based endpoint index. There are two + shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX + and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide infor about + (default?) bulk write and read endpoints respectively. + @param[out] info Upon successful completion will have endpoint information. + @return true on success, false on failure. If false is returned + GetLastError() provides extended error information. + */ + virtual bool GetEndpointInformation(UCHAR endpoint_index, + AdbEndpointInformation* info); + + /** \brief Opens an endpoint on this interface. + + @param[in] endpoint_index Zero-based endpoint index. There are two + shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX + and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide infor about + (default?) bulk write and read endpoints respectively. + @param[in] access_type Desired access type. In the current implementation + this parameter has no effect on the way endpoint is opened. It's + always read / write access. + @param[in] sharing_mode Desired share mode. In the current implementation + this parameter has no effect on the way endpoint is opened. It's + always shared for read / write. + @return Handle to the opened endpoint object or NULL on failure. + If NULL is returned GetLastError() provides extended information + about the error that occurred. + */ + virtual ADBAPIHANDLE OpenEndpoint(UCHAR endpoint_index, + AdbOpenAccessType access_type, + AdbOpenSharingMode sharing_mode); + + // + // Operations + // + + protected: + /** \brief Opens an endpoint on this interface. + + @param[in] endpoint_id Endpoint (pipe) address on the device. + @param[in] endpoint_index Zero-based endpoint index. + @return Handle to the opened endpoint object or NULL on failure. + If NULL is returned GetLastError() provides extended information + about the error that occurred. + */ + ADBAPIHANDLE OpenEndpoint(UCHAR endpoint_id, UCHAR endpoint_index); + + public: + /// Gets handle to the USB device + HANDLE usb_device_handle() const { + return usb_device_handle_; + } + + /// Gets interface handle used by WinUSB API + WINUSB_INTERFACE_HANDLE winusb_handle() const { + return winusb_handle_; + } + + /// Gets current interface number. + UCHAR interface_number() const { + return interface_number_; + } + + protected: + /// Handle to the USB device + HANDLE usb_device_handle_; + + /// Interface handle used by WinUSB API + WINUSB_INTERFACE_HANDLE winusb_handle_; + + /// Current interface number. This value is obtained via call to + /// WinUsb_GetCurrentAlternateSetting and is used in WinUsb_Xxx + /// calls that require interface number. + UCHAR interface_number_; + + /// Index for the default bulk read endpoint + UCHAR def_read_endpoint_; + + /// ID for the default bulk read endpoint + UCHAR read_endpoint_id_; + + /// Index for the default bulk write endpoint + UCHAR def_write_endpoint_; + + /// ID for the default bulk write endpoint + UCHAR write_endpoint_id_; +}; + +#endif // ANDROID_USB_API_ADB_WINUSB_INTERFACE_H__ diff --git a/host/windows/usb/api/adb_winusb_io_completion.cpp b/host/windows/usb/api/adb_winusb_io_completion.cpp new file mode 100755 index 000000000..baeb7bbb8 --- /dev/null +++ b/host/windows/usb/api/adb_winusb_io_completion.cpp @@ -0,0 +1,87 @@ +/* + * 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 AdbWinUsbIOCompletion that + encapsulates a wrapper around OVERLAPPED Win32 structure returned from + asynchronous I/O requests issued via WinUsb API. +*/ + +#include "stdafx.h" +#include "adb_winusb_io_completion.h" + +AdbWinUsbIOCompletion::AdbWinUsbIOCompletion( + AdbWinUsbEndpointObject* parent_io_obj, + ULONG expected_trans_size, + HANDLE event_hndl) + : AdbIOCompletion(parent_io_obj, expected_trans_size, event_hndl) { +} + +AdbWinUsbIOCompletion::~AdbWinUsbIOCompletion() { +} + +bool AdbWinUsbIOCompletion::GetOvelappedIoResult(LPOVERLAPPED ovl_data, + ULONG* bytes_transferred, + bool wait) { + if (NULL != bytes_transferred) { + *bytes_transferred = 0; + } + + if (!IsOpened()) { + SetLastError(ERROR_INVALID_HANDLE); + return false; + } + + ULONG transfer; + bool ret = WinUsb_GetOverlappedResult( + parent_winusb_io_object()->winusb_handle(), + overlapped(), + &transfer, + wait ? TRUE : FALSE) ? true : false; + + // TODO: This is bizzare but I've seen it happening + // that GetOverlappedResult with wait set to true returns "prematurely", + // with wrong transferred bytes value and GetLastError reporting + // ERROR_IO_PENDING. So, lets give it an up to a 20 ms loop! + ULONG error = GetLastError(); + + if (wait && ret && (0 == transfer) && (0 != expected_transfer_size_) && + ((ERROR_IO_INCOMPLETE == error) || (ERROR_IO_PENDING == error))) { + for (int trying = 0; trying < 10; trying++) { + Sleep(2); + ret = WinUsb_GetOverlappedResult( + parent_winusb_io_object()->winusb_handle(), + overlapped(), + &transfer, + wait ? TRUE : FALSE) ? true : false; + error = GetLastError(); + if (!ret || (0 != transfer) || + ((ERROR_IO_INCOMPLETE != error) && (ERROR_IO_PENDING != error))) { + break; + } + } + } + + if (NULL != ovl_data) { + CopyMemory(ovl_data, overlapped(), sizeof(OVERLAPPED)); + } + + if (NULL != bytes_transferred) { + *bytes_transferred = transfer; + } + + return ret; +} diff --git a/host/windows/usb/api/adb_winusb_io_completion.h b/host/windows/usb/api/adb_winusb_io_completion.h new file mode 100755 index 000000000..a97a3a8b2 --- /dev/null +++ b/host/windows/usb/api/adb_winusb_io_completion.h @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#ifndef ANDROID_USB_API_ADB_WINUSB_IO_COMPLETION_H__ +#define ANDROID_USB_API_ADB_WINUSB_IO_COMPLETION_H__ +/** \file + This file consists of declaration of class AdbWinUsbIOCompletion that + encapsulates a wrapper around OVERLAPPED Win32 structure returned from + asynchronous I/O requests issued via WinUsb API. +*/ + +#include "adb_io_completion.h" +#include "adb_winusb_endpoint_object.h" + +/** \brief Encapsulates encapsulates a wrapper around OVERLAPPED Win32 + structure returned from asynchronous I/O requests issued via WinUsb API. + + A handle to this object is returned to the caller of each successful + asynchronous I/O request. Just like all other handles this handle + must be closed after it's no longer needed. +*/ +class AdbWinUsbIOCompletion : public AdbIOCompletion { + public: + /** \brief Constructs the object + + @param[in] parent_io_obj Parent WinUsb I/O object that created this + instance. + @param[in] expected_trans_size Number of bytes expected to be transferred + with the I/O. + @param[in] event_hndl Event handle that should be signaled when I/O + completes. Can be NULL. If it's not NULL this handle will be + used to initialize OVERLAPPED structure for this object. + */ + AdbWinUsbIOCompletion(AdbWinUsbEndpointObject* parent_io_obj, + ULONG expected_trans_size, + HANDLE event_hndl); + + protected: + /** \brief Destructs the object. + + We hide destructor in order to prevent ourseves from accidentaly allocating + instances on the stack. If such attemp occur, compiler will error. + */ + virtual ~AdbWinUsbIOCompletion(); + + // + // Abstract overrides + // + + public: + /** \brief Gets overlapped I/O result + + This method uses WinUsb_GetOverlappedResult to get results of the + overlapped I/O operation. + @param[out] ovl_data Buffer for the copy of this object's OVERLAPPED + structure. Can be NULL. + @param[out] bytes_transferred Pointer to a variable that receives the + number of bytes that were actually transferred by a read or write + operation. See SDK doc on GetOvelappedResult for more information. + Unlike regular GetOvelappedResult call this parameter can be NULL. + @param[in] wait If this parameter is true, the method does not return + until the operation has been completed. If this parameter is false + and the operation is still pending, the method returns false and + the GetLastError function returns ERROR_IO_INCOMPLETE. + @return true if I/O has been completed or false on failure or if request + is not yet completed. If false is returned GetLastError() provides + extended error information. If GetLastError returns + ERROR_IO_INCOMPLETE it means that I/O is not yet completed. + */ + virtual bool GetOvelappedIoResult(LPOVERLAPPED ovl_data, + ULONG* bytes_transferred, + bool wait); + + public: + /// Gets WinUsb parent object + AdbWinUsbEndpointObject* parent_winusb_io_object() const { + return reinterpret_cast(parent_io_object()); + } +}; + +#endif // ANDROID_USB_API_ADB_WINUSB_IO_COMPLETION_H__