Add classes encapsulatinglegacy USB API

Added implementation for endpoints and overlapped I/O support for legacy API support.
diff --git a/host/windows/usb/api/SOURCES b/host/windows/usb/api/SOURCES
index 4b9d360..f6e6614 100755
--- a/host/windows/usb/api/SOURCES
+++ b/host/windows/usb/api/SOURCES
@@ -88,6 +88,7 @@
 SOURCES = adb_api.cpp                     \

           adb_endpoint_object.cpp         \

           adb_winusb_endpoint_object.cpp  \

+          adb_legacy_endpoint_object.cpp  \

           adb_helper_routines.cpp         \

           adb_interface.cpp               \

           adb_winusb_interface.cpp        \

@@ -95,6 +96,7 @@
           adb_interface_enum.cpp          \

           adb_io_completion.cpp           \

           adb_winusb_io_completion.cpp    \

+          adb_legacy_io_completion.cpp    \

           adb_object_handle.cpp           \

           AdbWinApi.cpp                   \

 		      AdbWinApi.rc

diff --git a/host/windows/usb/api/adb_helper_routines.cpp b/host/windows/usb/api/adb_helper_routines.cpp
index 9e37380..e45ff91 100644
--- a/host/windows/usb/api/adb_helper_routines.cpp
+++ b/host/windows/usb/api/adb_helper_routines.cpp
@@ -1,5 +1,5 @@
 /*

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

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

  *

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

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

@@ -25,6 +25,61 @@
 #include "adb_helper_routines.h"

 #include "adb_interface_enum.h"

 

+bool GetSDKComplientParam(AdbOpenAccessType access_type,

+                          AdbOpenSharingMode sharing_mode,

+                          ULONG* desired_access,

+                          ULONG* desired_sharing) {

+  if (NULL != desired_access) {

+    switch (access_type) {

+      case AdbOpenAccessTypeReadWrite:

+        *desired_access = GENERIC_READ | GENERIC_WRITE;

+        break;

+

+      case AdbOpenAccessTypeRead:

+        *desired_access = GENERIC_READ;

+        break;

+

+      case AdbOpenAccessTypeWrite:

+        *desired_access = GENERIC_WRITE;

+        break;

+

+      case AdbOpenAccessTypeQueryInfo:

+        *desired_access = FILE_READ_ATTRIBUTES | FILE_READ_EA;

+        break;

+

+      default:

+        SetLastError(ERROR_INVALID_ACCESS);

+        return false;

+    }

+  }

+

+  if (NULL != desired_sharing) {

+    switch (sharing_mode) {

+      case AdbOpenSharingModeReadWrite:

+        *desired_sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;

+        break;

+

+      case AdbOpenSharingModeRead:

+        *desired_sharing = FILE_SHARE_READ;

+        break;

+

+      case AdbOpenSharingModeWrite:

+        *desired_sharing = FILE_SHARE_WRITE;

+        break;

+

+      case AdbOpenSharingModeExclusive:

+        *desired_sharing = 0;

+        break;

+

+      default:

+        SetLastError(ERROR_INVALID_PARAMETER);

+        return false;

+    }

+  }

+

+  return true;

+}

+

 bool EnumerateDeviceInterfaces(HDEVINFO hardware_dev_info,

                                GUID class_id,

                                bool exclude_removed,

diff --git a/host/windows/usb/api/adb_helper_routines.h b/host/windows/usb/api/adb_helper_routines.h
index 907e638..b6885e4 100644
--- a/host/windows/usb/api/adb_helper_routines.h
+++ b/host/windows/usb/api/adb_helper_routines.h
@@ -1,5 +1,5 @@
 /*

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

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

  *

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

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

@@ -23,6 +23,23 @@
 

 #include "adb_api_private_defines.h"

 

+/** \brief Converts access type and share mode from our enum into

+  SDK - complient values.

+

+  @param[in] access_type Enumerated access type

+  @param[in] sharing_mode Enumerated share mode

+  @param[out] desired_access Will receive SDK - complient desired access

+         flags. This parameter can be NULL.

+  @param[out] desired_sharing Will receive SDK - complient share mode.

+         This parameter can be NULL.

+  @return True on success, false on failure, in which case GetLastError()

+          provides extended information about the error that occurred.

+*/

+bool GetSDKComplientParam(AdbOpenAccessType access_type,

+                          AdbOpenSharingMode sharing_mode,

+                          ULONG* desired_access,

+                          ULONG* desired_sharing);

+

 /** \brief Given the hardware device information enumerates interfaces for

   this device.

 

diff --git a/host/windows/usb/api/adb_legacy_endpoint_object.cpp b/host/windows/usb/api/adb_legacy_endpoint_object.cpp
new file mode 100755
index 0000000..2baa53b
--- /dev/null
+++ b/host/windows/usb/api/adb_legacy_endpoint_object.cpp
@@ -0,0 +1,237 @@
+/*

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

+ *

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

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

+ * You may obtain a copy of the License at

+ *

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

+ *

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

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

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

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

+ * limitations under the License.

+ */

