Refactor API classes to support both, WinUsb and Legacy API

To support both, WinUsb and Legacy driver APIs we need to abstract classes
that depend on driver API details and then implement two sets of the
actual classes: one for WinUsb, and another for the Legacy drivers, so
we can choose in runtime which objects should be instantiated, depending
on what type of driver we have underneath this API.
diff --git a/host/windows/usb/api/SOURCES b/host/windows/usb/api/SOURCES
index fcca802..4b9d360 100755
--- a/host/windows/usb/api/SOURCES
+++ b/host/windows/usb/api/SOURCES
@@ -85,12 +85,16 @@
 PRECOMPILED_SOURCEFILE = stdafx.cpp

 

 # Define source files for AdbWinApi.dll

-SOURCES = adb_api.cpp             \

-          adb_endpoint_object.cpp \

-          adb_helper_routines.cpp \

-          adb_interface.cpp       \

-          adb_interface_enum.cpp  \

-          adb_io_completion.cpp   \

-          adb_object_handle.cpp   \

-          AdbWinApi.cpp           \

+SOURCES = adb_api.cpp                     \

+          adb_endpoint_object.cpp         \

+          adb_winusb_endpoint_object.cpp  \

+          adb_helper_routines.cpp         \

+          adb_interface.cpp               \

+          adb_winusb_interface.cpp        \

+          adb_legacy_interface.cpp        \

+          adb_interface_enum.cpp          \

+          adb_io_completion.cpp           \

+          adb_winusb_io_completion.cpp    \

+          adb_object_handle.cpp           \

+          AdbWinApi.cpp                   \

 		      AdbWinApi.rc

diff --git a/host/windows/usb/api/adb_api.cpp b/host/windows/usb/api/adb_api.cpp
index eadf07a..f9bd94e 100644
--- a/host/windows/usb/api/adb_api.cpp
+++ b/host/windows/usb/api/adb_api.cpp
@@ -24,6 +24,8 @@
 #include "adb_object_handle.h"

 #include "adb_interface_enum.h"

 #include "adb_interface.h"

+#include "adb_winusb_interface.h"

+#include "adb_legacy_interface.h"

 #include "adb_endpoint_object.h"

 #include "adb_io_completion.h"

 #include "adb_helper_routines.h"

