Add classes encapsulatinglegacy USB API
Added implementation for endpoints and overlapped I/O support for legacy API support.
diff --git a/host/windows/usb/api/SOURCES b/host/windows/usb/api/SOURCES
index 4b9d360..f6e6614 100755
--- a/host/windows/usb/api/SOURCES
+++ b/host/windows/usb/api/SOURCES
@@ -88,6 +88,7 @@
SOURCES = adb_api.cpp \
adb_endpoint_object.cpp \
adb_winusb_endpoint_object.cpp \
+ adb_legacy_endpoint_object.cpp \
adb_helper_routines.cpp \
adb_interface.cpp \
adb_winusb_interface.cpp \
@@ -95,6 +96,7 @@
adb_interface_enum.cpp \
adb_io_completion.cpp \
adb_winusb_io_completion.cpp \
+ adb_legacy_io_completion.cpp \
adb_object_handle.cpp \
AdbWinApi.cpp \
AdbWinApi.rc
diff --git a/host/windows/usb/api/adb_helper_routines.cpp b/host/windows/usb/api/adb_helper_routines.cpp
index 9e37380..e45ff91 100644
--- a/host/windows/usb/api/adb_helper_routines.cpp
+++ b/host/windows/usb/api/adb_helper_routines.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 The Android Open Source Project
+ * Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,6 +25,61 @@
#include "adb_helper_routines.h"
#include "adb_interface_enum.h"
+bool GetSDKComplientParam(AdbOpenAccessType access_type,
+ AdbOpenSharingMode sharing_mode,
+ ULONG* desired_access,
+ ULONG* desired_sharing) {
+ if (NULL != desired_access) {
+ switch (access_type) {
+ case AdbOpenAccessTypeReadWrite:
+ *desired_access = GENERIC_READ | GENERIC_WRITE;
+ break;
+
+ case AdbOpenAccessTypeRead:
+ *desired_access = GENERIC_READ;
+ break;
+
+ case AdbOpenAccessTypeWrite:
+ *desired_access = GENERIC_WRITE;
+ break;
+
+ case AdbOpenAccessTypeQueryInfo:
+ *desired_access = FILE_READ_ATTRIBUTES | FILE_READ_EA;
+ break;
+
+ default:
+ SetLastError(ERROR_INVALID_ACCESS);
+ return false;
+ }
+ }
+
+ if (NULL != desired_sharing) {
+ switch (sharing_mode) {
+ case AdbOpenSharingModeReadWrite:
+ *desired_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ break;
+
+ case AdbOpenSharingModeRead:
+ *desired_sharing = FILE_SHARE_READ;
+ break;
+
+ case AdbOpenSharingModeWrite:
+ *desired_sharing = FILE_SHARE_WRITE;
+ break;
+
+ case AdbOpenSharingModeExclusive:
+ *desired_sharing = 0;
+ break;
+
+ default:
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info,
GUID class_id,
bool exclude_removed,
diff --git a/host/windows/usb/api/adb_helper_routines.h b/host/windows/usb/api/adb_helper_routines.h
index 907e638..b6885e4 100644
--- a/host/windows/usb/api/adb_helper_routines.h
+++ b/host/windows/usb/api/adb_helper_routines.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.
@@ -23,6 +23,23 @@
#include "adb_api_private_defines.h"
+/** \brief Converts access type and share mode from our enum into
+ SDK - complient values.
+
+ @param[in] access_type Enumerated access type
+ @param[in] sharing_mode Enumerated share mode
+ @param[out] desired_access Will receive SDK - complient desired access
+ flags. This parameter can be NULL.
+ @param[out] desired_sharing Will receive SDK - complient share mode.
+ This parameter can be NULL.
+ @return True on success, false on failure, in which case GetLastError()
+ provides extended information about the error that occurred.
+*/
+bool GetSDKComplientParam(AdbOpenAccessType access_type,
+ AdbOpenSharingMode sharing_mode,
+ ULONG* desired_access,
+ ULONG* desired_sharing);
+
/** \brief Given the hardware device information enumerates interfaces for
this device.
diff --git a/host/windows/usb/api/adb_legacy_endpoint_object.cpp b/host/windows/usb/api/adb_legacy_endpoint_object.cpp
new file mode 100755
index 0000000..2baa53b
--- /dev/null
+++ b/host/windows/usb/api/adb_legacy_endpoint_object.cpp
@@ -0,0 +1,237 @@
+/*
+ * 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 AdbLegacyEndpointObject that
+ encapsulates a handle opened to an endpoint on our device controlled by
+ a custom (legacy) USB driver.
+*/
+
+#include "stdafx.h"
+#include "adb_api_legacy.h"
+#include "adb_legacy_endpoint_object.h"
+#include "adb_legacy_io_completion.h"
+#include "adb_helper_routines.h"
+
+AdbLegacyEndpointObject::AdbLegacyEndpointObject(
+ AdbLegacyInterfaceObject* parent_interf,
+ UCHAR endpoint_id,
+ UCHAR endpoint_index)
+ : AdbEndpointObject(parent_interf, endpoint_id, endpoint_index),
+ usb_handle_(INVALID_HANDLE_VALUE) {
+}
+
+AdbLegacyEndpointObject::~AdbLegacyEndpointObject() {
+ if (INVALID_HANDLE_VALUE != usb_handle_) {
+ ::CloseHandle(usb_handle_);
+ }
+}
+
+ADBAPIHANDLE AdbLegacyEndpointObject::CommonAsyncReadWrite(
+ bool is_read,
+ void* buffer,
+ ULONG bytes_to_transfer,
+ ULONG* bytes_transferred,
+ HANDLE event_handle,
+ ULONG time_out) {
+ if (NULL != bytes_transferred) {
+ *bytes_transferred = 0;
+ }
+
+ if (!IsOpened()) {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return false;
+ }
+
+ bool is_ioctl_write = is_read ? false : (0 != time_out);
+
+ // Create completion i/o object
+ AdbLegacyIOCompletion* adb_io_completion = NULL;
+
+ try {
+ adb_io_completion = new AdbLegacyIOCompletion(this,
+ bytes_to_transfer,
+ event_handle,
+ is_ioctl_write);
+ } catch (... ) {
+ // We don't expect exceptions other than OOM thrown here.
+ 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;
+ if (0 == time_out) {
+ // Go the read / write file way
+ res = is_read ? ReadFile(usb_handle(),
+ buffer,
+ bytes_to_transfer,
+ &transferred,
+ adb_io_completion->overlapped()) :
+ WriteFile(usb_handle(),
+ buffer,
+ bytes_to_transfer,
+ &transferred,
+ adb_io_completion->overlapped());
+ } else {
+ // Go IOCTL way
+ AdbBulkTransfer transfer_param;
+ transfer_param.time_out = time_out;
+ transfer_param.transfer_size = is_read ? 0 : bytes_to_transfer;
+ transfer_param.SetWriteBuffer(is_read ? NULL : buffer);
+
+ res = DeviceIoControl(usb_handle(),
+ is_read ? ADB_IOCTL_BULK_READ : ADB_IOCTL_BULK_WRITE,
+ &transfer_param, sizeof(transfer_param),
+ is_read ? buffer : adb_io_completion->transferred_bytes_ptr(),
+ is_read ? bytes_to_transfer : sizeof(ULONG),
+ &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 AdbLegacyEndpointObject::CommonSyncReadWrite(bool is_read,
+ void* buffer,
+ ULONG bytes_to_transfer,
+ ULONG* bytes_transferred,
+ ULONG time_out) {
+ if (NULL != bytes_transferred) {
+ *bytes_transferred = 0;
+ }
+
+ if (!IsOpened()) {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return false;
+ }
+
+ bool is_ioctl_write = is_read ? false : (0 != time_out);
+
+ // 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));
+
+ BOOL ret = TRUE;
+ ULONG ioctl_write_transferred = 0;
+ if (0 == time_out) {
+ // Go the read / write file way
+ ret = is_read ?
+ ReadFile(usb_handle(), buffer, bytes_to_transfer, bytes_transferred, &overlapped) :
+ WriteFile(usb_handle(), buffer, bytes_to_transfer, bytes_transferred, &overlapped);
+ } else {
+ // Go IOCTL way
+ AdbBulkTransfer transfer_param;
+ transfer_param.time_out = time_out;
+ transfer_param.transfer_size = is_read ? 0 : bytes_to_transfer;
+ transfer_param.SetWriteBuffer(is_read ? NULL : buffer);
+
+ ULONG tmp;
+ ret = DeviceIoControl(usb_handle(),
+ is_read ? ADB_IOCTL_BULK_READ : ADB_IOCTL_BULK_WRITE,
+ &transfer_param, sizeof(transfer_param),
+ is_read ? buffer : &ioctl_write_transferred,
+ is_read ? bytes_to_transfer : sizeof(ULONG),
+ &tmp,
+ &overlapped);
+ }
+
+ // Lets see the result
+ if (!ret && (ERROR_IO_PENDING != GetLastError())) {
+ // I/O failed.
+ return false;
+ }
+
+ // Lets wait till I/O completes
+ ULONG transferred = 0;
+ ret = GetOverlappedResult(usb_handle(), &overlapped, &transferred, TRUE);
+ if (ret && (NULL != bytes_transferred)) {
+ *bytes_transferred = is_ioctl_write ? ioctl_write_transferred :
+ transferred;
+ }
+
+ return ret ? true : false;
+}
+
+ADBAPIHANDLE AdbLegacyEndpointObject::CreateHandle(
+ const wchar_t* item_path,
+ AdbOpenAccessType access_type,
+ AdbOpenSharingMode share_mode) {
+ // Convert access / share parameters into CreateFile - compatible
+ ULONG desired_access;
+ ULONG desired_sharing;
+
+ if (!GetSDKComplientParam(access_type, share_mode,
+ &desired_access, &desired_sharing)) {
+ return NULL;
+ }
+
+ // Open USB handle
+ usb_handle_ = CreateFile(item_path,
+ desired_access,
+ share_mode,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED, // Always overlapped!
+ NULL);
+ if (INVALID_HANDLE_VALUE == usb_handle_) {
+ return NULL;
+ }
+
+ // Create ADB handle
+ ADBAPIHANDLE ret = AdbObjectHandle::CreateHandle();
+
+ if (NULL == ret) {
+ // If creation of ADB handle failed we have to close USB handle too.
+ ULONG error = GetLastError();
+ ::CloseHandle(usb_handle());
+ usb_handle_ = INVALID_HANDLE_VALUE;
+ SetLastError(error);
+ }
+
+ return ret;
+}
+
+bool AdbLegacyEndpointObject::CloseHandle() {
+ if (INVALID_HANDLE_VALUE != usb_handle_) {
+ ::CloseHandle(usb_handle_);
+ usb_handle_ = INVALID_HANDLE_VALUE;
+ }
+
+ return AdbEndpointObject::CloseHandle();
+}
diff --git a/host/windows/usb/api/adb_legacy_endpoint_object.h b/host/windows/usb/api/adb_legacy_endpoint_object.h
new file mode 100755
index 0000000..a8613d2
--- /dev/null
+++ b/host/windows/usb/api/adb_legacy_endpoint_object.h
@@ -0,0 +1,142 @@
+/*
+ * 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_ENDPOINT_OBJECT_H__
+#define ANDROID_USB_API_ADB_LEGACY_ENDPOINT_OBJECT_H__
+/** \file
+ This file consists of declaration of class AdbLegacyEndpointObject that
+ encapsulates a handle opened to an endpoint on our device controlled by
+ a custom (legacy) USB driver.
+*/
+
+#include "adb_endpoint_object.h"
+#include "adb_legacy_interface.h"
+
+/** Encapsulates a handle opened to an endpoint on our device controlled by
+ a custom (legacy) USB driver.
+*/
+class AdbLegacyEndpointObject : public AdbEndpointObject {
+ public:
+ /** \brief Constructs the object
+
+ @param[in] interface Parent legacy USB 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.
+ */
+ AdbLegacyEndpointObject(AdbLegacyInterfaceObject* 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 ~AdbLegacyEndpointObject();
+
+ //
+ // 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
+ //
+
+ public:
+ /** \brief Opens endpoint and creates a handle to this object
+
+ @param item_path[in] Path to the endpoint on our USB device.
+ @param access_type[in] Desired access type. In the current implementation
+ this parameter has no effect on the way item is opened. It's
+ always read / write access.
+ @param sharing_mode[in] Desired share mode. In the current implementation
+ this parameter has no effect on the way item is opened. It's
+ always shared for read / write.
+ @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(const wchar_t* item_path,
+ AdbOpenAccessType access_type,
+ AdbOpenSharingMode share_mode);
+
+
+ /** \brief This method is called when handle to this object gets closed.
+
+ We override this method in order to close handle to the endpoint opened
+ 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();
+
+ public:
+ /// Gets handle to the endpoint opened on our USB device.
+ HANDLE usb_handle() const {
+ return usb_handle_;
+ }
+
+ protected:
+ /// Handle to the endpoint opened on our USB device.
+ HANDLE usb_handle_;
+};
+
+#endif // ANDROID_USB_API_ADB_LEGACY_ENDPOINT_OBJECT_H__
diff --git a/host/windows/usb/api/adb_legacy_interface.cpp b/host/windows/usb/api/adb_legacy_interface.cpp
index 95c750e..9eab9bd 100755
--- a/host/windows/usb/api/adb_legacy_interface.cpp
+++ b/host/windows/usb/api/adb_legacy_interface.cpp
@@ -17,48 +17,308 @@
/** \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_api_legacy.h"
#include "adb_legacy_interface.h"
-#include "adb_endpoint_object.h"
+#include "adb_legacy_endpoint_object.h"
AdbLegacyInterfaceObject::AdbLegacyInterfaceObject(const wchar_t* interf_name)
- : AdbInterfaceObject(interf_name) {
+ : AdbInterfaceObject(interf_name),
+ def_read_endpoint_(0xFF),
+ read_endpoint_id_(0xFF),
+ def_write_endpoint_(0xFF),
+ write_endpoint_id_(0xFF) {
}
AdbLegacyInterfaceObject::~AdbLegacyInterfaceObject() {
}
ADBAPIHANDLE AdbLegacyInterfaceObject::CreateHandle() {
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return NULL;
-}
+ // Open USB device for this intefface
+ HANDLE usb_device_handle = CreateFile(interface_name().c_str(),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ if (INVALID_HANDLE_VALUE == usb_device_handle) {
+ return NULL;
+ }
-bool AdbLegacyInterfaceObject::CloseHandle() {
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return false;
+ // Now, we ensured that our usb device / interface is up and running.
+ // Lets collect device, interface and pipe information
+ bool ok = true;
+ if (!CacheUsbDeviceDescriptor(usb_device_handle) ||
+ !CacheUsbConfigurationDescriptor(usb_device_handle) ||
+ !CacheUsbInterfaceDescriptor(usb_device_handle)) {
+ ok = false;
+ }
+
+ // Preserve error accross handle close
+ ULONG error = ok ? NO_ERROR : GetLastError();
+
+ ::CloseHandle(usb_device_handle);
+
+ if (NO_ERROR != error) {
+ SetLastError(error);
+ }
+
+ if (!ok) {
+ return false;
+ }
+
+ // Save indexes and IDs for bulk read / write endpoints. We will use them to
+ // convert ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX and
+ // ADB_QUERY_BULK_READ_ENDPOINT_INDEX into actual endpoint indexes and IDs.
+ for (UCHAR endpoint = 0; endpoint < usb_interface_descriptor_.bNumEndpoints;
+ endpoint++) {
+ // Get endpoint information
+ AdbEndpointInformation pipe_info;
+ if (!GetEndpointInformation(endpoint, &pipe_info)) {
+ return false;
+ }
+
+ if (AdbEndpointTypeBulk == pipe_info.endpoint_type) {
+ // This is a bulk endpoint. Cache its index and ID.
+ if (0 != (pipe_info.endpoint_address & USB_ENDPOINT_DIRECTION_MASK)) {
+ // Use this endpoint as default bulk read endpoint
+ ATLASSERT(0xFF == def_read_endpoint_);
+ def_read_endpoint_ = endpoint;
+ read_endpoint_id_ = pipe_info.endpoint_address;
+ } else {
+ // Use this endpoint as default bulk write endpoint
+ ATLASSERT(0xFF == def_write_endpoint_);
+ def_write_endpoint_ = endpoint;
+ write_endpoint_id_ = pipe_info.endpoint_address;
+ }
+ }
+ }
+
+ return AdbObjectHandle::CreateHandle();
}
bool AdbLegacyInterfaceObject::GetSerialNumber(void* buffer,
unsigned long* buffer_char_size,
bool ansi) {
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return false;
+ if (!IsOpened()) {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return false;
+ }
+
+ // Open USB device for this intefface
+ HANDLE usb_device_handle = CreateFile(interface_name().c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ if (INVALID_HANDLE_VALUE == usb_device_handle) {
+ return NULL;
+ }
+
+ WCHAR serial_number[512];
+
+ // Send IOCTL
+ DWORD ret_bytes = 0;
+ BOOL ret = DeviceIoControl(usb_device_handle,
+ ADB_IOCTL_GET_SERIAL_NUMBER,
+ NULL, 0,
+ serial_number, sizeof(serial_number),
+ &ret_bytes,
+ NULL);
+
+ // Preserve error accross CloseHandle
+ ULONG error = ret ? NO_ERROR : GetLastError();
+
+ ::CloseHandle(usb_device_handle);
+
+ if (NO_ERROR != error) {
+ SetLastError(error);
+ return false;
+ }
+
+ unsigned long str_len =
+ static_cast<unsigned long>(wcslen(serial_number) + 1);
+
+ if ((NULL == buffer) || (*buffer_char_size < str_len)) {
+ *buffer_char_size = str_len;
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return false;
+ }
+
+ if (!ansi) {
+ // If user asked for wide char name just return it
+ wcscpy(reinterpret_cast<wchar_t*>(buffer), serial_number);
+ return true;
+ }
+
+ // We need to convert name from wide char to ansi string
+ int res = WideCharToMultiByte(CP_ACP,
+ 0,
+ serial_number,
+ static_cast<int>(str_len),
+ reinterpret_cast<PSTR>(buffer),
+ static_cast<int>(*buffer_char_size),
+ NULL,
+ NULL);
+ return (res != 0);
}
bool AdbLegacyInterfaceObject::GetEndpointInformation(
UCHAR endpoint_index,
AdbEndpointInformation* info) {
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return false;
+ // Open USB device for this intefface
+ HANDLE usb_device_handle = CreateFile(interface_name().c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ NULL);
+ if (INVALID_HANDLE_VALUE == usb_device_handle) {
+ return NULL;
+ }
+
+ // Init ICTL param
+ AdbQueryEndpointInformation param;
+ param.endpoint_index = endpoint_index;
+
+ // Send IOCTL
+ DWORD ret_bytes = 0;
+ BOOL ret = DeviceIoControl(usb_device_handle,
+ ADB_IOCTL_GET_ENDPOINT_INFORMATION,
+ ¶m, sizeof(param),
+ info, sizeof(AdbEndpointInformation),
+ &ret_bytes,
+ NULL);
+ ATLASSERT(!ret || (sizeof(AdbEndpointInformation) == ret_bytes));
+
+ // Preserve error accross CloseHandle
+ ULONG error = ret ? NO_ERROR : GetLastError();
+
+ ::CloseHandle(usb_device_handle);
+
+ if (NO_ERROR != error) {
+ SetLastError(error);
+ }
+
+ return ret ? true : false;
}
ADBAPIHANDLE AdbLegacyInterfaceObject::OpenEndpoint(
UCHAR endpoint_index,
AdbOpenAccessType access_type,
AdbOpenSharingMode sharing_mode) {
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return NULL;
+ // Convert index into name and ID.
+ std::wstring endpoint_name;
+ UCHAR endpoint_id;
+
+ try {
+ if ((ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) ||
+ (def_read_endpoint_ == endpoint_index)) {
+ endpoint_name = DEVICE_BULK_READ_PIPE_NAME;
+ endpoint_id = read_endpoint_id_;
+ endpoint_index = def_read_endpoint_;
+ } else if ((ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) ||
+ (def_write_endpoint_ == endpoint_index)) {
+ endpoint_name = DEVICE_BULK_WRITE_PIPE_NAME;
+ endpoint_id = write_endpoint_id_;
+ endpoint_index = def_write_endpoint_;
+ } else {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+ } catch (...) {
+ // We don't expect exceptions other than OOM thrown here.
+ SetLastError(ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+
+ return OpenEndpoint(endpoint_name.c_str(), endpoint_id, endpoint_index,
+ access_type, sharing_mode);
+}
+
+ADBAPIHANDLE AdbLegacyInterfaceObject::OpenEndpoint(
+ const wchar_t* endpoint_name,
+ UCHAR endpoint_id,
+ UCHAR endpoint_index,
+ AdbOpenAccessType access_type,
+ AdbOpenSharingMode sharing_mode) {
+ if (!IsOpened()) {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return false;
+ }
+
+ AdbLegacyEndpointObject* adb_endpoint = NULL;
+
+ try {
+ adb_endpoint =
+ new AdbLegacyEndpointObject(this, endpoint_id, endpoint_index);
+ } catch (...) {
+ // We don't expect exceptions other than OOM thrown here.
+ SetLastError(ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+
+ // Build full path to the object
+ std::wstring endpoint_path = interface_name();
+ endpoint_path += L"\\";
+ endpoint_path += endpoint_name;
+
+ ADBAPIHANDLE ret = adb_endpoint->CreateHandle(endpoint_path.c_str(),
+ access_type,
+ sharing_mode);
+
+ adb_endpoint->Release();
+
+ return ret;
+}
+
+bool AdbLegacyInterfaceObject::CacheUsbDeviceDescriptor(
+ HANDLE usb_device_handle) {
+ DWORD ret_bytes = 0;
+ BOOL ret = DeviceIoControl(usb_device_handle,
+ ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR,
+ NULL, 0,
+ &usb_device_descriptor_,
+ sizeof(usb_device_descriptor_),
+ &ret_bytes,
+ NULL);
+ ATLASSERT(!ret || (sizeof(USB_DEVICE_DESCRIPTOR) == ret_bytes));
+
+ return ret ? true : false;
+}
+
+bool AdbLegacyInterfaceObject::CacheUsbConfigurationDescriptor(
+ HANDLE usb_device_handle) {
+ DWORD ret_bytes = 0;
+ BOOL ret = DeviceIoControl(usb_device_handle,
+ ADB_IOCTL_GET_USB_CONFIGURATION_DESCRIPTOR,
+ NULL, 0,
+ &usb_config_descriptor_,
+ sizeof(usb_config_descriptor_),
+ &ret_bytes,
+ NULL);
+ ATLASSERT(!ret || (sizeof(USB_CONFIGURATION_DESCRIPTOR) == ret_bytes));
+
+ return ret ? true : false;
+}
+
+bool AdbLegacyInterfaceObject::CacheUsbInterfaceDescriptor(
+ HANDLE usb_device_handle) {
+ DWORD ret_bytes = 0;
+ BOOL ret = DeviceIoControl(usb_device_handle,
+ ADB_IOCTL_GET_USB_INTERFACE_DESCRIPTOR,
+ NULL, 0,
+ &usb_interface_descriptor_,
+ sizeof(usb_interface_descriptor_),
+ &ret_bytes,
+ NULL);
+ ATLASSERT(!ret || (sizeof(USB_INTERFACE_DESCRIPTOR) == ret_bytes));
+
+ return ret ? true : false;
}
diff --git a/host/windows/usb/api/adb_legacy_interface.h b/host/windows/usb/api/adb_legacy_interface.h
index 6d4b0e8..8dd0b22 100755
--- a/host/windows/usb/api/adb_legacy_interface.h
+++ b/host/windows/usb/api/adb_legacy_interface.h
@@ -60,15 +60,6 @@
*/
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
//
@@ -124,6 +115,76 @@
virtual ADBAPIHANDLE OpenEndpoint(UCHAR endpoint_index,
AdbOpenAccessType access_type,
AdbOpenSharingMode sharing_mode);
+
+ //
+ // Internal operations
+ //
+
+ protected:
+ /** \brief Opens an endpoint on this interface.
+
+ @param[in] endpoint_name Endpoint file name.
+ @param[in] endpoint_id Endpoint (pipe) address on the device.
+ @param[in] endpoint_index Zero-based endpoint index.
+ @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.
+ */
+ ADBAPIHANDLE OpenEndpoint(const wchar_t* endpoint_name,
+ UCHAR endpoint_id,
+ UCHAR endpoint_index,
+ AdbOpenAccessType access_type,
+ AdbOpenSharingMode sharing_mode);
+
+ /** \brief Caches device descriptor for the USB device associated with
+ this interface.
+
+ This method is called from CreateHandle method to cache some interface
+ information.
+ @param[in] usb_device_handle Handle to USB device.
+ @return 'true' on success, 'false' on failure. If 'false' is returned
+ GetLastError() provides extended error information.
+ */
+ bool CacheUsbDeviceDescriptor(HANDLE usb_device_handle);
+
+ /** \brief Caches descriptor for the selected USB device configuration.
+
+ This method is called from CreateHandle method to cache some interface
+ information.
+ @param[in] usb_device_handle Handle to USB device.
+ @return 'true' on success, 'false' on failure. If 'false' is returned
+ GetLastError() provides extended error information.
+ */
+ bool CacheUsbConfigurationDescriptor(HANDLE usb_device_handle);
+
+ /** \brief Caches descriptor for this interface.
+
+ This method is called from CreateHandle method to cache some interface
+ information.
+ @param[in] usb_device_handle Handle to USB device.
+ @return 'true' on success, 'false' on failure. If 'false' is returned
+ GetLastError() provides extended error information.
+ */
+ bool CacheUsbInterfaceDescriptor(HANDLE usb_device_handle);
+
+ protected:
+ /// 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_LEGACY_INTERFACE_H__
diff --git a/host/windows/usb/api/adb_legacy_io_completion.cpp b/host/windows/usb/api/adb_legacy_io_completion.cpp
new file mode 100755
index 0000000..e3d1498
--- /dev/null
+++ b/host/windows/usb/api/adb_legacy_io_completion.cpp
@@ -0,0 +1,90 @@
+/*
+ * 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 AdbLegacyIOCompletion that
+ encapsulates a wrapper around OVERLAPPED Win32 structure returned from
+ asynchronous I/O requests issued via legacy USB API.
+*/
+
+#include "stdafx.h"
+#include "adb_legacy_io_completion.h"
+
+AdbLegacyIOCompletion::AdbLegacyIOCompletion(
+ AdbLegacyEndpointObject* parent_io_obj,
+ ULONG expected_trans_size,
+ HANDLE event_hndl,
+ bool is_write_ctl)
+ : AdbIOCompletion(parent_io_obj, expected_trans_size, event_hndl),
+ transferred_bytes_(0),
+ is_write_ioctl_(is_write_ctl) {
+}
+
+AdbLegacyIOCompletion::~AdbLegacyIOCompletion() {
+}
+
+bool AdbLegacyIOCompletion::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 = GetOverlappedResult(parent_legacy_io_object()->usb_handle(),
+ overlapped(),
+ &transfer,
+ wait) ? 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 = GetOverlappedResult(parent_legacy_io_object()->usb_handle(),
+ overlapped(),
+ &transfer,
+ wait) ? 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 = is_write_ioctl() ? transferred_bytes_ : transfer;
+ }
+
+ return ret;
+}
diff --git a/host/windows/usb/api/adb_legacy_io_completion.h b/host/windows/usb/api/adb_legacy_io_completion.h
new file mode 100755
index 0000000..743219e
--- /dev/null
+++ b/host/windows/usb/api/adb_legacy_io_completion.h
@@ -0,0 +1,115 @@
+/*
+ * 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_IO_COMPLETION_H__
+#define ANDROID_USB_API_ADB_LEGACY_IO_COMPLETION_H__
+/** \file
+ This file consists of declaration of class AdbLegacyIOCompletion that
+ encapsulates a wrapper around OVERLAPPED Win32 structure returned from
+ asynchronous I/O requests issued via legacy USB API.
+*/
+
+#include "adb_io_completion.h"
+#include "adb_legacy_endpoint_object.h"
+
+/** \brief Encapsulates a wrapper around OVERLAPPED Win32 structure returned
+ from asynchronous I/O requests issued via legacy USB 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 AdbLegacyIOCompletion : public AdbIOCompletion {
+ public:
+ /** \brief Constructs the object.
+
+ @param[in] parent_io_obj Parent legacy endpoint 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.
+ @param[in] is_write_ctl Flag indicating whether or not this completion
+ object is created for ADB_IOCTL_BULK_WRITE I/O.
+ */
+ AdbLegacyIOCompletion(AdbLegacyEndpointObject* parent_io_obj,
+ ULONG expected_trans_size,
+ HANDLE event_hndl,
+ bool is_write_ctl);
+
+ 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 ~AdbLegacyIOCompletion();
+
+ //
+ // Abstract overrides
+ //
+
+ public:
+ /** \brief Gets overlapped I/O result
+
+ This method uses 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 parent legacy endpoint.
+ AdbLegacyEndpointObject* parent_legacy_io_object() const {
+ return reinterpret_cast<AdbLegacyEndpointObject*>(parent_io_object());
+ }
+
+ /// Gets write IOCTL flag.
+ bool is_write_ioctl() const {
+ return is_write_ioctl_;
+ }
+
+ /// Gets address for ADB_IOCTL_BULK_WRITE output buffer.
+ ULONG* transferred_bytes_ptr() {
+ ATLASSERT(is_write_ioctl());
+ return &transferred_bytes_;
+ }
+
+ protected:
+ /// Recepient for number of transferred bytes in write IOCTL.
+ ULONG transferred_bytes_;
+
+ /// Write IOCTL flag.
+ bool is_write_ioctl_;
+};
+
+#endif // ANDROID_USB_API_ADB_LEGACY_IO_COMPLETION_H__
diff --git a/host/windows/usb/api/adb_winusb_interface.cpp b/host/windows/usb/api/adb_winusb_interface.cpp
index 00e575d..d09c1cb 100755
--- a/host/windows/usb/api/adb_winusb_interface.cpp
+++ b/host/windows/usb/api/adb_winusb_interface.cpp
@@ -305,7 +305,7 @@
}
ADBAPIHANDLE AdbWinUsbInterfaceObject::OpenEndpoint(UCHAR endpoint_id,
- UCHAR endpoint_index) {
+ UCHAR endpoint_index) {
if (!IsOpened()) {
SetLastError(ERROR_INVALID_HANDLE);
return false;