+

+/** \file

+  This file consists of implementation of class AdbLegacyEndpointObject that

+  encapsulates a handle opened to an endpoint on our device controlled by

+  a custom (legacy) USB driver.

+*/

+

+#include "stdafx.h"

+#include "adb_api_legacy.h"

+#include "adb_legacy_endpoint_object.h"

+#include "adb_legacy_io_completion.h"

+#include "adb_helper_routines.h"

+

+AdbLegacyEndpointObject::AdbLegacyEndpointObject(

+    AdbLegacyInterfaceObject* parent_interf,

+    UCHAR endpoint_id,

+    UCHAR endpoint_index)

+    : AdbEndpointObject(parent_interf, endpoint_id, endpoint_index),

+      usb_handle_(INVALID_HANDLE_VALUE) {

+}

+

+AdbLegacyEndpointObject::~AdbLegacyEndpointObject() {

+  if (INVALID_HANDLE_VALUE != usb_handle_) {

+    ::CloseHandle(usb_handle_);

+  }

+}

+

+ADBAPIHANDLE AdbLegacyEndpointObject::CommonAsyncReadWrite(

+    bool is_read,

+    void* buffer,

+    ULONG bytes_to_transfer,

+    ULONG* bytes_transferred,

+    HANDLE event_handle,

+    ULONG time_out) {

+  if (NULL != bytes_transferred) {

+    *bytes_transferred = 0;

+  }

+

+  if (!IsOpened()) {

+    SetLastError(ERROR_INVALID_HANDLE);

+    return false;

+  }

+

+  bool is_ioctl_write = is_read ? false : (0 != time_out);

+

+  // Create completion i/o object

+  AdbLegacyIOCompletion* adb_io_completion = NULL;

+

+  try {

+    adb_io_completion = new AdbLegacyIOCompletion(this,

+                                                  bytes_to_transfer,

+                                                  event_handle,

+                                                  is_ioctl_write);

+  } catch (... ) {

+    // We don't expect exceptions other than OOM thrown here.

+    SetLastError(ERROR_OUTOFMEMORY);

+    return NULL;

+  }

+

+  // Create a handle for it

+  ADBAPIHANDLE ret = adb_io_completion->CreateHandle();

+  ULONG transferred = 0;

+  if (NULL != ret) {

+    BOOL res = TRUE;

+    if (0 == time_out) {

+      // Go the read / write file way

+      res = is_read ? ReadFile(usb_handle(),

+                               buffer,

+                               bytes_to_transfer,

+                               &transferred,

+                               adb_io_completion->overlapped()) :

+                      WriteFile(usb_handle(),

+                                buffer,

+                                bytes_to_transfer,

+                                &transferred,

+                                adb_io_completion->overlapped());

+    } else {

+      // Go IOCTL way

+      AdbBulkTransfer transfer_param;

+      transfer_param.time_out = time_out;

+      transfer_param.transfer_size = is_read ? 0 : bytes_to_transfer;

+      transfer_param.SetWriteBuffer(is_read ? NULL : buffer);

+

+      res = DeviceIoControl(usb_handle(),

+        is_read ? ADB_IOCTL_BULK_READ : ADB_IOCTL_BULK_WRITE,

+        &transfer_param, sizeof(transfer_param),

+        is_read ? buffer : adb_io_completion->transferred_bytes_ptr(),

+        is_read ? bytes_to_transfer : sizeof(ULONG),

+        &transferred,

+        adb_io_completion->overlapped());

+    }

+

+    if (NULL != bytes_transferred) {

+      *bytes_transferred = transferred;

+    }

+

+    ULONG error = GetLastError();

+    if (!res && (ERROR_IO_PENDING != error)) {

+      // I/O failed immediatelly. We need to close i/o completion object

+      // before we return NULL to the caller.

+      adb_io_completion->CloseHandle();

+      ret = NULL;

+      SetLastError(error);

+    }

+  }

+

+  // Offseting 'new'

+  adb_io_completion->Release();

+

+  return ret;

+}

+

