vchtchetkine | dceaaa5 | 2009-07-22 13:34:53 -0700 | [diff] [blame^] | 1 | /*
|
| 2 | * Copyright (C) 2006 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 AdbInterfaceObject that
|
| 19 | encapsulates an interface on our USB device.
|
| 20 | */
|
| 21 |
|
| 22 | #include "stdafx.h"
|
| 23 | #include "adb_interface.h"
|
| 24 | #include "adb_endpoint_object.h"
|
| 25 |
|
| 26 | AdbInterfaceObject::AdbInterfaceObject(const wchar_t* interf_name)
|
| 27 | : AdbObjectHandle(AdbObjectTypeInterface),
|
| 28 | interface_name_(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 | ATLASSERT(NULL != interf_name);
|
| 37 | }
|
| 38 |
|
| 39 | AdbInterfaceObject::~AdbInterfaceObject() {
|
| 40 | ATLASSERT(NULL == winusb_handle_);
|
| 41 | ATLASSERT(INVALID_HANDLE_VALUE == usb_device_handle_);
|
| 42 | }
|
| 43 |
|
| 44 | ADBAPIHANDLE AdbInterfaceObject::CreateHandle() {
|
| 45 | // Open USB device for this inteface Note that WinUsb API
|
| 46 | // requires the handle to be opened for overlapped I/O.
|
| 47 | usb_device_handle_ = CreateFile(interface_name().c_str(),
|
| 48 | GENERIC_READ | GENERIC_WRITE,
|
| 49 | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
| 50 | NULL, OPEN_EXISTING,
|
| 51 | FILE_FLAG_OVERLAPPED, NULL);
|
| 52 | if (INVALID_HANDLE_VALUE == usb_device_handle_)
|
| 53 | return NULL;
|
| 54 |
|
| 55 | // Initialize WinUSB API for this interface
|
| 56 | if (!WinUsb_Initialize(usb_device_handle_, &winusb_handle_))
|
| 57 | return NULL;
|
| 58 |
|
| 59 | // Cache current interface number that will be used in
|
| 60 | // WinUsb_Xxx calls performed on this interface.
|
| 61 | if (!WinUsb_GetCurrentAlternateSetting(winusb_handle(), &interface_number_))
|
| 62 | return false;
|
| 63 |
|
| 64 | // Cache interface properties
|
| 65 | unsigned long bytes_written;
|
| 66 |
|
| 67 | // Cache USB device descriptor
|
| 68 | if (!WinUsb_GetDescriptor(winusb_handle(), USB_DEVICE_DESCRIPTOR_TYPE, 0, 0,
|
| 69 | reinterpret_cast<PUCHAR>(&usb_device_descriptor_),
|
| 70 | sizeof(usb_device_descriptor_), &bytes_written)) {
|
| 71 | return false;
|
| 72 | }
|
| 73 |
|
| 74 | // Cache USB configuration descriptor
|
| 75 | if (!WinUsb_GetDescriptor(winusb_handle(), USB_CONFIGURATION_DESCRIPTOR_TYPE,
|
| 76 | 0, 0,
|
| 77 | reinterpret_cast<PUCHAR>(&usb_config_descriptor_),
|
| 78 | sizeof(usb_config_descriptor_), &bytes_written)) {
|
| 79 | return false;
|
| 80 | }
|
| 81 |
|
| 82 | // Cache USB interface descriptor
|
| 83 | if (!WinUsb_QueryInterfaceSettings(winusb_handle(), interface_number(),
|
| 84 | &usb_interface_descriptor_)) {
|
| 85 | return false;
|
| 86 | }
|
| 87 |
|
| 88 | // Save indexes and IDs for bulk read / write endpoints. We will use them to
|
| 89 | // convert ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX and
|
| 90 | // ADB_QUERY_BULK_READ_ENDPOINT_INDEX into actual endpoint indexes and IDs.
|
| 91 | for (UCHAR endpoint = 0; endpoint < usb_interface_descriptor_.bNumEndpoints;
|
| 92 | endpoint++) {
|
| 93 | // Get endpoint information
|
| 94 | WINUSB_PIPE_INFORMATION pipe_info;
|
| 95 | if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint,
|
| 96 | &pipe_info)) {
|
| 97 | return false;
|
| 98 | }
|
| 99 |
|
| 100 | if (UsbdPipeTypeBulk == pipe_info.PipeType) {
|
| 101 | // This is a bulk endpoint. Cache its index and ID.
|
| 102 | if (0 != (pipe_info.PipeId & USB_ENDPOINT_DIRECTION_MASK)) {
|
| 103 | // Use this endpoint as default bulk read endpoint
|
| 104 | ATLASSERT(0xFF == def_read_endpoint_);
|
| 105 | def_read_endpoint_ = endpoint;
|
| 106 | read_endpoint_id_ = pipe_info.PipeId;
|
| 107 | } else {
|
| 108 | // Use this endpoint as default bulk write endpoint
|
| 109 | ATLASSERT(0xFF == def_write_endpoint_);
|
| 110 | def_write_endpoint_ = endpoint;
|
| 111 | write_endpoint_id_ = pipe_info.PipeId;
|
| 112 | }
|
| 113 | }
|
| 114 | }
|
| 115 |
|
| 116 | return AdbObjectHandle::CreateHandle();
|
| 117 | }
|
| 118 |
|
| 119 | bool AdbInterfaceObject::CloseHandle() {
|
| 120 | if (NULL != winusb_handle_) {
|
| 121 | WinUsb_Free(winusb_handle_);
|
| 122 | winusb_handle_ = NULL;
|
| 123 | }
|
| 124 | if (INVALID_HANDLE_VALUE != usb_device_handle_) {
|
| 125 | ::CloseHandle(usb_device_handle_);
|
| 126 | usb_device_handle_ = INVALID_HANDLE_VALUE;
|
| 127 | }
|
| 128 |
|
| 129 | return AdbObjectHandle::CloseHandle();
|
| 130 | }
|
| 131 |
|
| 132 | bool AdbInterfaceObject::GetInterfaceName(void* buffer,
|
| 133 | unsigned long* buffer_char_size,
|
| 134 | bool ansi) {
|
| 135 | if (NULL == buffer_char_size) {
|
| 136 | SetLastError(ERROR_INVALID_PARAMETER);
|
| 137 | return false;
|
| 138 | }
|
| 139 |
|
| 140 | // Lets see if buffer is big enough
|
| 141 | ULONG name_len = static_cast<ULONG>(interface_name_.length() + 1);
|
| 142 | if ((NULL == buffer) || (*buffer_char_size < name_len)) {
|
| 143 | *buffer_char_size = name_len;
|
| 144 | SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
| 145 | return false;
|
| 146 | }
|
| 147 |
|
| 148 | if (!ansi) {
|
| 149 | // If user asked for wide char name just return it
|
| 150 | wcscpy(reinterpret_cast<wchar_t*>(buffer), interface_name().c_str());
|
| 151 | return true;
|
| 152 | }
|
| 153 |
|
| 154 | // We need to convert name from wide char to ansi string
|
| 155 | int res = WideCharToMultiByte(CP_ACP,
|
| 156 | 0,
|
| 157 | interface_name().c_str(),
|
| 158 | static_cast<int>(name_len),
|
| 159 | reinterpret_cast<PSTR>(buffer),
|
| 160 | static_cast<int>(*buffer_char_size),
|
| 161 | NULL,
|
| 162 | NULL);
|
| 163 | return (res != 0);
|
| 164 | }
|
| 165 |
|
| 166 | bool AdbInterfaceObject::GetSerialNumber(void* buffer,
|
| 167 | unsigned long* buffer_char_size,
|
| 168 | bool ansi) {
|
| 169 | if (!IsOpened()) {
|
| 170 | SetLastError(ERROR_INVALID_HANDLE);
|
| 171 | return false;
|
| 172 | }
|
| 173 |
|
| 174 | if (NULL == buffer_char_size) {
|
| 175 | SetLastError(ERROR_INVALID_PARAMETER);
|
| 176 | return false;
|
| 177 | }
|
| 178 |
|
| 179 | // Calculate serial number string size. Note that WinUsb_GetDescriptor
|
| 180 | // API will not return number of bytes needed to store serial number
|
| 181 | // string. So we will have to start with a reasonably large preallocated
|
| 182 | // buffer and then loop through WinUsb_GetDescriptor calls, doubling up
|
| 183 | // string buffer size every time ERROR_INSUFFICIENT_BUFFER is returned.
|
| 184 | union {
|
| 185 | // Preallocate reasonably sized buffer on the stack.
|
| 186 | char small_buffer[64];
|
| 187 | USB_STRING_DESCRIPTOR initial_ser_num;
|
| 188 | };
|
| 189 | USB_STRING_DESCRIPTOR* ser_num = &initial_ser_num;
|
| 190 | // Buffer byte size
|
| 191 | unsigned long ser_num_size = sizeof(small_buffer);
|
| 192 | // After successful call to WinUsb_GetDescriptor will contain serial
|
| 193 | // number descriptor size.
|
| 194 | unsigned long bytes_written;
|
| 195 | while (!WinUsb_GetDescriptor(winusb_handle(), USB_STRING_DESCRIPTOR_TYPE,
|
| 196 | usb_device_descriptor_.iSerialNumber,
|
| 197 | 0x0409, // English (US)
|
| 198 | reinterpret_cast<PUCHAR>(ser_num),
|
| 199 | ser_num_size, &bytes_written)) {
|
| 200 | // Any error other than ERROR_INSUFFICIENT_BUFFER is terminal here.
|
| 201 | if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
|
| 202 | if (ser_num != &initial_ser_num)
|
| 203 | delete[] reinterpret_cast<char*>(ser_num);
|
| 204 | return false;
|
| 205 | }
|
| 206 |
|
| 207 | // Double up buffer size and reallocate string buffer
|
| 208 | ser_num_size *= 2;
|
| 209 | if (ser_num != &initial_ser_num)
|
| 210 | delete[] reinterpret_cast<char*>(ser_num);
|
| 211 | try {
|
| 212 | ser_num =
|
| 213 | reinterpret_cast<USB_STRING_DESCRIPTOR*>(new char[ser_num_size]);
|
| 214 | } catch (...) {
|
| 215 | SetLastError(ERROR_OUTOFMEMORY);
|
| 216 | return false;
|
| 217 | }
|
| 218 | }
|
| 219 |
|
| 220 | // Serial number string length
|
| 221 | unsigned long str_len = (ser_num->bLength -
|
| 222 | FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString)) /
|
| 223 | sizeof(wchar_t);
|
| 224 |
|
| 225 | // Lets see if requested buffer is big enough to fit the string
|
| 226 | if ((NULL == buffer) || (*buffer_char_size < (str_len + 1))) {
|
| 227 | // Requested buffer is too small.
|
| 228 | if (ser_num != &initial_ser_num)
|
| 229 | delete[] reinterpret_cast<char*>(ser_num);
|
| 230 | *buffer_char_size = str_len + 1;
|
| 231 | SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
| 232 | return false;
|
| 233 | }
|
| 234 |
|
| 235 | bool ret = true;
|
| 236 | if (ansi) {
|
| 237 | // We need to convert name from wide char to ansi string
|
| 238 | if (0 != WideCharToMultiByte(CP_ACP, 0, ser_num->bString,
|
| 239 | static_cast<int>(str_len),
|
| 240 | reinterpret_cast<PSTR>(buffer),
|
| 241 | static_cast<int>(*buffer_char_size),
|
| 242 | NULL, NULL)) {
|
| 243 | // Zero-terminate output string.
|
| 244 | reinterpret_cast<char*>(buffer)[str_len] = '\0';
|
| 245 | } else {
|
| 246 | ret = false;
|
| 247 | }
|
| 248 | } else {
|
| 249 | // For wide char output just copy string buffer,
|
| 250 | // and zero-terminate output string.
|
| 251 | CopyMemory(buffer, ser_num->bString, bytes_written);
|
| 252 | reinterpret_cast<wchar_t*>(buffer)[str_len] = L'\0';
|
| 253 | }
|
| 254 |
|
| 255 | if (ser_num != &initial_ser_num)
|
| 256 | delete[] reinterpret_cast<char*>(ser_num);
|
| 257 |
|
| 258 | return ret;
|
| 259 | }
|
| 260 |
|
| 261 | bool AdbInterfaceObject::GetUsbDeviceDescriptor(USB_DEVICE_DESCRIPTOR* desc) {
|
| 262 | if (!IsOpened()) {
|
| 263 | SetLastError(ERROR_INVALID_HANDLE);
|
| 264 | return false;
|
| 265 | }
|
| 266 |
|
| 267 | if (NULL == desc) {
|
| 268 | SetLastError(ERROR_INVALID_PARAMETER);
|
| 269 | return false;
|
| 270 | }
|
| 271 |
|
| 272 | CopyMemory(desc, usb_device_descriptor(), sizeof(USB_DEVICE_DESCRIPTOR));
|
| 273 |
|
| 274 | return true;
|
| 275 | }
|
| 276 |
|
| 277 | bool AdbInterfaceObject::GetUsbConfigurationDescriptor(
|
| 278 | USB_CONFIGURATION_DESCRIPTOR* desc) {
|
| 279 | if (!IsOpened()) {
|
| 280 | SetLastError(ERROR_INVALID_HANDLE);
|
| 281 | return false;
|
| 282 | }
|
| 283 |
|
| 284 | if (NULL == desc) {
|
| 285 | SetLastError(ERROR_INVALID_PARAMETER);
|
| 286 | return false;
|
| 287 | }
|
| 288 |
|
| 289 | CopyMemory(desc, usb_config_descriptor(),
|
| 290 | sizeof(USB_CONFIGURATION_DESCRIPTOR));
|
| 291 |
|
| 292 | return true;
|
| 293 | }
|
| 294 |
|
| 295 | bool AdbInterfaceObject::GetUsbInterfaceDescriptor(
|
| 296 | USB_INTERFACE_DESCRIPTOR* desc) {
|
| 297 | if (!IsOpened()) {
|
| 298 | SetLastError(ERROR_INVALID_HANDLE);
|
| 299 | return false;
|
| 300 | }
|
| 301 |
|
| 302 | if (NULL == desc) {
|
| 303 | SetLastError(ERROR_INVALID_PARAMETER);
|
| 304 | return false;
|
| 305 | }
|
| 306 |
|
| 307 | CopyMemory(desc, usb_interface_descriptor(), sizeof(USB_INTERFACE_DESCRIPTOR));
|
| 308 |
|
| 309 | return true;
|
| 310 | }
|
| 311 |
|
| 312 | bool AdbInterfaceObject::GetEndpointInformation(UCHAR endpoint_index,
|
| 313 | AdbEndpointInformation* info) {
|
| 314 | if (!IsOpened()) {
|
| 315 | SetLastError(ERROR_INVALID_HANDLE);
|
| 316 | return false;
|
| 317 | }
|
| 318 |
|
| 319 | if (NULL == info) {
|
| 320 | SetLastError(ERROR_INVALID_PARAMETER);
|
| 321 | return false;
|
| 322 | }
|
| 323 |
|
| 324 | // Get actual endpoint index for predefined read / write endpoints.
|
| 325 | if (ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) {
|
| 326 | endpoint_index = def_read_endpoint_;
|
| 327 | } else if (ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) {
|
| 328 | endpoint_index = def_write_endpoint_;
|
| 329 | }
|
| 330 |
|
| 331 | // Query endpoint information
|
| 332 | WINUSB_PIPE_INFORMATION pipe_info;
|
| 333 | if (!WinUsb_QueryPipe(winusb_handle(), interface_number(), endpoint_index,
|
| 334 | &pipe_info)) {
|
| 335 | return false;
|
| 336 | }
|
| 337 |
|
| 338 | // Save endpoint information into output.
|
| 339 | info->max_packet_size = pipe_info.MaximumPacketSize;
|
| 340 | info->max_transfer_size = 0xFFFFFFFF;
|
| 341 | info->endpoint_address = pipe_info.PipeId;
|
| 342 | info->polling_interval = pipe_info.Interval;
|
| 343 | info->setting_index = interface_number();
|
| 344 | switch (pipe_info.PipeType) {
|
| 345 | case UsbdPipeTypeControl:
|
| 346 | info->endpoint_type = AdbEndpointTypeControl;
|
| 347 | break;
|
| 348 |
|
| 349 | case UsbdPipeTypeIsochronous:
|
| 350 | info->endpoint_type = AdbEndpointTypeIsochronous;
|
| 351 | break;
|
| 352 |
|
| 353 | case UsbdPipeTypeBulk:
|
| 354 | info->endpoint_type = AdbEndpointTypeBulk;
|
| 355 | break;
|
| 356 |
|
| 357 | case UsbdPipeTypeInterrupt:
|
| 358 | info->endpoint_type = AdbEndpointTypeInterrupt;
|
| 359 | break;
|
| 360 |
|
| 361 | default:
|
| 362 | info->endpoint_type = AdbEndpointTypeInvalid;
|
| 363 | break;
|
| 364 | }
|
| 365 |
|
| 366 | return true;
|
| 367 | }
|
| 368 |
|
| 369 | ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint(
|
| 370 | UCHAR endpoint_index,
|
| 371 | AdbOpenAccessType access_type,
|
| 372 | AdbOpenSharingMode sharing_mode) {
|
| 373 | // Convert index into id
|
| 374 | UCHAR endpoint_id;
|
| 375 |
|
| 376 | if ((ADB_QUERY_BULK_READ_ENDPOINT_INDEX == endpoint_index) ||
|
| 377 | (def_read_endpoint_ == endpoint_index)) {
|
| 378 | endpoint_id = read_endpoint_id_;
|
| 379 | endpoint_index = def_read_endpoint_;
|
| 380 | } else if ((ADB_QUERY_BULK_WRITE_ENDPOINT_INDEX == endpoint_index) ||
|
| 381 | (def_write_endpoint_ == endpoint_index)) {
|
| 382 | endpoint_id = write_endpoint_id_;
|
| 383 | endpoint_index = def_write_endpoint_;
|
| 384 | } else {
|
| 385 | SetLastError(ERROR_INVALID_PARAMETER);
|
| 386 | return false;
|
| 387 | }
|
| 388 |
|
| 389 | return OpenEndpoint(endpoint_id, endpoint_index);
|
| 390 | }
|
| 391 |
|
| 392 | ADBAPIHANDLE AdbInterfaceObject::OpenEndpoint(UCHAR endpoint_id,
|
| 393 | UCHAR endpoint_index) {
|
| 394 | if (!IsOpened()) {
|
| 395 | SetLastError(ERROR_INVALID_HANDLE);
|
| 396 | return false;
|
| 397 | }
|
| 398 |
|
| 399 | AdbEndpointObject* adb_endpoint = NULL;
|
| 400 |
|
| 401 | try {
|
| 402 | adb_endpoint = new AdbEndpointObject(this, endpoint_id, endpoint_index);
|
| 403 | } catch (...) {
|
| 404 | SetLastError(ERROR_OUTOFMEMORY);
|
| 405 | return NULL;
|
| 406 | }
|
| 407 |
|
| 408 | ADBAPIHANDLE ret = adb_endpoint->CreateHandle();
|
| 409 |
|
| 410 | adb_endpoint->Release();
|
| 411 |
|
| 412 | return ret;
|
| 413 | }
|