Merge change 8516 into donut
* changes: Refactor API classes to support both, WinUsb and Legacy API
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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"
|
||||
|
||||
190
host/windows/usb/api/adb_api_legacy.h
Executable file
190
host/windows/usb/api/adb_api_legacy.h
Executable file
@@ -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_
|
||||
@@ -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<PUCHAR>(buffer),
|
||||
bytes_to_transfer,
|
||||
&transferred,
|
||||
adb_io_completion->overlapped()) :
|
||||
WinUsb_WritePipe(parent_interface()->winusb_handle(),
|
||||
endpoint_id(),
|
||||
reinterpret_cast<PUCHAR>(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<PUCHAR>(buffer),
|
||||
bytes_to_transfer,
|
||||
&transferred,
|
||||
&overlapped) :
|
||||
WinUsb_WritePipe(parent_interface()->winusb_handle(),
|
||||
endpoint_id(),
|
||||
reinterpret_cast<PUCHAR>(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;
|
||||
}
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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<PUCHAR>(&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<PUCHAR>(&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<PUCHAR>(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<char*>(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<char*>(ser_num);
|
||||
try {
|
||||
ser_num =
|
||||
reinterpret_cast<USB_STRING_DESCRIPTOR*>(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<char*>(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<int>(str_len),
|
||||
reinterpret_cast<PSTR>(buffer),
|
||||
static_cast<int>(*buffer_char_size),
|
||||
NULL, NULL)) {
|
||||
// Zero-terminate output string.
|
||||
reinterpret_cast<char*>(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<wchar_t*>(buffer)[str_len] = L'\0';
|
||||
}
|
||||
|
||||
if (ser_num != &initial_ser_num)
|
||||
delete[] reinterpret_cast<char*>(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;
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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
|
||||
|
||||
64
host/windows/usb/api/adb_legacy_interface.cpp
Executable file
64
host/windows/usb/api/adb_legacy_interface.cpp
Executable file
@@ -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;
|
||||
}
|
||||
129
host/windows/usb/api/adb_legacy_interface.h
Executable file
129
host/windows/usb/api/adb_legacy_interface.h
Executable file
@@ -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__
|
||||
159
host/windows/usb/api/adb_winusb_endpoint_object.cpp
Executable file
159
host/windows/usb/api/adb_winusb_endpoint_object.cpp
Executable file
@@ -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<PUCHAR>(buffer),
|
||||
bytes_to_transfer,
|
||||
&transferred,
|
||||
adb_io_completion->overlapped()) :
|
||||
WinUsb_WritePipe(parent_winusb_interface()->winusb_handle(),
|
||||
endpoint_id(),
|
||||
reinterpret_cast<PUCHAR>(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<PUCHAR>(buffer),
|
||||
bytes_to_transfer,
|
||||
&transferred,
|
||||
&overlapped) :
|
||||
WinUsb_WritePipe(parent_winusb_interface()->winusb_handle(),
|
||||
endpoint_id(),
|
||||
reinterpret_cast<PUCHAR>(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;
|
||||
}
|
||||
131
host/windows/usb/api/adb_winusb_endpoint_object.h
Executable file
131
host/windows/usb/api/adb_winusb_endpoint_object.h
Executable file
@@ -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<AdbWinUsbInterfaceObject*>(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__
|
||||
329
host/windows/usb/api/adb_winusb_interface.cpp
Executable file
329
host/windows/usb/api/adb_winusb_interface.cpp
Executable file
@@ -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<PUCHAR>(&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<PUCHAR>(&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<PUCHAR>(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<char*>(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<char*>(ser_num);
|
||||
try {
|
||||
ser_num =
|
||||
reinterpret_cast<USB_STRING_DESCRIPTOR*>(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<char*>(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<int>(str_len),
|
||||
reinterpret_cast<PSTR>(buffer),
|
||||
static_cast<int>(*buffer_char_size),
|
||||
NULL, NULL)) {
|
||||
// Zero-terminate output string.
|
||||
reinterpret_cast<char*>(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<wchar_t*>(buffer)[str_len] = L'\0';
|
||||
}
|
||||
|
||||
if (ser_num != &initial_ser_num)
|
||||
delete[] reinterpret_cast<char*>(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;
|
||||
}
|
||||
186
host/windows/usb/api/adb_winusb_interface.h
Executable file
186
host/windows/usb/api/adb_winusb_interface.h
Executable file
@@ -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__
|
||||
87
host/windows/usb/api/adb_winusb_io_completion.cpp
Executable file
87
host/windows/usb/api/adb_winusb_io_completion.cpp
Executable file
@@ -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;
|
||||
}
|
||||
94
host/windows/usb/api/adb_winusb_io_completion.h
Executable file
94
host/windows/usb/api/adb_winusb_io_completion.h
Executable file
@@ -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<AdbWinUsbEndpointObject*>(parent_io_object());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ANDROID_USB_API_ADB_WINUSB_IO_COMPLETION_H__
|
||||
Reference in New Issue
Block a user