+bool AdbLegacyEndpointObject::CommonSyncReadWrite(bool is_read,

+                                                  void* buffer,

+                                                  ULONG bytes_to_transfer,

+                                                  ULONG* bytes_transferred,

+                                                  ULONG time_out) {

+  if (NULL != bytes_transferred) {

+    *bytes_transferred = 0;

+  }

+

+  if (!IsOpened()) {

+    SetLastError(ERROR_INVALID_HANDLE);

+    return false;

+  }

+

+  bool is_ioctl_write = is_read ? false : (0 != time_out);

+

+  // This is synchronous I/O. Since we always open I/O items for

+  // overlapped I/O we're obligated to always provide OVERLAPPED

+  // structure to read / write routines. Prepare it now.

+  OVERLAPPED overlapped;

+  ZeroMemory(&overlapped, sizeof(overlapped));

+

+  BOOL ret = TRUE;

+  ULONG ioctl_write_transferred = 0;

+  if (0 == time_out) {

+    // Go the read / write file way

+    ret = is_read ?

+      ReadFile(usb_handle(), buffer, bytes_to_transfer, bytes_transferred, &overlapped) :

+      WriteFile(usb_handle(), buffer, bytes_to_transfer, bytes_transferred, &overlapped);

+  } else {

+    // Go IOCTL way

+    AdbBulkTransfer transfer_param;

+    transfer_param.time_out = time_out;

+    transfer_param.transfer_size = is_read ? 0 : bytes_to_transfer;

+    transfer_param.SetWriteBuffer(is_read ? NULL : buffer);

+

+    ULONG tmp;

+    ret = DeviceIoControl(usb_handle(),

+      is_read ? ADB_IOCTL_BULK_READ : ADB_IOCTL_BULK_WRITE,

+      &transfer_param, sizeof(transfer_param),

+      is_read ? buffer : &ioctl_write_transferred,

+      is_read ? bytes_to_transfer : sizeof(ULONG),

+      &tmp,

+      &overlapped);

+  }

+

+  // Lets see the result

+  if (!ret && (ERROR_IO_PENDING != GetLastError())) {

+    // I/O failed.

+    return false;

+  }

+

+  // Lets wait till I/O completes

+  ULONG transferred = 0;

+  ret = GetOverlappedResult(usb_handle(), &overlapped, &transferred, TRUE);

+  if (ret && (NULL != bytes_transferred)) {

+    *bytes_transferred = is_ioctl_write ? ioctl_write_transferred :

+                                          transferred;

+  }

+

+  return ret ? true : false;

+}

+

+ADBAPIHANDLE AdbLegacyEndpointObject::CreateHandle(

+    const wchar_t* item_path,

+    AdbOpenAccessType access_type,

+    AdbOpenSharingMode share_mode) {

+  // Convert access / share parameters into CreateFile - compatible

+  ULONG desired_access;

+  ULONG desired_sharing;

+

+  if (!GetSDKComplientParam(access_type, share_mode,

+                            &desired_access, &desired_sharing)) {

+    return NULL;

+  }

+

+  // Open USB handle

+  usb_handle_ = CreateFile(item_path,

+                           desired_access,

+                           share_mode,

+                           NULL,

+                           OPEN_EXISTING,

+                           FILE_FLAG_OVERLAPPED,  // Always overlapped!

+                           NULL);

+  if (INVALID_HANDLE_VALUE == usb_handle_) {

+    return NULL;

+  }

+

+  // Create ADB handle

+  ADBAPIHANDLE ret = AdbObjectHandle::CreateHandle();

+

+  if (NULL == ret) {

+    // If creation of ADB handle failed we have to close USB handle too.

+    ULONG error = GetLastError();

+    ::CloseHandle(usb_handle());

+    usb_handle_ = INVALID_HANDLE_VALUE;

+    SetLastError(error);

+  }

+

+  return ret;

+}

+

+bool AdbLegacyEndpointObject::CloseHandle() {

+  if (INVALID_HANDLE_VALUE != usb_handle_) {

+    ::CloseHandle(usb_handle_);

+    usb_handle_ = INVALID_HANDLE_VALUE;

+  }

+

+  return AdbEndpointObject::CloseHandle();

+}

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

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

+ *

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

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

+ * You may obtain a copy of the License at

+ *

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

+ *

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

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

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

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

+ * limitations under the License.

+ */

+

+#ifndef ANDROID_USB_API_ADB_LEGACY_ENDPOINT_OBJECT_H__

+#define ANDROID_USB_API_ADB_LEGACY_ENDPOINT_OBJECT_H__

+/** \file

+  This file consists of declaration of class AdbLegacyEndpointObject that

+  encapsulates a handle opened to an endpoint on our device controlled by

+  a custom (legacy) USB driver.

+*/

+

+#include "adb_endpoint_object.h"

+#include "adb_legacy_interface.h"

+

+/** Encapsulates a handle opened to an endpoint on our device controlled by

+  a custom (legacy) USB driver.

+*/