@@ -100,7 +102,11 @@
 

   try {

     // Instantiate object

-    obj = new AdbInterfaceObject(interface_name);

+    if (IsLegacyInterface(interface_name)) {

+      obj = new AdbLegacyInterfaceObject(interface_name);

+    } else {

+      obj = new AdbWinUsbInterfaceObject(interface_name);

+    }

 

     // Create handle for it

     ret = obj->CreateHandle();

diff --git a/host/windows/usb/api/adb_api.h b/host/windows/usb/api/adb_api.h
index e503238..900ea40 100644
--- a/host/windows/usb/api/adb_api.h
+++ b/host/windows/usb/api/adb_api.h
@@ -16,11 +16,14 @@
 

 #ifndef ANDROID_USB_API_ADBWINAPI_H__

 #define ANDROID_USB_API_ADBWINAPI_H__

+

 /** \file

   This file consists of declarations of routines exported by the API as well

   as types, structures, and constants definitions used in the API.

 */

 

+#include "adb_api_legacy.h"

+

 // Enables compillation for "straight" C

 #ifdef __cplusplus

   #define EXTERN_C    extern "C"

diff --git a/host/windows/usb/api/adb_api_legacy.h b/host/windows/usb/api/adb_api_legacy.h
new file mode 100755
index 0000000..d6a62d8
--- /dev/null
+++ b/host/windows/usb/api/adb_api_legacy.h
@@ -0,0 +1,190 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+#ifndef ANDROID_USB_API_ADB_API_LEGACY_H_

+#define ANDROID_USB_API_ADB_API_LEGACY_H_

+/** \file

+  This file consists of declarations of constants and structures required

+  for supporting communications of this API with a legacy (custom) USB

+  driver.

+*/

+

+// Enables compillation for "straight" C

+#ifdef __cplusplus

+  #define EXTERN_C    extern "C"

+#else

+  #define EXTERN_C    extern

+  typedef int bool;

+  #define true  1

+  #define false 0

+#endif

+

+/// Name for the default bulk read pipe

+#define DEVICE_BULK_READ_PIPE_NAME  L"BulkRead"

+

+/// Name for the default bulk write pipe

+#define DEVICE_BULK_WRITE_PIPE_NAME L"BulkWrite"

+

+/// Prefix for an index-based pipe name

+#define DEVICE_PIPE_NAME_PREFIX     L"PIPE_"

+

+/** \name IOCTL codes for the driver

+*/

+///@{

+

+/// Control code for IOCTL that gets USB_DEVICE_DESCRIPTOR

+#define ADB_CTL_GET_USB_DEVICE_DESCRIPTOR         10

+

+/// Control code for IOCTL that gets USB_CONFIGURATION_DESCRIPTOR

+#define ADB_CTL_GET_USB_CONFIGURATION_DESCRIPTOR  11

+

+/// Control code for IOCTL that gets USB_INTERFACE_DESCRIPTOR

+#define ADB_CTL_GET_USB_INTERFACE_DESCRIPTOR      12

+

+/// Control code for IOCTL that gets endpoint information

+#define ADB_CTL_GET_ENDPOINT_INFORMATION          13

+

+/// Control code for bulk read IOCTL

+#define ADB_CTL_BULK_READ                         14

+

+/// Control code for bulk write IOCTL

+#define ADB_CTL_BULK_WRITE                        15

+

+/// Control code for IOCTL that gets device serial number

+#define ADB_CTL_GET_SERIAL_NUMBER                 16

+

+/// IOCTL that gets USB_DEVICE_DESCRIPTOR

+#define ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR \

+              CTL_CODE(FILE_DEVICE_UNKNOWN, \

+                       ADB_CTL_GET_USB_DEVICE_DESCRIPTOR, \

+                       METHOD_BUFFERED, \

+                       FILE_READ_ACCESS)

+

+/// IOCTL that gets USB_CONFIGURATION_DESCRIPTOR

+#define ADB_IOCTL_GET_USB_CONFIGURATION_DESCRIPTOR \

+              CTL_CODE(FILE_DEVICE_UNKNOWN, \

+                       ADB_CTL_GET_USB_CONFIGURATION_DESCRIPTOR, \

+                       METHOD_BUFFERED, \

+                       FILE_READ_ACCESS)

+

+/// IOCTL that gets USB_INTERFACE_DESCRIPTOR

+#define ADB_IOCTL_GET_USB_INTERFACE_DESCRIPTOR \

+              CTL_CODE(FILE_DEVICE_UNKNOWN, \

+                       ADB_CTL_GET_USB_INTERFACE_DESCRIPTOR, \

+                       METHOD_BUFFERED, \

+                       FILE_READ_ACCESS)

+

+/// IOCTL that gets endpoint information

+#define ADB_IOCTL_GET_ENDPOINT_INFORMATION \

+              CTL_CODE(FILE_DEVICE_UNKNOWN, \

+                       ADB_CTL_GET_ENDPOINT_INFORMATION, \

+                       METHOD_BUFFERED, \

+                       FILE_READ_ACCESS)

+

+/// Bulk read IOCTL

+#define ADB_IOCTL_BULK_READ \

+              CTL_CODE(FILE_DEVICE_UNKNOWN, \

+                       ADB_CTL_BULK_READ, \

+                       METHOD_OUT_DIRECT, \

+                       FILE_READ_ACCESS)

+

+// For bulk write IOCTL we send request data in the form of AdbBulkTransfer

+// structure and output buffer is just ULONG that receives number of bytes

+// actually written. Since both of these are tiny we can use buffered I/O

+// for this IOCTL.

+/// Bulk write IOCTL

+#define ADB_IOCTL_BULK_WRITE \

+              CTL_CODE(FILE_DEVICE_UNKNOWN, \

+                       ADB_CTL_BULK_WRITE, \

+                       METHOD_BUFFERED, \

+                       FILE_WRITE_ACCESS)

+

+/// IOCTL that gets device serial number

+#define ADB_IOCTL_GET_SERIAL_NUMBER \

+              CTL_CODE(FILE_DEVICE_UNKNOWN, \

+                       ADB_CTL_GET_SERIAL_NUMBER, \

+                       METHOD_BUFFERED, \

+                       FILE_READ_ACCESS)

+

+///@}

+

+/** Structure AdbQueryEndpointInformation formats input for

+  ADB_IOCTL_GET_ENDPOINT_INFORMATION IOCTL request

+*/

+struct AdbQueryEndpointInformation {

+  /// Zero-based endpoint index for which information is queried.

+  /// See ADB_QUERY_BULK_xxx_ENDPOINT_INDEX for shortcuts.

+  UCHAR endpoint_index;

+};

+

+/** Structure AdbBulkTransfer formats parameters for ADB_CTL_BULK_READ and

+  ADB_CTL_BULK_WRITE IOCTL requests.

+*/

+struct AdbBulkTransfer {

+  /// Time in milliseconds to complete this request

+  ULONG time_out;

+

+  /// Size of the data to transfer. This parameter is used only for

+  /// ADB_CTL_BULK_WRITE request. For ADB_CTL_BULK_READ requests transfer

+  /// size is defined by the output buffer size.

+  ULONG transfer_size;

+

+  /// Initializes statically allocated structure

+  __forceinline AdbBulkTransfer() {

+    time_out = 0;

+    transfer_size = 0;

+    for_x64 = 0;

+  }

+

+  /// Provides access to protected write_buffer field

+  void* GetWriteBuffer() {

+    return write_buffer;

+  }

+

+  /// Provides access to protected write_buffer field

+  const void* GetWriteBuffer() const {

+    return write_buffer;

+  }

+

+  /// Sets write_buffer field.

+  void SetWriteBuffer(void* buffer) {

+    // For 32-bit we must zero out high 32 bit of the address, so 64-bit

+    // driver will see valid address when accessing 64-bit write_buffer.

+    for_x64 = 0;

+    write_buffer = buffer;

+  }

+

+protected:

+  /// Pointer to the actual buffer for ADB_CTL_BULK_WRITE request. This field

+  /// is not used in ADB_CTL_BULK_READ request. Note that in order to support

+  /// compatibility between 32-bit and 64-bit versions of both, driver and

+  /// application we must sizeof this field to the max pointer sizeof (which

+  /// is 64 bit in our case). The idea is that if IOCTL was issued by a 64-bit

+  /// process to a 64-bit driver, write_buffer will be valid 64-bit pointer to

+  /// the write buffer. Same is true for 32-bit app talking to 32-bit driver.

+  /// If, however, a 32-bit app is talking to 64-bit driver, then write_buffer

+  /// initialized by 32-bit app will contain 32-bit address, which will be

+  /// correctly picked up ("extended") by 64-bit driver. Since when setting

+  /// this field by a 32-bit app requires some extra work (see SetWriteBuffer)

+  /// we hide this field, making it accessible only throug the accessor

+  /// methods (Get/SetWriteBuffer).

+  union {

+    void* write_buffer;

+    __int64 for_x64;

+  };

+};

+

+#endif  // ANDROID_USB_API_ADB_API_LEGACY_H_

diff --git a/host/windows/usb/api/adb_endpoint_object.cpp b/host/windows/usb/api/adb_endpoint_object.cpp
index 9237a60..6e093e2 100644
--- a/host/windows/usb/api/adb_endpoint_object.cpp
+++ b/host/windows/usb/api/adb_endpoint_object.cpp
@@ -15,14 +15,12 @@
  */

 

 /** \file

-  This file consists of implementation of class AdbIOObject that

-  encapsulates an interface on our USB device.

+  This file consists of implementation of class AdbEndpointObject that

+  encapsulates a handle opened to an endpoint on our device.

 */

 

 #include "stdafx.h"

 #include "adb_endpoint_object.h"

-#include "adb_io_completion.h"

-#include "adb_helper_routines.h"

 

 AdbEndpointObject::AdbEndpointObject(AdbInterfaceObject* parent_interf,

                                      UCHAR endpoint_id,

@@ -96,126 +94,3 @@
                              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;

-}

diff --git a/host/windows/usb/api/adb_endpoint_object.h b/host/windows/usb/api/adb_endpoint_object.h
index d4d1a6a..295eb46 100644
--- a/host/windows/usb/api/adb_endpoint_object.h
+++ b/host/windows/usb/api/adb_endpoint_object.h
@@ -17,14 +17,17 @@
 #ifndef ANDROID_USB_API_ADB_ENDPOINT_OBJECT_H__

 #define ANDROID_USB_API_ADB_ENDPOINT_OBJECT_H__

 /** \file

-  This file consists of declaration of class AdbIOObject that encapsulates a

-  handle opened to an endpoint on our device.

+  This file consists of declaration of class AdbEndpointObject that

+  encapsulates a handle opened to an endpoint on our device.

 */

 

 #include "adb_interface.h"

 

 /** Class AdbEndpointObject encapsulates a handle opened to an endpoint on

   our device.

+

+  This class implement functionality that is common for both, WinUsb and

+  legacy APIs.

 */

 class AdbEndpointObject : public AdbObjectHandle {

  public:

@@ -49,6 +52,55 @@
   */

   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 @@
     @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 @@
                          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 @@
                                           NULL;

   }

 

-  /// Gets parent interface WinUsb handle

-  WINUSB_INTERFACE_HANDLE winusb_handle() const {

-    return parent_interface()->winusb_handle();

-  }

-

  protected:

   /// Parent interface

   AdbInterfaceObject* parent_interface_;

diff --git a/host/windows/usb/api/adb_helper_routines.cpp b/host/windows/usb/api/adb_helper_routines.cpp
index 3a7748b..0bc44df 100644
--- a/host/windows/usb/api/adb_helper_routines.cpp
+++ b/host/windows/usb/api/adb_helper_routines.cpp
@@ -187,3 +187,32 @@
 

   return !name->empty();

 }

+

