Refactor ADB API dll to support WinUsb
diff --git a/host/windows/usb/api/adb_interface.cpp b/host/windows/usb/api/adb_interface.cpp
index 9369e13..9b073a4 100644
--- a/host/windows/usb/api/adb_interface.cpp
+++ b/host/windows/usb/api/adb_interface.cpp
@@ -1,344 +1,413 @@
-/*
- * Copyright (C) 2006 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 AdbInterfaceObject that
-  encapsulates an 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) {
-  ATLASSERT(NULL != interf_name);
-}
-
-AdbInterfaceObject::~AdbInterfaceObject() {
-}
-
-ADBAPIHANDLE AdbInterfaceObject::CreateHandle() {
-  // 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;
-
-  // 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;
-
-  return AdbObjectHandle::CreateHandle();
-}
-
-bool AdbInterfaceObject::GetInterfaceName(void* buffer,
-                                          unsigned long* buffer_char_size,
-                                          bool ansi) {
-  // Lets see if buffer is big enough
-  ULONG name_len = static_cast<ULONG>(interface_name_.length() + 1);
-  if ((NULL == buffer) || (*buffer_char_size < name_len)) {
-    *buffer_char_size = name_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), interface_name().c_str());
-    return true;
-  }
-
-  // We need to convert name from wide char to ansi string
-  int res = WideCharToMultiByte(CP_ACP,
-                                0,
-                                interface_name().c_str(),
-                                static_cast<int>(name_len),
-                                reinterpret_cast<PSTR>(buffer),
-                                static_cast<int>(*buffer_char_size),
-                                NULL,
-                                NULL);
-  return (res != 0);
-}
-
-bool AdbInterfaceObject::GetSerialNumber(void* buffer,
-                                         unsigned long* buffer_char_size,
-                                         bool ansi) {
-  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 AdbInterfaceObject::GetUsbDeviceDescriptor(USB_DEVICE_DESCRIPTOR* desc) {
-  if (!IsOpened()) {
-    SetLastError(ERROR_INVALID_HANDLE);
-    return false;
-  }
-
-  CopyMemory(desc, usb_device_descriptor(), sizeof(USB_DEVICE_DESCRIPTOR));
-
-  return true;
-}
-
-bool AdbInterfaceObject::GetUsbConfigurationDescriptor(
-    USB_CONFIGURATION_DESCRIPTOR* desc) {
-  if (!IsOpened()) {
-    SetLastError(ERROR_INVALID_HANDLE);
-    return false;
-  }
-
-  CopyMemory(desc, usb_config_descriptor(),
-             sizeof(USB_CONFIGURATION_DESCRIPTOR));
-
-  return true;
-}
-
-bool AdbInterfaceObject::GetUsbInterfaceDescriptor(
-    USB_INTERFACE_DESCRIPTOR* desc) {
-  if (!IsOpened()) {
-    SetLastError(ERROR_INVALID_HANDLE);
-    return false;
-  }
-
-  CopyMemory(desc, usb_interface_descriptor(), sizeof(USB_INTERFACE_DESCRIPTOR));
-
-  return true;
-}
-
-bool AdbInterfaceObject::GetEndpointInformation(UCHAR endpoint_index,
-                                                AdbEndpointInformation* info) {
-  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;
-
-  // 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 AdbInterfaceObject::OpenEndpoint(
-    UCHAR endpoint_index,
-    AdbOpenAccessType access_type,
-    AdbOpenSharingMode sharing_mode) {
-  // Convert index into name
-  std::wstring endpoint_name;
-
-  try {
-    if (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) {
-      endpoint_name = DEVICE_BULK_READ_PIPE_NAME;
-    } else if (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) {
-      endpoint_name = DEVICE_BULK_WRITE_PIPE_NAME;
-    } else {
-      wchar_t fmt[265];
-      swprintf(fmt, L"%ws%u", DEVICE_PIPE_NAME_PREFIX, endpoint_index);
-      endpoint_name = fmt;
-    }
-  } catch (...) {
-    SetLastError(ERROR_OUTOFMEMORY);
-    return NULL;
-  }
-
-  return OpenEndpoint(endpoint_name.c_str(), access_type, sharing_mode);
-}
-
-ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint(
-    const wchar_t* endpoint_name,
-    AdbOpenAccessType access_type,
-    AdbOpenSharingMode sharing_mode) {
-  if (!IsOpened()) {
-    SetLastError(ERROR_INVALID_HANDLE);
-    return false;
-  }
-
-  AdbEndpointObject* adb_endpoint = NULL;
-  
-  try {
-    adb_endpoint = new AdbEndpointObject(this);
-  } catch (...) {
-    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 AdbInterfaceObject::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 AdbInterfaceObject::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 AdbInterfaceObject::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;
-}
+/*

+ * Copyright (C) 2006 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 AdbInterfaceObject that

+  encapsulates an 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) {

+  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,

+                                          unsigned long* buffer_char_size,

+                                          bool ansi) {

+  if (NULL == buffer_char_size) {

+    SetLastError(ERROR_INVALID_PARAMETER);

+    return false;

+  }

+

+  // Lets see if buffer is big enough

+  ULONG name_len = static_cast<ULONG>(interface_name_.length() + 1);

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

+    *buffer_char_size = name_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), interface_name().c_str());

+    return true;

+  }

+

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

+  int res = WideCharToMultiByte(CP_ACP,

+                                0,

+                                interface_name().c_str(),

+                                static_cast<int>(name_len),

+                                reinterpret_cast<PSTR>(buffer),

+                                static_cast<int>(*buffer_char_size),

+                                NULL,

+                                NULL);

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

+    return false;

+  }

+

+  if (NULL == desc) {

+    SetLastError(ERROR_INVALID_PARAMETER);

+    return false;

+  }

+

+  CopyMemory(desc, usb_device_descriptor(), sizeof(USB_DEVICE_DESCRIPTOR));

+

+  return true;

+}

+

+bool AdbInterfaceObject::GetUsbConfigurationDescriptor(

+    USB_CONFIGURATION_DESCRIPTOR* desc) {

+  if (!IsOpened()) {

+    SetLastError(ERROR_INVALID_HANDLE);

+    return false;

+  }

+

+  if (NULL == desc) {

+    SetLastError(ERROR_INVALID_PARAMETER);

+    return false;

+  }

+

+  CopyMemory(desc, usb_config_descriptor(),

+             sizeof(USB_CONFIGURATION_DESCRIPTOR));

+

+  return true;

+}

+

+bool AdbInterfaceObject::GetUsbInterfaceDescriptor(

+    USB_INTERFACE_DESCRIPTOR* desc) {

+  if (!IsOpened()) {

+    SetLastError(ERROR_INVALID_HANDLE);

+    return false;

+  }

+

+  if (NULL == desc) {

+    SetLastError(ERROR_INVALID_PARAMETER);

+    return false;

+  }

+

+  CopyMemory(desc, usb_interface_descriptor(), sizeof(USB_INTERFACE_DESCRIPTOR));

+

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

+}