+class AdbLegacyEndpointObject : public AdbEndpointObject {

+ public:

+  /** \brief Constructs the object

+

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

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

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

+          array of endpoints.

+  */

+  AdbLegacyEndpointObject(AdbLegacyInterfaceObject* parent_interf,

+                          UCHAR endpoint_id,

+                          UCHAR endpoint_index);

+

+ protected:

+  /** \brief Destructs the object.

+

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

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

+  */

+  virtual ~AdbLegacyEndpointObject();

+

+  //

+  // Abstract overrides

+  //

+

+ protected:

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

+

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

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

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

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

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

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

+           initialize OVERLAPPED structure for this I/O.

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

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

+           timeout set for this I/O.

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

+            returned GetLastError() provides extended error information.

+  */

+  virtual ADBAPIHANDLE CommonAsyncReadWrite(bool is_read,

+                                            void* buffer,

+                                            ULONG bytes_to_transfer,

+                                            ULONG* bytes_transferred,

+                                            HANDLE event_handle,

+                                            ULONG time_out);

+

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

+

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

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

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

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

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

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

+           timeout set for this I/O.

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

+            GetLastError() provides extended error information.

+  */

+  virtual bool CommonSyncReadWrite(bool is_read,

+                                   void* buffer,

+                                   ULONG bytes_to_transfer,

+                                   ULONG* bytes_transferred,

+                                   ULONG time_out);

+

+  //

+  // Operations

+  //

+

+ public:

+  /** \brief Opens endpoint and creates a handle to this object

+

+    @param item_path[in] Path to the endpoint on our USB device.

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

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

+          always read / write access.

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

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

+          always shared for read / write.

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

+            If NULL is returned GetLastError() provides extended error

+            information. ERROR_GEN_FAILURE is set if an attempt was

+            made to create already opened object.

+  */

+  virtual ADBAPIHANDLE CreateHandle(const wchar_t* item_path,

+                                    AdbOpenAccessType access_type,

+                                    AdbOpenSharingMode share_mode);

+

+

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

+

+    We override this method in order to close handle to the endpoint opened

+    in CreateHandle method of this class.

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

+            false is returned GetLastError() provides extended error

+            information.

+  */

+  virtual bool CloseHandle();

+

+ public:

+  /// Gets handle to the endpoint opened on our USB device.

+  HANDLE usb_handle() const {

+    return usb_handle_;

+  }

+

+ protected:

+  /// Handle to the endpoint opened on our USB device.

+  HANDLE              usb_handle_;

+};

+

+#endif  // ANDROID_USB_API_ADB_LEGACY_ENDPOINT_OBJECT_H__

diff --git a/host/windows/usb/api/adb_legacy_interface.cpp b/host/windows/usb/api/adb_legacy_interface.cpp
index 95c750e..9eab9bd 100755
--- a/host/windows/usb/api/adb_legacy_interface.cpp
+++ b/host/windows/usb/api/adb_legacy_interface.cpp
@@ -17,48 +17,308 @@
 /** \file

   This file consists of implementation of class AdbLegacyInterfaceObject

   that encapsulates an interface on our USB device that is accessible

-  via WinUsb API.

 */

 

 #include "stdafx.h"

+#include "adb_api_legacy.h"

 #include "adb_legacy_interface.h"

-#include "adb_endpoint_object.h"

+#include "adb_legacy_endpoint_object.h"

 

 AdbLegacyInterfaceObject::AdbLegacyInterfaceObject(const wchar_t* interf_name)