+bool IsLegacyInterface(const wchar_t* interface_name) {

+  // Open USB device for this intefface

+  HANDLE usb_device_handle = CreateFile(interface_name,

+                                        GENERIC_READ | GENERIC_WRITE,

+                                        FILE_SHARE_READ | FILE_SHARE_WRITE,

+                                        NULL,

+                                        OPEN_EXISTING,

+                                        0,

+                                        NULL);

+  if (INVALID_HANDLE_VALUE == usb_device_handle)

+    return NULL;

+

+  // Try to issue ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR IOCTL that is supported

+  // by the legacy driver, but is not implemented in the WinUsb driver.

+  DWORD ret_bytes = 0;

+  USB_DEVICE_DESCRIPTOR descriptor;

+  BOOL ret = DeviceIoControl(usb_device_handle,

+                             ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR,

+                             NULL, 0,

+                             &descriptor,

+                             sizeof(descriptor),

+                             &ret_bytes,

+                             NULL);

+  ::CloseHandle(usb_device_handle);

+

+  // If IOCTL succeeded we've got legacy driver underneath.

+  return ret ? true : false;

+}

diff --git a/host/windows/usb/api/adb_helper_routines.h b/host/windows/usb/api/adb_helper_routines.h
index 68a20a9..907e638 100644
--- a/host/windows/usb/api/adb_helper_routines.h
+++ b/host/windows/usb/api/adb_helper_routines.h
@@ -106,4 +106,15 @@
                       PSP_DEVICE_INTERFACE_DATA dev_info_data,

                       std::wstring* name);

 

+/** \brief Checks if given interface is available via custom USB driver.

+

+  In this routine we will query the given interface with an IOCTL that should

+  be supported by the custom driver. If IOCTL fails, we make a conclusion that

+  this interface is available via WinUsb, and not via custom USB driver.

+  @param[in] interface_name Name of the interface to check.

+  @return true if interface is available via custom USB driver, or false

+          otherwise.

+*/

+bool IsLegacyInterface(const wchar_t* interface_name);

+

 #endif  // ANDROID_USB_API_ADB_HELPER_ROUTINES_H__

diff --git a/host/windows/usb/api/adb_interface.cpp b/host/windows/usb/api/adb_interface.cpp
index 9b073a4..a0803aa 100644
--- a/host/windows/usb/api/adb_interface.cpp
+++ b/host/windows/usb/api/adb_interface.cpp
@@ -16,117 +16,19 @@
 

 /** \file

   This file consists of implementation of class AdbInterfaceObject that

-  encapsulates an interface on our USB device.

+  encapsulates a generic interface on our USB device.

 */

 

 #include "stdafx.h"

 #include "adb_interface.h"

-#include "adb_endpoint_object.h"

 

 AdbInterfaceObject::AdbInterfaceObject(const wchar_t* interf_name)

     : AdbObjectHandle(AdbObjectTypeInterface),

-      interface_name_(interf_name),

-      usb_device_handle_(INVALID_HANDLE_VALUE),

-      winusb_handle_(NULL),

-      interface_number_(0xFF),

-      def_read_endpoint_(0xFF),

-      read_endpoint_id_(0xFF),

-      def_write_endpoint_(0xFF),

-      write_endpoint_id_(0xFF) {

+      interface_name_(interf_name) {

   ATLASSERT(NULL != interf_name);

 }

 

 AdbInterfaceObject::~AdbInterfaceObject() {

-  ATLASSERT(NULL == winusb_handle_);

-  ATLASSERT(INVALID_HANDLE_VALUE == usb_device_handle_);

-}

-

-ADBAPIHANDLE AdbInterfaceObject::CreateHandle() {

-  // Open USB device for this inteface Note that WinUsb API

-  // requires the handle to be opened for overlapped I/O.

-  usb_device_handle_ = CreateFile(interface_name().c_str(),

-                                  GENERIC_READ | GENERIC_WRITE,

-                                  FILE_SHARE_READ | FILE_SHARE_WRITE,

-                                  NULL, OPEN_EXISTING,

-                                  FILE_FLAG_OVERLAPPED, NULL);

-  if (INVALID_HANDLE_VALUE == usb_device_handle_)

-    return NULL;

-

-  // Initialize WinUSB API for this interface

-  if (!WinUsb_Initialize(usb_device_handle_, &winusb_handle_))

-    return NULL;

-

-  // Cache current interface number that will be used in

-  // WinUsb_Xxx calls performed on this interface.

-  if (!WinUsb_GetCurrentAlternateSetting(winusb_handle(), &interface_number_))

-    return false;

-

-  // Cache interface properties

-  unsigned long bytes_written;

-

-  // Cache USB device descriptor

-  if (!WinUsb_GetDescriptor(winusb_handle(), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0,

-                            reinterpret_cast<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 @@
   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 @@
 

   return true;

 }

-

-bool AdbInterfaceObject::GetEndpointInformation(UCHAR endpoint_index,

-                                                AdbEndpointInformation* info) {

-  if (!IsOpened()) {

-    SetLastError(ERROR_INVALID_HANDLE);

-    return false;

-  }

-

-  if (NULL == info) {

-    SetLastError(ERROR_INVALID_PARAMETER);

-    return false;

-  }

-

-  // Get actual endpoint index for predefined read / write endpoints.

-  if (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) {

-    endpoint_index = def_read_endpoint_;

-  } else if (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) {

-    endpoint_index = def_write_endpoint_;

-  }

-

-  // Query endpoint information

-  WINUSB_PIPE_INFORMATION pipe_info;

-  if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint_index,

-                        &pipe_info)) {

-    return false;

-  }

-

-  // Save endpoint information into output.

-  info->max_packet_size = pipe_info.MaximumPacketSize;

-  info->max_transfer_size = 0xFFFFFFFF;

-  info->endpoint_address = pipe_info.PipeId;

-  info->polling_interval = pipe_info.Interval;

-  info->setting_index = interface_number();

-  switch (pipe_info.PipeType) {

-    case UsbdPipeTypeControl:

-      info->endpoint_type = AdbEndpointTypeControl;

-      break;

-

-    case UsbdPipeTypeIsochronous:

-      info->endpoint_type = AdbEndpointTypeIsochronous;

-      break;

-

-    case UsbdPipeTypeBulk:

-      info->endpoint_type = AdbEndpointTypeBulk;

-      break;

-

-    case UsbdPipeTypeInterrupt:

-      info->endpoint_type = AdbEndpointTypeInterrupt;

-      break;

-

-    default:

-      info->endpoint_type = AdbEndpointTypeInvalid;

-      break;

-  }

-

-  return true;

-}

-

-ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint(

-    UCHAR endpoint_index,

-    AdbOpenAccessType access_type,

-    AdbOpenSharingMode sharing_mode) {

-  // Convert index into id

-  UCHAR endpoint_id;

-

-  if ((ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) ||

-      (def_read_endpoint_ == endpoint_index)) {

-    endpoint_id = read_endpoint_id_;

-    endpoint_index = def_read_endpoint_;

-  } else if ((ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) ||

-             (def_write_endpoint_ == endpoint_index)) {

-    endpoint_id = write_endpoint_id_;

-    endpoint_index = def_write_endpoint_;

-  } else {

-    SetLastError(ERROR_INVALID_PARAMETER);

-    return false;

-  }

-

-  return OpenEndpoint(endpoint_id, endpoint_index);

-}

-

-ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint(UCHAR endpoint_id,

-                                              UCHAR endpoint_index) {

-  if (!IsOpened()) {

-    SetLastError(ERROR_INVALID_HANDLE);

-    return false;

-  }

-

-  AdbEndpointObject* adb_endpoint = NULL;

-  

-  try {

-    adb_endpoint = new AdbEndpointObject(this, endpoint_id, endpoint_index);

-  } catch (...) {

-    SetLastError(ERROR_OUTOFMEMORY);

-    return NULL;

-  }

-

-  ADBAPIHANDLE ret = adb_endpoint->CreateHandle();

-

-  adb_endpoint->Release();

-

-  return ret;

-}

diff --git a/host/windows/usb/api/adb_interface.h b/host/windows/usb/api/adb_interface.h
index d428d12..4afb17d 100644
--- a/host/windows/usb/api/adb_interface.h
+++ b/host/windows/usb/api/adb_interface.h
@@ -18,12 +18,15 @@
 #define ANDROID_USB_API_ADB_INTERFACE_H__

 /** \file

   This file consists of declaration of class AdbInterfaceObject that

-  encapsulates an interface on our USB device.

+  encapsulates a generic interface on our USB device.

 */

 

 #include "adb_object_handle.h"

 

 /** \brief Encapsulates an interface on our USB device.

+

+  This is an abstract class that implements functionality common for both,

+  legacy, and WinUsb based interfaces.

 */

 class AdbInterfaceObject : public AdbObjectHandle {

  public:

@@ -41,53 +44,11 @@
   */

   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 @@
     @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 @@
     @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 @@
             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 @@
     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 @@
 

   /// Cached usb interface descriptor

   USB_INTERFACE_DESCRIPTOR      usb_interface_descriptor_;

-

-  /// Handle to the USB device

-  HANDLE                        usb_device_handle_;

-

-  /// Interface handle used by WinUSB API

-  WINUSB_INTERFACE_HANDLE       winusb_handle_;

-

-  /// Current interface number. This value is obtained via call to

-  /// WinUsb_GetCurrentAlternateSetting and is used in WinUsb_Xxx

-  /// calls that require interface number.

-  UCHAR                         interface_number_;

-

-  /// Index for the default bulk read endpoint

-  UCHAR                         def_read_endpoint_;

-

-  /// ID for the default bulk read endpoint

-  UCHAR                         read_endpoint_id_;

-

-  /// Index for the default bulk write endpoint

-  UCHAR                         def_write_endpoint_;

-

-  /// ID for the default bulk write endpoint

-  UCHAR                         write_endpoint_id_;

 };

 

 #endif  // ANDROID_USB_API_ADB_INTERFACE_H__

diff --git a/host/windows/usb/api/adb_io_completion.cpp b/host/windows/usb/api/adb_io_completion.cpp
index 64f97fd..6575e03 100644
--- a/host/windows/usb/api/adb_io_completion.cpp
+++ b/host/windows/usb/api/adb_io_completion.cpp
@@ -1,5 +1,5 @@
 /*

- * Copyright (C) 2006 The Android Open Source Project

+ * Copyright (C) 2009 The Android Open Source Project

  *

  * Licensed under the Apache License, Version 2.0 (the "License");

  * you may not use this file except in compliance with the License.

@@ -16,8 +16,8 @@
 

 /** \file

   This file consists of implementation of class AdbIOCompletion that

-  encapsulates a wrapper around OVERLAPPED Win32 structure returned

-  from asynchronous I/O requests.

+  encapsulates a generic wrapper around OVERLAPPED Win32 structure

+  returned from asynchronous I/O requests.

 */

 

 #include "stdafx.h"

@@ -39,54 +39,6 @@
   parent_io_object_->Release();

 }

 

