diff options
Diffstat (limited to 'host/windows/usb/api/adb_winusb_interface.cpp')
| -rwxr-xr-x | host/windows/usb/api/adb_winusb_interface.cpp | 329 |
1 files changed, 329 insertions, 0 deletions
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 000000000..d09c1cbeb --- /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;
+}
|