-  : AdbInterfaceObject(interf_name) {

+    : AdbInterfaceObject(interf_name),

+      def_read_endpoint_(0xFF),

+      read_endpoint_id_(0xFF),

+      def_write_endpoint_(0xFF),

+      write_endpoint_id_(0xFF) {

 }

 

 AdbLegacyInterfaceObject::~AdbLegacyInterfaceObject() {

 }

 

 ADBAPIHANDLE AdbLegacyInterfaceObject::CreateHandle() {

-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

-  return NULL;

-}

+  // Open USB device for this intefface

+  HANDLE usb_device_handle = CreateFile(interface_name().c_str(),

+                                        GENERIC_READ | GENERIC_WRITE,

+                                        FILE_SHARE_READ | FILE_SHARE_WRITE,

+                                        NULL,

+                                        OPEN_EXISTING,

+                                        0,

+                                        NULL);

+  if (INVALID_HANDLE_VALUE == usb_device_handle) {

+    return NULL;

+  }

 

-bool AdbLegacyInterfaceObject::CloseHandle() {

-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

-  return false;

+  // Now, we ensured that our usb device / interface is up and running.

+  // Lets collect device, interface and pipe information

+  bool ok = true;

+  if (!CacheUsbDeviceDescriptor(usb_device_handle) ||

+      !CacheUsbConfigurationDescriptor(usb_device_handle) ||

+      !CacheUsbInterfaceDescriptor(usb_device_handle)) {

+    ok = false;

+  }

+

+  // Preserve error accross handle close

+  ULONG error = ok ? NO_ERROR : GetLastError();

+

+  ::CloseHandle(usb_device_handle);

+

+  if (NO_ERROR != error) {

+    SetLastError(error);

+  }

+

+  if (!ok) {

+    return false;

+  }

+

+  // Save indexes and IDs for bulk read / write endpoints. We will use them to

+  // convert ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX and

+  // ADB_QUERY_BULK_READ_ENDPOINT_INDEX into actual endpoint indexes and IDs.

+  for (UCHAR endpoint = 0; endpoint < usb_interface_descriptor_.bNumEndpoints;

+       endpoint++) {

+    // Get endpoint information

+    AdbEndpointInformation pipe_info;

+    if (!GetEndpointInformation(endpoint, &pipe_info)) {

+      return false;

+    }

+

+    if (AdbEndpointTypeBulk == pipe_info.endpoint_type) {

+      // This is a bulk endpoint. Cache its index and ID.

+      if (0 != (pipe_info.endpoint_address & USB_ENDPOINT_DIRECTION_MASK)) {

+        // Use this endpoint as default bulk read endpoint

+        ATLASSERT(0xFF == def_read_endpoint_);

+        def_read_endpoint_ = endpoint;

+        read_endpoint_id_ = pipe_info.endpoint_address;

+      } else {

+        // Use this endpoint as default bulk write endpoint

+        ATLASSERT(0xFF == def_write_endpoint_);

+        def_write_endpoint_ = endpoint;

+        write_endpoint_id_ = pipe_info.endpoint_address;

+      }

+    }

+  }

+

+  return AdbObjectHandle::CreateHandle();

 }

 

 bool AdbLegacyInterfaceObject::GetSerialNumber(void* buffer,

                                                unsigned long* buffer_char_size,

                                                bool ansi) {

-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

-  return false;

+  if (!IsOpened()) {

+    SetLastError(ERROR_INVALID_HANDLE);

+    return false;

+  }

+

+  // Open USB device for this intefface

+  HANDLE usb_device_handle = CreateFile(interface_name().c_str(),

+                                        GENERIC_READ,

+                                        FILE_SHARE_READ | FILE_SHARE_WRITE,

+                                        NULL,

+                                        OPEN_EXISTING,

+                                        0,

+                                        NULL);

+  if (INVALID_HANDLE_VALUE == usb_device_handle) {

+    return NULL;

+  }

+

+  WCHAR serial_number[512];

+

+  // Send IOCTL

+  DWORD ret_bytes = 0;

+  BOOL ret = DeviceIoControl(usb_device_handle,

+                             ADB_IOCTL_GET_SERIAL_NUMBER,

+                             NULL, 0,

+                             serial_number, sizeof(serial_number),

+                             &ret_bytes,

+                             NULL);

+

+  // Preserve error accross CloseHandle

+  ULONG error = ret ? NO_ERROR : GetLastError();

+

+  ::CloseHandle(usb_device_handle);

+

+  if (NO_ERROR != error) {

+    SetLastError(error);

+    return false;

+  }

+

+  unsigned long str_len =

+    static_cast<unsigned long>(wcslen(serial_number) + 1);

+

+  if ((NULL == buffer) || (*buffer_char_size < str_len)) {

+    *buffer_char_size = str_len;

+    SetLastError(ERROR_INSUFFICIENT_BUFFER);

+    return false;

+  }

+

+  if (!ansi) {

+    // If user asked for wide char name just return it

+    wcscpy(reinterpret_cast<wchar_t*>(buffer), serial_number);

+    return true;

+  }

+

+  // We need to convert name from wide char to ansi string

+  int res = WideCharToMultiByte(CP_ACP,

+                                0,

+                                serial_number,

+                                static_cast<int>(str_len),

+                                reinterpret_cast<PSTR>(buffer),

+                                static_cast<int>(*buffer_char_size),

+                                NULL,

+                                NULL);

+  return (res != 0);

 }

 

 bool AdbLegacyInterfaceObject::GetEndpointInformation(

     UCHAR endpoint_index,

     AdbEndpointInformation* info) {

-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

-  return false;

+  // Open USB device for this intefface

+  HANDLE usb_device_handle = CreateFile(interface_name().c_str(),

+                                        GENERIC_READ,

+                                        FILE_SHARE_READ | FILE_SHARE_WRITE,

+                                        NULL,

+                                        OPEN_EXISTING,

+                                        0,

+                                        NULL);

+  if (INVALID_HANDLE_VALUE == usb_device_handle) {

+    return NULL;

+  }

+

+  // Init ICTL param

+  AdbQueryEndpointInformation param;

+  param.endpoint_index = endpoint_index;

+

+  // Send IOCTL

+  DWORD ret_bytes = 0;

+  BOOL ret = DeviceIoControl(usb_device_handle,

+                             ADB_IOCTL_GET_ENDPOINT_INFORMATION,

+                             &param, sizeof(param),

+                             info, sizeof(AdbEndpointInformation),

+                             &ret_bytes,

+                             NULL);

+  ATLASSERT(!ret || (sizeof(AdbEndpointInformation) == ret_bytes));

+

+  // Preserve error accross CloseHandle

+  ULONG error = ret ? NO_ERROR : GetLastError();

+

+  ::CloseHandle(usb_device_handle);

+

+  if (NO_ERROR != error) {

+    SetLastError(error);

+  }

+

+  return ret ? true : false;

 }

 

 ADBAPIHANDLE AdbLegacyInterfaceObject::OpenEndpoint(

     UCHAR endpoint_index,

     AdbOpenAccessType access_type,

     AdbOpenSharingMode sharing_mode) {

-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);

-  return NULL;

+  // Convert index into name and ID.

+  std::wstring endpoint_name;

+  UCHAR endpoint_id;

+

+  try {

+    if ((ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) ||

+        (def_read_endpoint_ == endpoint_index)) {

+      endpoint_name = DEVICE_BULK_READ_PIPE_NAME;

+      endpoint_id = read_endpoint_id_;

+      endpoint_index = def_read_endpoint_;

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

+               (def_write_endpoint_ == endpoint_index)) {

+      endpoint_name = DEVICE_BULK_WRITE_PIPE_NAME;

+      endpoint_id = write_endpoint_id_;

+      endpoint_index = def_write_endpoint_;

+    } else {

+      SetLastError(ERROR_INVALID_PARAMETER);

+      return false;

+    }

+  } catch (...) {

+    // We don't expect exceptions other than OOM thrown here.

+    SetLastError(ERROR_OUTOFMEMORY);

+    return NULL;

+  }

+

+  return OpenEndpoint(endpoint_name.c_str(), endpoint_id, endpoint_index,

+                      access_type, sharing_mode);

+}