-bool AdbIOCompletion::GetOvelappedIoResult(LPOVERLAPPED ovl_data,

-                                           ULONG* bytes_transferred,

-                                           bool wait) {

-  if (NULL != bytes_transferred)

-    *bytes_transferred = 0;

-

-  if (!IsOpened()) {

-    SetLastError(ERROR_INVALID_HANDLE);

-    return false;

-  }

-

-  ULONG transfer;

-  bool ret = WinUsb_GetOverlappedResult(parent_io_object()->winusb_handle(),

-                                        overlapped(),

-                                        &transfer,

-                                        wait ? TRUE : FALSE) ? true : false;

-

-  // TODO: This is bizzare but I've seen it happening

-  // that GetOverlappedResult with wait set to true returns "prematurely",

-  // with wrong transferred bytes value and GetLastError reporting

-  // ERROR_IO_PENDING. So, lets give it an up to a 20 ms loop!

-  ULONG error = GetLastError();

-

-  if (wait && ret && (0 == transfer) && (0 != expected_transfer_size_) &&

-      ((ERROR_IO_INCOMPLETE == error) || (ERROR_IO_PENDING == error))) {

-    for (int trying = 0; trying < 10; trying++) {

-      Sleep(2);

-      ret = WinUsb_GetOverlappedResult(parent_io_object()->winusb_handle(),

-                                       overlapped(),

-                                       &transfer,

-                                       wait ? TRUE : FALSE) ? true : false;

-      error = GetLastError();

-      if (!ret || (0 != transfer) ||

-          ((ERROR_IO_INCOMPLETE != error) && (ERROR_IO_PENDING != error))) {

-        break;

-      }

-    }

-  }

-

-  if (NULL != ovl_data)

-    CopyMemory(ovl_data, overlapped(), sizeof(OVERLAPPED));

-

-  if (NULL != bytes_transferred)

-    *bytes_transferred = transfer;

-

-  return ret;

-}

