vchtchetkine | 8267511 | 2009-07-24 11:30:41 -0700 | [diff] [blame] | 1 | /*
|
| 2 | * Copyright (C) 2009 The Android Open Source Project
|
| 3 | *
|
| 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
| 5 | * you may not use this file except in compliance with the License.
|
| 6 | * You may obtain a copy of the License at
|
| 7 | *
|
| 8 | * http://www.apache.org/licenses/LICENSE-2.0
|
| 9 | *
|
| 10 | * Unless required by applicable law or agreed to in writing, software
|
| 11 | * distributed under the License is distributed on an "AS IS" BASIS,
|
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 13 | * See the License for the specific language governing permissions and
|
| 14 | * limitations under the License.
|
| 15 | */
|
| 16 |
|
| 17 | /** \file
|
| 18 | This file consists of implementation of class AdbWinUsbInterfaceObject
|
| 19 | that encapsulates an interface on our USB device that is accessible
|
| 20 | via WinUsb API.
|
| 21 | */
|
| 22 |
|
| 23 | #include "stdafx.h"
|
| 24 | #include "adb_winusb_interface.h"
|
| 25 | #include "adb_winusb_endpoint_object.h"
|
| 26 |
|
| 27 | AdbWinUsbInterfaceObject::AdbWinUsbInterfaceObject(const wchar_t* interf_name)
|
| 28 | : AdbInterfaceObject(interf_name),
|
| 29 | usb_device_handle_(INVALID_HANDLE_VALUE),
|
| 30 | winusb_handle_(NULL),
|
| 31 | interface_number_(0xFF),
|
| 32 | def_read_endpoint_(0xFF),
|
| 33 | read_endpoint_id_(0xFF),
|
| 34 | def_write_endpoint_(0xFF),
|
| 35 | write_endpoint_id_(0xFF) {
|
| 36 | }
|
| 37 |
|
| 38 | AdbWinUsbInterfaceObject::~AdbWinUsbInterfaceObject() {
|
| 39 | ATLASSERT(NULL == winusb_handle_);
|
| 40 | ATLASSERT(INVALID_HANDLE_VALUE == usb_device_handle_);
|
| 41 | }
|
| 42 |
|
| 43 | ADBAPIHANDLE AdbWinUsbInterfaceObject::CreateHandle() {
|
| 44 | // Open USB device for this inteface Note that WinUsb API
|
| 45 | // requires the handle to be opened for overlapped I/O.
|
| 46 | usb_device_handle_ = CreateFile(interface_name().c_str(),
|
| 47 | GENERIC_READ | GENERIC_WRITE,
|
| 48 | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
| 49 | NULL, OPEN_EXISTING,
|
| 50 | FILE_FLAG_OVERLAPPED, NULL);
|
| 51 | if (INVALID_HANDLE_VALUE == usb_device_handle_)
|
| 52 | return NULL;
|
| 53 |
|
| 54 | // Initialize WinUSB API for this interface
|
| 55 | if (!WinUsb_Initialize(usb_device_handle_, &winusb_handle_))
|
| 56 | return NULL;
|
| 57 |
|
| 58 | // Cache current interface number that will be used in
|
| 59 | // WinUsb_Xxx calls performed on this interface.
|
| 60 | if (!WinUsb_GetCurrentAlternateSetting(winusb_handle(), &interface_number_))
|
| 61 | return false;
|
| 62 |
|
| 63 | // Cache interface properties
|
| 64 | unsigned long bytes_written;
|
| 65 |
|
| 66 | // Cache USB device descriptor
|
| 67 | if (!WinUsb_GetDescriptor(winusb_handle(), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0,
|
| 68 | reinterpret_cast<PUCHAR>(&usb_device_descriptor_),
|
| 69 | sizeof(usb_device_descriptor_), &bytes_written)) {
|
| 70 | return false;
|
| 71 | }
|
| 72 |
|
| 73 | // Cache USB configuration descriptor
|
| 74 | if (!WinUsb_GetDescriptor(winusb_handle(), USB_CONFIGURATION_DESCRIPTOR_TYPE,
|
| 75 | 0, 0,
|
| 76 | reinterpret_cast<PUCHAR>(&usb_config_descriptor_),
|
| 77 | sizeof(usb_config_descriptor_), &bytes_written)) {
|
| 78 | return false;
|
| 79 | }
|
| 80 |
|
| 81 | // Cache USB interface descriptor
|
| 82 | if (!WinUsb_QueryInterfaceSettings(winusb_handle(), interface_number(),
|
| 83 | &usb_interface_descriptor_)) {
|
| 84 | return false;
|
| 85 | }
|
| 86 |
|
| 87 | // Save indexes and IDs for bulk read / write endpoints. We will use them to
|
| 88 | // convert ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX and
|
| 89 | // ADB_QUERY_BULK_READ_ENDPOINT_INDEX into actual endpoint indexes and IDs.
|
| 90 | for (UCHAR endpoint = 0; endpoint < usb_interface_descriptor_.bNumEndpoints;
|
| 91 | endpoint++) {
|
| 92 | // Get endpoint information
|
| 93 | WINUSB_PIPE_INFORMATION pipe_info;
|
| 94 | if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint,
|
| 95 | &pipe_info)) {
|
| 96 | return false;
|
| 97 | }
|
| 98 |
|
| 99 | if (UsbdPipeTypeBulk == pipe_info.PipeType) {
|
| 100 | // This is a bulk endpoint. Cache its index and ID.
|
| 101 | if (0 != (pipe_info.PipeId & USB_ENDPOINT_DIRECTION_MASK)) {
|
| 102 | // Use this endpoint as default bulk read endpoint
|
| 103 | ATLASSERT(0xFF == def_read_endpoint_);
|
| 104 | def_read_endpoint_ = endpoint;
|
| 105 | read_endpoint_id_ = pipe_info.PipeId;
|
| 106 | } else {
|
| 107 | // Use this endpoint as default bulk write endpoint
|
| 108 | ATLASSERT(0xFF == def_write_endpoint_);
|
| 109 | def_write_endpoint_ = endpoint;
|
| 110 | write_endpoint_id_ = pipe_info.PipeId;
|
| 111 | }
|
| 112 | }
|
| 113 | }
|
| 114 |
|
| 115 | return AdbInterfaceObject::CreateHandle();
|
| 116 | }
|
| 117 |
|
| 118 | bool AdbWinUsbInterfaceObject::CloseHandle() {
|
| 119 | if (NULL != winusb_handle_) {
|
| 120 | WinUsb_Free(winusb_handle_);
|
| 121 | winusb_handle_ = NULL;
|
| 122 | }
|
| 123 | if (INVALID_HANDLE_VALUE != usb_device_handle_) {
|
| 124 | ::CloseHandle(usb_device_handle_);
|
| 125 | usb_device_handle_ = INVALID_HANDLE_VALUE;
|
| 126 | }
|
| 127 |
|
| 128 | return AdbInterfaceObject::CloseHandle();
|
| 129 | }
|
| 130 |
|
| 131 | bool AdbWinUsbInterfaceObject::GetSerialNumber(void* buffer,
|
| 132 | unsigned long* buffer_char_size,
|
| 133 | bool ansi) {
|
| 134 | if (!IsOpened()) {
|
| 135 | SetLastError(ERROR_INVALID_HANDLE);
|
| 136 | return false;
|
| 137 | }
|
| 138 |
|
| 139 | if (NULL == buffer_char_size) {
|
| 140 | SetLastError(ERROR_INVALID_PARAMETER);
|
| 141 | return false;
|
| 142 | }
|
| 143 |
|
| 144 | // Calculate serial number string size. Note that WinUsb_GetDescriptor
|
| 145 | // API will not return number of bytes needed to store serial number
|
| 146 | // string. So we will have to start with a reasonably large preallocated
|
| 147 | // buffer and then loop through WinUsb_GetDescriptor calls, doubling up
|
| 148 | // string buffer size every time ERROR_INSUFFICIENT_BUFFER is returned.
|
| 149 | union {
|
| 150 | // Preallocate reasonably sized buffer on the stack.
|
| 151 | char small_buffer[64];
|
| 152 | USB_STRING_DESCRIPTOR initial_ser_num;
|
| 153 | };
|
| 154 | USB_STRING_DESCRIPTOR* ser_num = &initial_ser_num;
|
| 155 | // Buffer byte size
|
| 156 | unsigned long ser_num_size = sizeof(small_buffer);
|
| 157 | // After successful call to WinUsb_GetDescriptor will contain serial
|
| 158 | // number descriptor size.
|
| 159 | unsigned long bytes_written;
|
| 160 | while (!WinUsb_GetDescriptor(winusb_handle(), USB_STRING_DESCRIPTOR_TYPE,
|
| 161 | usb_device_descriptor_.iSerialNumber,
|
| 162 | 0x0409, // English (US)
|
| 163 | reinterpret_cast<PUCHAR>(ser_num),
|
| 164 | ser_num_size, &bytes_written)) {
|
| 165 | // Any error other than ERROR_INSUFFICIENT_BUFFER is terminal here.
|
| 166 | if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
|
| 167 | if (ser_num != &initial_ser_num)
|
| 168 | delete[] reinterpret_cast<char*>(ser_num);
|
| 169 | return false;
|
| 170 | }
|
| 171 |
|
| 172 | // Double up buffer size and reallocate string buffer
|
| 173 | ser_num_size *= 2;
|
| 174 | if (ser_num != &initial_ser_num)
|
| 175 | delete[] reinterpret_cast<char*>(ser_num);
|
| 176 | try {
|
| 177 | ser_num =
|
| 178 | reinterpret_cast<USB_STRING_DESCRIPTOR*>(new char[ser_num_size]);
|
| 179 | } catch (...) {
|
| 180 | SetLastError(ERROR_OUTOFMEMORY);
|
| 181 | return false;
|
| 182 | }
|
| 183 | }
|
| 184 |
|
| 185 | // Serial number string length
|
| 186 | unsigned long str_len = (ser_num->bLength -
|
| 187 | FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)) /
|
| 188 | sizeof(wchar_t);
|
| 189 |
|
| 190 | // Lets see if requested buffer is big enough to fit the string
|
| 191 | if ((NULL == buffer) || (*buffer_char_size < (str_len + 1))) {
|
| 192 | // Requested buffer is too small.
|
| 193 | if (ser_num != &initial_ser_num)
|
| 194 | delete[] reinterpret_cast<char*>(ser_num);
|
| 195 | *buffer_char_size = str_len + 1;
|
| 196 | SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
| 197 | return false;
|
| 198 | }
|
| 199 |
|
| 200 | bool ret = true;
|
| 201 | if (ansi) {
|
| 202 | // We need to convert name from wide char to ansi string
|
| 203 | if (0 != WideCharToMultiByte(CP_ACP, 0, ser_num->bString,
|
| 204 | static_cast<int>(str_len),
|
| 205 | reinterpret_cast<PSTR>(buffer),
|
| 206 | static_cast<int>(*buffer_char_size),
|
| 207 | NULL, NULL)) {
|
| 208 | // Zero-terminate output string.
|
| 209 | reinterpret_cast<char*>(buffer)[str_len] = '\0';
|
| 210 | } else {
|
| 211 | ret = false;
|
| 212 | }
|
| 213 | } else {
|
| 214 | // For wide char output just copy string buffer,
|
| 215 | // and zero-terminate output string.
|
| 216 | CopyMemory(buffer, ser_num->bString, bytes_written);
|
| 217 | reinterpret_cast<wchar_t*>(buffer)[str_len] = L'\0';
|
| 218 | }
|
| 219 |
|
| 220 | if (ser_num != &initial_ser_num)
|
| 221 | delete[] reinterpret_cast<char*>(ser_num);
|
| 222 |
|
| 223 | return ret;
|
| 224 | }
|
| 225 |
|
| 226 | bool AdbWinUsbInterfaceObject::GetEndpointInformation(
|
| 227 | UCHAR endpoint_index,
|
| 228 | AdbEndpointInformation* info) {
|
| 229 | if (!IsOpened()) {
|
| 230 | SetLastError(ERROR_INVALID_HANDLE);
|
| 231 | return false;
|
| 232 | }
|
| 233 |
|
| 234 | if (NULL == info) {
|
| 235 | SetLastError(ERROR_INVALID_PARAMETER);
|
| 236 | return false;
|
| 237 | }
|
| 238 |
|
| 239 | // Get actual endpoint index for predefined read / write endpoints.
|
| 240 | if (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) {
|
| 241 | endpoint_index = def_read_endpoint_;
|
| 242 | } else if (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) {
|
| 243 | endpoint_index = def_write_endpoint_;
|
| 244 | }
|
| 245 |
|
| 246 | // Query endpoint information
|
| 247 | WINUSB_PIPE_INFORMATION pipe_info;
|
| 248 | if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint_index,
|
| 249 | &pipe_info)) {
|
| 250 | return false;
|
| 251 | }
|
| 252 |
|
| 253 | // Save endpoint information into output.
|
| 254 | info->max_packet_size = pipe_info.MaximumPacketSize;
|
| 255 | info->max_transfer_size = 0xFFFFFFFF;
|
| 256 | info->endpoint_address = pipe_info.PipeId;
|
| 257 | info->polling_interval = pipe_info.Interval;
|
| 258 | info->setting_index = interface_number();
|
| 259 | switch (pipe_info.PipeType) {
|
| 260 | case UsbdPipeTypeControl:
|
| 261 | info->endpoint_type = AdbEndpointTypeControl;
|
| 262 | break;
|
| 263 |
|
| 264 | case UsbdPipeTypeIsochronous:
|
| 265 | info->endpoint_type = AdbEndpointTypeIsochronous;
|
| 266 | break;
|
| 267 |
|
| 268 | case UsbdPipeTypeBulk:
|
| 269 | info->endpoint_type = AdbEndpointTypeBulk;
|
| 270 | break;
|
| 271 |
|
| 272 | case UsbdPipeTypeInterrupt:
|
| 273 | info->endpoint_type = AdbEndpointTypeInterrupt;
|
| 274 | break;
|
| 275 |
|
| 276 | default:
|
| 277 | info->endpoint_type = AdbEndpointTypeInvalid;
|
| 278 | break;
|
| 279 | }
|
| 280 |
|
| 281 | return true;
|
| 282 | }
|
| 283 |
|
| 284 | ADBAPIHANDLE AdbWinUsbInterfaceObject::OpenEndpoint(
|
| 285 | UCHAR endpoint_index,
|
| 286 | AdbOpenAccessType access_type,
|
| 287 | AdbOpenSharingMode sharing_mode) {
|
| 288 | // Convert index into id
|
| 289 | UCHAR endpoint_id;
|
| 290 |
|
| 291 | if ((ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) ||
|
| 292 | (def_read_endpoint_ == endpoint_index)) {
|
| 293 | endpoint_id = read_endpoint_id_;
|
| 294 | endpoint_index = def_read_endpoint_;
|
| 295 | } else if ((ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) ||
|
| 296 | (def_write_endpoint_ == endpoint_index)) {
|
| 297 | endpoint_id = write_endpoint_id_;
|
| 298 | endpoint_index = def_write_endpoint_;
|
| 299 | } else {
|
| 300 | SetLastError(ERROR_INVALID_PARAMETER);
|
| 301 | return false;
|
| 302 | }
|
| 303 |
|
| 304 | return OpenEndpoint(endpoint_id, endpoint_index);
|
| 305 | }
|
| 306 |
|
| 307 | ADBAPIHANDLE AdbWinUsbInterfaceObject::OpenEndpoint(UCHAR endpoint_id,
|
vchtchetkine | 3916484 | 2009-07-28 12:45:33 -0700 | [diff] [blame] | 308 | UCHAR endpoint_index) {
|
vchtchetkine | 8267511 | 2009-07-24 11:30:41 -0700 | [diff] [blame] | 309 | if (!IsOpened()) {
|
| 310 | SetLastError(ERROR_INVALID_HANDLE);
|
| 311 | return false;
|
| 312 | }
|
| 313 |
|
| 314 | AdbEndpointObject* adb_endpoint = NULL;
|
| 315 |
|
| 316 | try {
|
| 317 | adb_endpoint =
|
| 318 | new AdbWinUsbEndpointObject(this, endpoint_id, endpoint_index);
|
| 319 | } catch (...) {
|
| 320 | SetLastError(ERROR_OUTOFMEMORY);
|
| 321 | return NULL;
|
| 322 | }
|
| 323 |
|
| 324 | ADBAPIHANDLE ret = adb_endpoint->CreateHandle();
|
| 325 |
|
| 326 | adb_endpoint->Release();
|
| 327 |
|
| 328 | return ret;
|
| 329 | }
|