+

+ADBAPIHANDLE AdbLegacyInterfaceObject::OpenEndpoint(

+    const wchar_t* endpoint_name,

+    UCHAR endpoint_id,

+    UCHAR endpoint_index,

+    AdbOpenAccessType access_type,

+    AdbOpenSharingMode sharing_mode) {

+  if (!IsOpened()) {

+    SetLastError(ERROR_INVALID_HANDLE);

+    return false;

+  }

+

+  AdbLegacyEndpointObject* adb_endpoint = NULL;

+

+  try {

+    adb_endpoint =

+        new AdbLegacyEndpointObject(this, endpoint_id, endpoint_index);

+  } catch (...) {

+    // We don't expect exceptions other than OOM thrown here.

+    SetLastError(ERROR_OUTOFMEMORY);

+    return NULL;

+  }

+

+  // Build full path to the object

+  std::wstring endpoint_path = interface_name();

+  endpoint_path += L"\\";

+  endpoint_path += endpoint_name;

+

+  ADBAPIHANDLE ret = adb_endpoint->CreateHandle(endpoint_path.c_str(),

+                                                access_type,

+                                                sharing_mode);

+

+  adb_endpoint->Release();

+

+  return ret;

+}

+

+bool AdbLegacyInterfaceObject::CacheUsbDeviceDescriptor(

+    HANDLE usb_device_handle) {

+  DWORD ret_bytes = 0;

+  BOOL ret = DeviceIoControl(usb_device_handle,

+                             ADB_IOCTL_GET_USB_DEVICE_DESCRIPTOR,

+                             NULL, 0,

+                             &usb_device_descriptor_,

+                             sizeof(usb_device_descriptor_),

+                             &ret_bytes,

+                             NULL);

+  ATLASSERT(!ret || (sizeof(USB_DEVICE_DESCRIPTOR) == ret_bytes));

+

+  return ret ? true : false;

+}

+

+bool AdbLegacyInterfaceObject::CacheUsbConfigurationDescriptor(

+    HANDLE usb_device_handle) {

+  DWORD ret_bytes = 0;

+  BOOL ret = DeviceIoControl(usb_device_handle,

+                             ADB_IOCTL_GET_USB_CONFIGURATION_DESCRIPTOR,

+                             NULL, 0,

+                             &usb_config_descriptor_,

+                             sizeof(usb_config_descriptor_),

+                             &ret_bytes,

+                             NULL);

+  ATLASSERT(!ret || (sizeof(USB_CONFIGURATION_DESCRIPTOR) == ret_bytes));

+

+  return ret ? true : false;

+}

+

+bool AdbLegacyInterfaceObject::CacheUsbInterfaceDescriptor(

+    HANDLE usb_device_handle) {

+  DWORD ret_bytes = 0;

+  BOOL ret = DeviceIoControl(usb_device_handle,

+                             ADB_IOCTL_GET_USB_INTERFACE_DESCRIPTOR,

+                             NULL, 0,

+                             &usb_interface_descriptor_,

+                             sizeof(usb_interface_descriptor_),

+                             &ret_bytes,

+                             NULL);

+  ATLASSERT(!ret || (sizeof(USB_INTERFACE_DESCRIPTOR) == ret_bytes));

+

+  return ret ? true : false;

 }