-

 bool AdbIOCompletion::IsCompleted() {

   SetLastError(NO_ERROR);

   if (!IsOpened()) {

diff --git a/host/windows/usb/api/adb_io_completion.h b/host/windows/usb/api/adb_io_completion.h
index 3fea0e8..8a7c1d9 100644
--- a/host/windows/usb/api/adb_io_completion.h
+++ b/host/windows/usb/api/adb_io_completion.h
@@ -1,5 +1,5 @@
 /*

- * Copyright (C) 2006 The Android Open Source Project

+ * Copyright (C) 2009 The Android Open Source Project

  *

  * Licensed under the Apache License, Version 2.0 (the "License");

  * you may not use this file except in compliance with the License.

@@ -18,18 +18,20 @@
 #define ANDROID_USB_API_ADB_IO_COMPLETION_H__

 /** \file

   This file consists of declaration of class AdbIOCompletion that encapsulates

-  a wrapper around OVERLAPPED Win32 structure returned from asynchronous I/O

-  requests.

+  a generic wrapper around OVERLAPPED Win32 structure returned from

+  asynchronous I/O requests.

 */

 

 #include "adb_endpoint_object.h"

 

-/** \brief Encapsulates encapsulates a wrapper around OVERLAPPED Win32

+/** \brief Encapsulates encapsulates a generic wrapper around OVERLAPPED Win32

   structure returned from asynchronous I/O requests.

 

-  A handle to this object is returned to the caller of each successful

-  asynchronous I/O request. Just like all other handles this handle

-  must be closed after it's no longer needed.

+  This is an abstract class that implements functionality common for I/O

+  performed via WinUsb as well as legacy driver APIs. A handle to this object

+  is returned to the caller of each successful asynchronous I/O request. Just

+  like all other handles this handle must be closed after it's no longer

+  needed.

 */

 class AdbIOCompletion : public AdbObjectHandle {

  public:

@@ -56,6 +58,10 @@
   */

   virtual ~AdbIOCompletion();

 

+  //

+  // Abstract

+  //

+

  public:

   /** \brief Gets overlapped I/O result

 

@@ -76,8 +82,13 @@
   */

   virtual bool GetOvelappedIoResult(LPOVERLAPPED ovl_data,

                                     ULONG* bytes_transferred,

-                                    bool wait);

+                                    bool wait) = 0;

 

+  //

+  // Operations

+  //

+

+ public:

   /** \brief Checks if I/O that this object represents has completed.

 

     @return true if I/O has been completed or false if it's still

diff --git a/host/windows/usb/api/adb_legacy_interface.cpp b/host/windows/usb/api/adb_legacy_interface.cpp
new file mode 100755
index 0000000..95c750e
--- /dev/null
+++ b/host/windows/usb/api/adb_legacy_interface.cpp
@@ -0,0 +1,64 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+/** \file

+  This file consists of implementation of class AdbLegacyInterfaceObject

+  that encapsulates an interface on our USB device that is accessible

+  via WinUsb API.

+*/

+

+#include "stdafx.h"

+#include "adb_legacy_interface.h"

+#include "adb_endpoint_object.h"

+

+AdbLegacyInterfaceObject::AdbLegacyInterfaceObject(const wchar_t* interf_name)

+  : AdbInterfaceObject(interf_name) {

+}

+

+AdbLegacyInterfaceObject::~AdbLegacyInterfaceObject() {

+}

+

+ADBAPIHANDLE AdbLegacyInterfaceObject::CreateHandle() {

+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

+  return NULL;

+}

+

+bool AdbLegacyInterfaceObject::CloseHandle() {

+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

+  return false;

+}

+

+bool AdbLegacyInterfaceObject::GetSerialNumber(void* buffer,

+                                               unsigned long* buffer_char_size,

+                                               bool ansi) {

+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

+  return false;

+}

+

+bool AdbLegacyInterfaceObject::GetEndpointInformation(

+    UCHAR endpoint_index,

+    AdbEndpointInformation* info) {

+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

+  return false;

+}

+

+ADBAPIHANDLE AdbLegacyInterfaceObject::OpenEndpoint(

+    UCHAR endpoint_index,

+    AdbOpenAccessType access_type,

+    AdbOpenSharingMode sharing_mode) {

+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

+  return NULL;

+}

diff --git a/host/windows/usb/api/adb_legacy_interface.h b/host/windows/usb/api/adb_legacy_interface.h
new file mode 100755
index 0000000..6d4b0e8
--- /dev/null
+++ b/host/windows/usb/api/adb_legacy_interface.h
@@ -0,0 +1,129 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+#ifndef ANDROID_USB_API_ADB_LEGACY_INTERFACE_H__

+#define ANDROID_USB_API_ADB_LEGACY_INTERFACE_H__

+/** \file

+  This file consists of declaration of class AdbLegacyInterfaceObject

+  that encapsulates an interface on our USB device that is accessible

+  via custom USB driver.

+*/

+

+#include "adb_interface.h"

+

+/** \brief Encapsulates an interface on our USB device that is accessible

+  via custom USB driver.

+*/

+class AdbLegacyInterfaceObject : public AdbInterfaceObject {

+ public:

+  /** \brief Constructs the object.

+

+    @param[in] interf_name Name of the interface

+  */

+  explicit AdbLegacyInterfaceObject(const wchar_t* interf_name);

+

+ protected:

+  /** \brief Destructs the object.

+

+   We hide destructor in order to prevent ourseves from accidentaly allocating

+   instances on the stack. If such attemp occur, compiler will error.

+  */

+  virtual ~AdbLegacyInterfaceObject();

+

+  //

+  // Virtual overrides

+  //

+

+ public:

+  /** \brief Creates handle to this object.

+

+    In this call a handle for this object is generated and object is added

+    to the AdbObjectHandleMap. We override this method in order to initialize

+    access to the custom driver.

+    @return A handle to this object on success or NULL on an error.

+            If NULL is returned GetLastError() provides extended error

+            information. ERROR_GEN_FAILURE is set if an attempt was

+            made to create already opened object.

+  */

+  virtual ADBAPIHANDLE CreateHandle();

+

+  /** \brief This method is called when handle to this object gets closed.

+

+    In this call object is deleted from the AdbObjectHandleMap.

+    @return true on success or false if object is already closed. If

+            false is returned GetLastError() provides extended error

+            information.

+  */

+  virtual bool CloseHandle();

+

+  //

+  // Abstract overrides

+  //

+

+ public:

+  /** \brief Gets serial number for interface's device.

+

+    @param[out] buffer Buffer for the serail number string. Can be NULL in

+           which case buffer_char_size will contain number of characters

+           required for the string.

+    @param[in,out] buffer_char_size On the way in supplies size (in characters)

+           of the buffer. On the way out, if method failed and GetLastError

+           reports ERROR_INSUFFICIENT_BUFFER, will contain number of characters

+           required for the name.

+    @param[in] ansi If true the name will be returned as single character

+           string. Otherwise name will be returned as wide character string.

+    @return true on success, false on failure. If false is returned

+            GetLastError() provides extended error information.

+  */

+  virtual bool GetSerialNumber(void* buffer,

+                               unsigned long* buffer_char_size,

+                               bool ansi);

+

+  /** \brief Gets information about an endpoint on this interface.

+

+    @param[in] endpoint_index Zero-based endpoint index. There are two

+           shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX

+           and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide infor about

+           (default?) bulk write and read endpoints respectively.

+    @param[out] info Upon successful completion will have endpoint information.

+    @return true on success, false on failure. If false is returned

+            GetLastError() provides extended error information.

+  */

+  virtual bool GetEndpointInformation(UCHAR endpoint_index,

+                                      AdbEndpointInformation* info);

+

+  /** \brief Opens an endpoint on this interface.

+

+    @param[in] endpoint_index Zero-based endpoint index. There are two

+           shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX

+           and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide infor about

+           (default?) bulk write and read endpoints respectively.

+    @param[in] access_type Desired access type. In the current implementation

+           this parameter has no effect on the way endpoint is opened. It's

+           always read / write access.

+    @param[in] sharing_mode Desired share mode. In the current implementation

+           this parameter has no effect on the way endpoint is opened. It's

+           always shared for read / write.

+    @return Handle to the opened endpoint object or NULL on failure.

+            If NULL is returned GetLastError() provides extended information

+            about the error that occurred.

+  */

+  virtual ADBAPIHANDLE OpenEndpoint(UCHAR endpoint_index,

+                                    AdbOpenAccessType access_type,

+                                    AdbOpenSharingMode sharing_mode);

+};

+

+#endif  // ANDROID_USB_API_ADB_LEGACY_INTERFACE_H__

diff --git a/host/windows/usb/api/adb_winusb_endpoint_object.cpp b/host/windows/usb/api/adb_winusb_endpoint_object.cpp
new file mode 100755
index 0000000..236de3b
--- /dev/null
+++ b/host/windows/usb/api/adb_winusb_endpoint_object.cpp
@@ -0,0 +1,159 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+/** \file

+  This file consists of implementation of class AdbWinUsbEndpointObject that

+  encapsulates a handle opened to a WinUsb endpoint on our device.

+*/

+

+#include "stdafx.h"

+#include "adb_winusb_endpoint_object.h"

+#include "adb_winusb_io_completion.h"

+#include "adb_helper_routines.h"

+

+AdbWinUsbEndpointObject::AdbWinUsbEndpointObject(

+    AdbWinUsbInterfaceObject* parent_interf,

+    UCHAR endpoint_id,

+    UCHAR endpoint_index)

+    : AdbEndpointObject(parent_interf, endpoint_id, endpoint_index) {

+}

+

+AdbWinUsbEndpointObject::~AdbWinUsbEndpointObject() {

+}

+

+ADBAPIHANDLE AdbWinUsbEndpointObject::CommonAsyncReadWrite(

+    bool is_read,

+    void* buffer,

+    ULONG bytes_to_transfer,

+    ULONG* bytes_transferred,

+    HANDLE event_handle,

+    ULONG time_out) {

+  if (!SetTimeout(time_out))

+    return false;

+

+  // Create completion i/o object

+  AdbIOCompletion* adb_io_completion = NULL;

+

+  try {

+    adb_io_completion = new AdbWinUsbIOCompletion(this,

+                                                  bytes_to_transfer,

+                                                  event_handle);

+  } catch (... ) {

+    SetLastError(ERROR_OUTOFMEMORY);

+    return NULL;

+  }

+

+  // Create a handle for it

+  ADBAPIHANDLE ret = adb_io_completion->CreateHandle();

+  ULONG transferred = 0;

+  if (NULL != ret) {

+    BOOL res = TRUE;

+    // Go the read / write file way

+    res = is_read ?

+        WinUsb_ReadPipe(parent_winusb_interface()->winusb_handle(),

+                        endpoint_id(),

+                        reinterpret_cast<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;

+}

diff --git a/host/windows/usb/api/adb_winusb_endpoint_object.h b/host/windows/usb/api/adb_winusb_endpoint_object.h
new file mode 100755
index 0000000..26ef53b
--- /dev/null
+++ b/host/windows/usb/api/adb_winusb_endpoint_object.h
@@ -0,0 +1,131 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+#ifndef ANDROID_USB_API_ADB_WINUSB_ENDPOINT_OBJECT_H__

+#define ANDROID_USB_API_ADB_WINUSB_ENDPOINT_OBJECT_H__

+/** \file

+  This file consists of declaration of class AdbWinUsbEndpointObject that

+  encapsulates a handle opened to a WinUsb endpoint on our device.

+*/

+

+#include "adb_endpoint_object.h"

+#include "adb_winusb_interface.h"

+

+/** Class AdbWinUsbEndpointObject encapsulates a handle opened to an endpoint on

+  our device.

+*/

+class AdbWinUsbEndpointObject : public AdbEndpointObject {

+ public:

+  /** \brief Constructs the object

+

+    @param[in] interface Parent WinUsb interface for this object.

+    @param[in] endpoint_id Endpoint ID (endpoint address) on the device.

+    @param[in] endpoint_index Zero-based endpoint index in the interface's

+          array of endpoints.

+  */

+  AdbWinUsbEndpointObject(AdbWinUsbInterfaceObject* parent_interf,

+                          UCHAR endpoint_id,

+                          UCHAR endpoint_index);

+

+ protected:

+  /** \brief Destructs the object.

+

+    We hide destructor in order to prevent ourseves from accidentaly allocating

+    instances on the stack. If such attemp occur, compiler will error.

+  */

+  virtual ~AdbWinUsbEndpointObject();

+

+  //

+  // Abstract overrides

+  //

+

+ protected:

+  /** \brief Common code for async read / write

+

+    @param[in] is_read Read or write selector.

+    @param[in,out] buffer Pointer to the buffer for read / write.

+    @param[in] bytes_to_transfer Number of bytes to be read / written.

+    @param[out] bytes_transferred Number of bytes read / written. Can be NULL.

+    @param[in] event_handle Event handle that should be signaled when async I/O

+           completes. Can be NULL. If it's not NULL this handle will be used to

+           initialize OVERLAPPED structure for this I/O.

+    @param[in] time_out A timeout (in milliseconds) required for this I/O to

+           complete. Zero value in this parameter means that there is no

+           timeout set for this I/O.

+    @return A handle to IO completion object or NULL on failure. If NULL is

+            returned GetLastError() provides extended error information.

+  */

+  virtual ADBAPIHANDLE CommonAsyncReadWrite(bool is_read,

+                                            void* buffer,

+                                            ULONG bytes_to_transfer,

+                                            ULONG* bytes_transferred,

+                                            HANDLE event_handle,

+                                            ULONG time_out);

+

+  /** \brief Common code for sync read / write

+

+    @param[in] is_read Read or write selector.

+    @param[in,out] buffer Pointer to the buffer for read / write.

+    @param[in] bytes_to_transfer Number of bytes to be read / written.

+    @param[out] bytes_transferred Number of bytes read / written. Can be NULL.

+    @param[in] time_out A timeout (in milliseconds) required for this I/O to

+           complete. Zero value in this parameter means that there is no

+           timeout set for this I/O.

+    @return true on success, false on failure. If false is returned

+            GetLastError() provides extended error information.

+  */

+  virtual bool CommonSyncReadWrite(bool is_read,

+                                   void* buffer,

+                                   ULONG bytes_to_transfer,

+                                   ULONG* bytes_transferred,

+                                   ULONG time_out);

+

+  //

+  // Operations

+  //

+

+ protected:

+  /** \brief Sets read / write operation timeout.

+

+    @param[in] timeout Timeout value in milliseconds to use for current read

+          or write operation. Zero value passed in this parameters indicate

+          not timeout at all. Note that timeout that is set with this method is

+          global per endpoint (pipe). I.e. once set, it will be used against

+          all read / write operations performed on this endpoint, untill

+          another call to this method modifies it. This is a WinUsb design

+          flaw. Microsoft is aware of this and (hopefuly) future versions of

+          WinUsb framework will accept a timeout parameter in WinUsb_Read/Write

+          routines. For the purposes of ADB this flaw doesn't apperar to be an

+          issue, since we use single-threaded synchronous read / writes, so

+          there is no conflict in setting per-endpoint timeouts.

+    @return true on success, false on failure. If false is returned

+            GetLastError() provides extended error information.

+  */

+  virtual bool SetTimeout(ULONG timeout);

+

+ public:

+  /// Gets parent WinUsb interface 

+  AdbWinUsbInterfaceObject* parent_winusb_interface() const {

+    return reinterpret_cast<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__

diff --git a/host/windows/usb/api/adb_winusb_interface.cpp b/host/windows/usb/api/adb_winusb_interface.cpp
new file mode 100755
index 0000000..00e575d
--- /dev/null
+++ b/host/windows/usb/api/adb_winusb_interface.cpp
@@ -0,0 +1,329 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+/** \file

+  This file consists of implementation of class AdbWinUsbInterfaceObject

+  that encapsulates an interface on our USB device that is accessible

+  via WinUsb API.

+*/

+

+#include "stdafx.h"

+#include "adb_winusb_interface.h"

+#include "adb_winusb_endpoint_object.h"

+

+AdbWinUsbInterfaceObject::AdbWinUsbInterfaceObject(const wchar_t* interf_name)

+    : AdbInterfaceObject(interf_name),

+      usb_device_handle_(INVALID_HANDLE_VALUE),

+      winusb_handle_(NULL),

+      interface_number_(0xFF),

+      def_read_endpoint_(0xFF),

+      read_endpoint_id_(0xFF),

+      def_write_endpoint_(0xFF),

+      write_endpoint_id_(0xFF) {

+}

+

+AdbWinUsbInterfaceObject::~AdbWinUsbInterfaceObject() {

+  ATLASSERT(NULL == winusb_handle_);

+  ATLASSERT(INVALID_HANDLE_VALUE == usb_device_handle_);

+}

+

+ADBAPIHANDLE AdbWinUsbInterfaceObject::CreateHandle() {

+  // Open USB device for this inteface Note that WinUsb API

+  // requires the handle to be opened for overlapped I/O.

+  usb_device_handle_ = CreateFile(interface_name().c_str(),

+                                  GENERIC_READ | GENERIC_WRITE,

+                                  FILE_SHARE_READ | FILE_SHARE_WRITE,

+                                  NULL, OPEN_EXISTING,

+                                  FILE_FLAG_OVERLAPPED, NULL);

+  if (INVALID_HANDLE_VALUE == usb_device_handle_)

+    return NULL;

+

+  // Initialize WinUSB API for this interface

+  if (!WinUsb_Initialize(usb_device_handle_, &winusb_handle_))

+    return NULL;

+

+  // Cache current interface number that will be used in

+  // WinUsb_Xxx calls performed on this interface.

+  if (!WinUsb_GetCurrentAlternateSetting(winusb_handle(), &interface_number_))

+    return false;

+

+  // Cache interface properties

+  unsigned long bytes_written;

+

+  // Cache USB device descriptor

+  if (!WinUsb_GetDescriptor(winusb_handle(), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0,

+                            reinterpret_cast<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;

+}

diff --git a/host/windows/usb/api/adb_winusb_interface.h b/host/windows/usb/api/adb_winusb_interface.h
new file mode 100755
index 0000000..82f7f89
--- /dev/null
+++ b/host/windows/usb/api/adb_winusb_interface.h
@@ -0,0 +1,186 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+#ifndef ANDROID_USB_API_ADB_WINUSB_INTERFACE_H__

+#define ANDROID_USB_API_ADB_WINUSB_INTERFACE_H__

+/** \file

+  This file consists of declaration of class AdbWinUsbInterfaceObject

+  that encapsulates an interface on our USB device that is accessible

+  via WinUsb API.

+*/

+

+#include "adb_interface.h"

+

+/** \brief Encapsulates an interface on our USB device that is accessible

+  via WinUsb API.

+*/

+class AdbWinUsbInterfaceObject : public AdbInterfaceObject {

+ public:

+  /** \brief Constructs the object.

+

+    @param[in] interf_name Name of the interface

+  */

+  explicit AdbWinUsbInterfaceObject(const wchar_t* interf_name);

+

+ protected:

+  /** \brief Destructs the object.

+

+   We hide destructor in order to prevent ourseves from accidentaly allocating

+   instances on the stack. If such attemp occur, compiler will error.

+  */

+  virtual ~AdbWinUsbInterfaceObject();

+

+  //

+  // Virtual overrides

+  //

+

+ public:

+  /** \brief Creates handle to this object.

+

+    In this call a handle for this object is generated and object is added

+    to the AdbObjectHandleMap. We override this method in order to initialize

+    WinUsb API for the given interface.

+    @return A handle to this object on success or NULL on an error.

+            If NULL is returned GetLastError() provides extended error

+            information. ERROR_GEN_FAILURE is set if an attempt was

+            made to create already opened object.

+  */

+  virtual ADBAPIHANDLE CreateHandle();

+

+  /** \brief This method is called when handle to this object gets closed.

+

+    In this call object is deleted from the AdbObjectHandleMap. We override

+    this method in order close WinUsb handle created in CreateHandle method

+    of this class.

+    @return true on success or false if object is already closed. If

+            false is returned GetLastError() provides extended error

+            information.

+  */

+  virtual bool CloseHandle();

+

+  //

+  // Abstract overrides

+  //

+

+ public:

+  /** \brief Gets serial number for interface's device.

+

+    @param[out] buffer Buffer for the serail number string. Can be NULL in

+           which case buffer_char_size will contain number of characters

+           required for the string.

+    @param[in,out] buffer_char_size On the way in supplies size (in characters)

+           of the buffer. On the way out, if method failed and GetLastError

+           reports ERROR_INSUFFICIENT_BUFFER, will contain number of characters

+           required for the name.

+    @param[in] ansi If true the name will be returned as single character

+           string. Otherwise name will be returned as wide character string.

+    @return true on success, false on failure. If false is returned

+            GetLastError() provides extended error information.

+  */

+  virtual bool GetSerialNumber(void* buffer,

+                               unsigned long* buffer_char_size,

+                               bool ansi);

+

+  /** \brief Gets information about an endpoint on this interface.

+

+    @param[in] endpoint_index Zero-based endpoint index. There are two

+           shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX

+           and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide infor about

+           (default?) bulk write and read endpoints respectively.

+    @param[out] info Upon successful completion will have endpoint information.

+    @return true on success, false on failure. If false is returned

+            GetLastError() provides extended error information.

+  */

+  virtual bool GetEndpointInformation(UCHAR endpoint_index,

+                                      AdbEndpointInformation* info);

+

+  /** \brief Opens an endpoint on this interface.

+

+    @param[in] endpoint_index Zero-based endpoint index. There are two

+           shortcuts for this parameter: ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX

+           and ADB_QUERY_BULK_READ_ENDPOINT_INDEX that provide infor about

+           (default?) bulk write and read endpoints respectively.

+    @param[in] access_type Desired access type. In the current implementation

+           this parameter has no effect on the way endpoint is opened. It's

+           always read / write access.

+    @param[in] sharing_mode Desired share mode. In the current implementation

+           this parameter has no effect on the way endpoint is opened. It's

+           always shared for read / write.

+    @return Handle to the opened endpoint object or NULL on failure.

+            If NULL is returned GetLastError() provides extended information

+            about the error that occurred.

+  */

+  virtual ADBAPIHANDLE OpenEndpoint(UCHAR endpoint_index,

+                                    AdbOpenAccessType access_type,

+                                    AdbOpenSharingMode sharing_mode);

+

+  //

+  // Operations

+  //

+

+ protected:

+  /** \brief Opens an endpoint on this interface.

+

+    @param[in] endpoint_id Endpoint (pipe) address on the device.

+    @param[in] endpoint_index Zero-based endpoint index.

+    @return Handle to the opened endpoint object or NULL on failure.

+            If NULL is returned GetLastError() provides extended information

+            about the error that occurred.

+  */

+  ADBAPIHANDLE OpenEndpoint(UCHAR endpoint_id, UCHAR endpoint_index);

+

+ public:

+  /// Gets handle to the USB device

+  HANDLE usb_device_handle() const {

+    return usb_device_handle_;

+  }

+

+  /// Gets interface handle used by WinUSB API

+  WINUSB_INTERFACE_HANDLE winusb_handle() const {

+    return winusb_handle_;

+  }

+

+  /// Gets current interface number.

+  UCHAR interface_number() const {

+    return interface_number_;

+  }

+

+ protected:

+  /// Handle to the USB device

+  HANDLE                        usb_device_handle_;

+

+  /// Interface handle used by WinUSB API

+  WINUSB_INTERFACE_HANDLE       winusb_handle_;

+

+  /// Current interface number. This value is obtained via call to

+  /// WinUsb_GetCurrentAlternateSetting and is used in WinUsb_Xxx

+  /// calls that require interface number.

+  UCHAR                         interface_number_;

+

+  /// Index for the default bulk read endpoint

+  UCHAR                         def_read_endpoint_;

+

+  /// ID for the default bulk read endpoint

+  UCHAR                         read_endpoint_id_;

+

+  /// Index for the default bulk write endpoint

+  UCHAR                         def_write_endpoint_;

+

+  /// ID for the default bulk write endpoint

+  UCHAR                         write_endpoint_id_;

+};

+

+#endif  // ANDROID_USB_API_ADB_WINUSB_INTERFACE_H__

diff --git a/host/windows/usb/api/adb_winusb_io_completion.cpp b/host/windows/usb/api/adb_winusb_io_completion.cpp
new file mode 100755
index 0000000..baeb7bb
--- /dev/null
+++ b/host/windows/usb/api/adb_winusb_io_completion.cpp
@@ -0,0 +1,87 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+/** \file

+  This file consists of implementation of class AdbWinUsbIOCompletion that

+  encapsulates a wrapper around OVERLAPPED Win32 structure returned from

+  asynchronous I/O requests issued via WinUsb API.

+*/

+

+#include "stdafx.h"

+#include "adb_winusb_io_completion.h"

+

+AdbWinUsbIOCompletion::AdbWinUsbIOCompletion(

+    AdbWinUsbEndpointObject* parent_io_obj,

+    ULONG expected_trans_size,

+    HANDLE event_hndl)

+    : AdbIOCompletion(parent_io_obj, expected_trans_size, event_hndl) {

+}

+

+AdbWinUsbIOCompletion::~AdbWinUsbIOCompletion() {

+}

+

+bool AdbWinUsbIOCompletion::GetOvelappedIoResult(LPOVERLAPPED ovl_data,

+                                                 ULONG* bytes_transferred,

+                                                 bool wait) {

+  if (NULL != bytes_transferred) {

+    *bytes_transferred = 0;

+  }

+

+  if (!IsOpened()) {

+    SetLastError(ERROR_INVALID_HANDLE);

+    return false;

+  }

+

+  ULONG transfer;

+  bool ret = WinUsb_GetOverlappedResult(

+                  parent_winusb_io_object()->winusb_handle(),

+                  overlapped(),

+                  &transfer,

+                  wait ? TRUE : FALSE) ? true : false;

+

+  // TODO: This is bizzare but I've seen it happening

+  // that GetOverlappedResult with wait set to true returns "prematurely",

+  // with wrong transferred bytes value and GetLastError reporting

+  // ERROR_IO_PENDING. So, lets give it an up to a 20 ms loop!

+  ULONG error = GetLastError();

+

+  if (wait && ret && (0 == transfer) && (0 != expected_transfer_size_) &&

+      ((ERROR_IO_INCOMPLETE == error) || (ERROR_IO_PENDING == error))) {

+    for (int trying = 0; trying < 10; trying++) {

+      Sleep(2);

+      ret = WinUsb_GetOverlappedResult(

+                parent_winusb_io_object()->winusb_handle(),

+                overlapped(),

+                &transfer,

+                wait ? TRUE : FALSE) ? true : false;

+      error = GetLastError();

+      if (!ret || (0 != transfer) ||

+          ((ERROR_IO_INCOMPLETE != error) && (ERROR_IO_PENDING != error))) {

+        break;

+      }

+    }

+  }

+

+  if (NULL != ovl_data) {

+    CopyMemory(ovl_data, overlapped(), sizeof(OVERLAPPED));

+  }

+

+  if (NULL != bytes_transferred) {

+    *bytes_transferred = transfer;

+  }

+

+  return ret;

+}

diff --git a/host/windows/usb/api/adb_winusb_io_completion.h b/host/windows/usb/api/adb_winusb_io_completion.h
new file mode 100755
index 0000000..a97a3a8
--- /dev/null
+++ b/host/windows/usb/api/adb_winusb_io_completion.h
@@ -0,0 +1,94 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+#ifndef ANDROID_USB_API_ADB_WINUSB_IO_COMPLETION_H__

+#define ANDROID_USB_API_ADB_WINUSB_IO_COMPLETION_H__

+/** \file

+  This file consists of declaration of class AdbWinUsbIOCompletion that

+  encapsulates a wrapper around OVERLAPPED Win32 structure returned from

+  asynchronous I/O requests issued via WinUsb API.

+*/

+

+#include "adb_io_completion.h"

+#include "adb_winusb_endpoint_object.h"

+

+/** \brief Encapsulates encapsulates a wrapper around OVERLAPPED Win32

+  structure returned from asynchronous I/O requests issued via WinUsb API.

+

+  A handle to this object is returned to the caller of each successful

+  asynchronous I/O request. Just like all other handles this handle

+  must be closed after it's no longer needed.

+*/

+class AdbWinUsbIOCompletion : public AdbIOCompletion {

+ public:

+  /** \brief Constructs the object

+

+    @param[in] parent_io_obj Parent WinUsb I/O object that created this

+           instance.

+    @param[in] expected_trans_size Number of bytes expected to be transferred

+          with the I/O.

+    @param[in] event_hndl Event handle that should be signaled when I/O

+           completes. Can be NULL. If it's not NULL this handle will be

+           used to initialize OVERLAPPED structure for this object.

+  */

+  AdbWinUsbIOCompletion(AdbWinUsbEndpointObject* parent_io_obj,

+                        ULONG expected_trans_size,

+                        HANDLE event_hndl);

+

+ protected:

+  /** \brief Destructs the object.

+

+    We hide destructor in order to prevent ourseves from accidentaly allocating

+    instances on the stack. If such attemp occur, compiler will error.

+  */

+  virtual ~AdbWinUsbIOCompletion();

+

+  //

+  // Abstract overrides

+  //

+

+ public:

+  /** \brief Gets overlapped I/O result

+

+    This method uses WinUsb_GetOverlappedResult to get results of the

+    overlapped I/O operation.

+    @param[out] ovl_data Buffer for the copy of this object's OVERLAPPED

+           structure. Can be NULL.

+    @param[out] bytes_transferred Pointer to a variable that receives the

+           number of bytes that were actually transferred by a read or write

+           operation. See SDK doc on GetOvelappedResult for more information.

+           Unlike regular GetOvelappedResult call this parameter can be NULL.

+    @param[in] wait If this parameter is true, the method does not return

+           until the operation has been completed. If this parameter is false

+           and the operation is still pending, the method returns false and

+           the GetLastError function returns ERROR_IO_INCOMPLETE.

+    @return true if I/O has been completed or false on failure or if request

+           is not yet completed. If false is returned GetLastError() provides

+           extended error information. If GetLastError returns

+           ERROR_IO_INCOMPLETE it means that I/O is not yet completed.

+  */

+  virtual bool GetOvelappedIoResult(LPOVERLAPPED ovl_data,

+                                    ULONG* bytes_transferred,

+                                    bool wait);

+

+ public:

+  /// Gets WinUsb parent object

+  AdbWinUsbEndpointObject* parent_winusb_io_object() const {

+    return reinterpret_cast<AdbWinUsbEndpointObject*>(parent_io_object());

+  }

+};

+

+#endif  // ANDROID_USB_API_ADB_WINUSB_IO_COMPLETION_H__