diff --git a/host/windows/usb/api/adb_legacy_interface.h b/host/windows/usb/api/adb_legacy_interface.h
index 6d4b0e8..8dd0b22 100755
--- a/host/windows/usb/api/adb_legacy_interface.h
+++ b/host/windows/usb/api/adb_legacy_interface.h
@@ -60,15 +60,6 @@
   */

   virtual ADBAPIHANDLE CreateHandle();

 

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

-

-    In this call object is deleted from the AdbObjectHandleMap.

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

-            false is returned GetLastError() provides extended error

-            information.

-  */

-  virtual bool CloseHandle();

-

   //

   // Abstract overrides

   //

@@ -124,6 +115,76 @@
   virtual ADBAPIHANDLE OpenEndpoint(UCHAR endpoint_index,

                                     AdbOpenAccessType access_type,

                                     AdbOpenSharingMode sharing_mode);

+

+  //

+  // Internal operations

+  //

+

+ protected:

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

+

+    @param[in] endpoint_name Endpoint file name.

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

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

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

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

+           always read / write access.

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

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

+           always shared for read / write.

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

+            If NULL is returned GetLastError() provides extended information

+            about the error that occurred.

+  */

+  ADBAPIHANDLE OpenEndpoint(const wchar_t* endpoint_name,

+                            UCHAR endpoint_id,

+                            UCHAR endpoint_index,

+                            AdbOpenAccessType access_type,

+                            AdbOpenSharingMode sharing_mode);

+

+  /** \brief Caches device descriptor for the USB device associated with

+    this interface.

+

+    This method is called from CreateHandle method to cache some interface

+    information.

+    @param[in] usb_device_handle Handle to USB device.

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

+            GetLastError() provides extended error information.

+  */

+  bool CacheUsbDeviceDescriptor(HANDLE usb_device_handle);

+

+  /** \brief Caches descriptor for the selected USB device configuration.

+

+    This method is called from CreateHandle method to cache some interface

+    information.

+    @param[in] usb_device_handle Handle to USB device.

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

+            GetLastError() provides extended error information.

+  */

+  bool CacheUsbConfigurationDescriptor(HANDLE usb_device_handle);

+

+  /** \brief Caches descriptor for this interface.

+

+    This method is called from CreateHandle method to cache some interface

+    information.

+    @param[in] usb_device_handle Handle to USB device.

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

+            GetLastError() provides extended error information.

+  */

+  bool CacheUsbInterfaceDescriptor(HANDLE usb_device_handle);

+

+ protected:

+  /// Index for the default bulk read endpoint

+  UCHAR                         def_read_endpoint_;

+

+  /// ID for the default bulk read endpoint

+  UCHAR                         read_endpoint_id_;

+

+  /// Index for the default bulk write endpoint

+  UCHAR                         def_write_endpoint_;

+

+  /// ID for the default bulk write endpoint

+  UCHAR                         write_endpoint_id_;

 };

 

 #endif  // ANDROID_USB_API_ADB_LEGACY_INTERFACE_H__

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

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

+ *

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

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

+ * You may obtain a copy of the License at

+ *

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

+ *

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

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

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

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

+ * limitations under the License.

+ */

+

+/** \file

+  This file consists of implementation of class AdbLegacyIOCompletion that

+  encapsulates a wrapper around OVERLAPPED Win32 structure returned from

+  asynchronous I/O requests issued via legacy USB API.

+*/

+

+#include "stdafx.h"

+#include "adb_legacy_io_completion.h"

+

+AdbLegacyIOCompletion::AdbLegacyIOCompletion(

+    AdbLegacyEndpointObject* parent_io_obj,

+    ULONG expected_trans_size,

+    HANDLE event_hndl,

+    bool is_write_ctl)

+    : AdbIOCompletion(parent_io_obj, expected_trans_size, event_hndl),

+      transferred_bytes_(0),

+      is_write_ioctl_(is_write_ctl) {

+}

+

+AdbLegacyIOCompletion::~AdbLegacyIOCompletion() {

+}

+

+bool AdbLegacyIOCompletion::GetOvelappedIoResult(LPOVERLAPPED ovl_data,

+                                                 ULONG* bytes_transferred,

+                                                 bool wait) {

+  if (NULL != bytes_transferred) {

+    *bytes_transferred = 0;

+  }

+

+  if (!IsOpened()) {

+    SetLastError(ERROR_INVALID_HANDLE);

+    return false;

+  }

+

+  ULONG transfer;

+  bool ret = GetOverlappedResult(parent_legacy_io_object()->usb_handle(),

+                                 overlapped(),

+                                 &transfer,

+                                 wait) ? true :

+                                         false;

+

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

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

+  // with wrong transferred bytes value and GetLastError reporting

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

+  ULONG error = GetLastError();

+

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

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

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

+      Sleep(2);

+      ret = GetOverlappedResult(parent_legacy_io_object()->usb_handle(),

+                                overlapped(),

+                                &transfer,

+                                wait) ? true :

+                                        false;

+      error = GetLastError();

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

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

+        break;

+      }

+    }

+  }

+

+  if (NULL != ovl_data) {

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

+  }

+

+  if (NULL != bytes_transferred) {

+    *bytes_transferred = is_write_ioctl() ? transferred_bytes_ : transfer;

+  }

+

+  return ret;

+}

diff --git a/host/windows/usb/api/adb_legacy_io_completion.h b/host/windows/usb/api/adb_legacy_io_completion.h
new file mode 100755
index 0000000..743219e
--- /dev/null
+++ b/host/windows/usb/api/adb_legacy_io_completion.h
@@ -0,0 +1,115 @@
+/*

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

+ *

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

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

+ * You may obtain a copy of the License at

+ *

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

+ *

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

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

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

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

+ * limitations under the License.

+ */

+

+#ifndef ANDROID_USB_API_ADB_LEGACY_IO_COMPLETION_H__

+#define ANDROID_USB_API_ADB_LEGACY_IO_COMPLETION_H__

+/** \file

+  This file consists of declaration of class AdbLegacyIOCompletion that

+  encapsulates a wrapper around OVERLAPPED Win32 structure returned from

+  asynchronous I/O requests issued via legacy USB API.

+*/

+

+#include "adb_io_completion.h"

+#include "adb_legacy_endpoint_object.h"

+

+/** \brief Encapsulates a wrapper around OVERLAPPED Win32 structure returned

+  from asynchronous I/O requests issued via legacy USB API.

+

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

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

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

+*/

+class AdbLegacyIOCompletion : public AdbIOCompletion {

+ public:

+  /** \brief Constructs the object.

+

+    @param[in] parent_io_obj Parent legacy endpoint that created this

+           instance.

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

+          with the I/O.

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

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

+           used to initialize OVERLAPPED structure for this object.

+    @param[in] is_write_ctl Flag indicating whether or not this completion

+           object is created for ADB_IOCTL_BULK_WRITE I/O.

+  */

+  AdbLegacyIOCompletion(AdbLegacyEndpointObject* parent_io_obj,

+                        ULONG expected_trans_size,

+                        HANDLE event_hndl,

+                        bool is_write_ctl);

+

+ protected:

+  /** \brief Destructs the object.

+

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

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

+  */

+  virtual ~AdbLegacyIOCompletion();

+

+  //

+  // Abstract overrides

+  //

+

+ public:

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

+

+    This method uses GetOverlappedResult to get results of the overlapped I/O

+    operation.

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

+           structure. Can be NULL.

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

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

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

+           Unlike regular GetOvelappedResult call this parameter can be NULL.

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

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

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

+           the GetLastError function returns ERROR_IO_INCOMPLETE.

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

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

+           extended error information. If GetLastError returns

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

+  */

+  virtual bool GetOvelappedIoResult(LPOVERLAPPED ovl_data,

+                                    ULONG* bytes_transferred,

+                                    bool wait);

+

+ public:

+  /// Gets parent legacy endpoint.

+  AdbLegacyEndpointObject* parent_legacy_io_object() const {

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

+  }

+

+  /// Gets write IOCTL flag.

+  bool is_write_ioctl() const {

+    return is_write_ioctl_;

+  }

+

+  /// Gets address for ADB_IOCTL_BULK_WRITE output buffer.

+  ULONG* transferred_bytes_ptr() {

+    ATLASSERT(is_write_ioctl());

+    return &transferred_bytes_;

+  }

+

+ protected:

+  /// Recepient for number of transferred bytes in write IOCTL.

+  ULONG         transferred_bytes_;

+

+  /// Write IOCTL flag.

+  bool          is_write_ioctl_;

+};

+

+#endif  // ANDROID_USB_API_ADB_LEGACY_IO_COMPLETION_H__

diff --git a/host/windows/usb/api/adb_winusb_interface.cpp b/host/windows/usb/api/adb_winusb_interface.cpp
index 00e575d..d09c1cb 100755
--- a/host/windows/usb/api/adb_winusb_interface.cpp
+++ b/host/windows/usb/api/adb_winusb_interface.cpp
@@ -305,7 +305,7 @@
 }

 

 ADBAPIHANDLE AdbWinUsbInterfaceObject::OpenEndpoint(UCHAR endpoint_id,

-                                              UCHAR endpoint_index) {

+                                                    UCHAR endpoint_index) {

   if (!IsOpened()) {

     SetLastError(ERROR_INVALID_HANDLE);

     return false;