adb_interface.cpp revision dceaaa52cec11631c72cfea5fb74ee607602ecde
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 26AdbInterfaceObject::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 39AdbInterfaceObject::~AdbInterfaceObject() { 40 ATLASSERT(NULL == winusb_handle_); 41 ATLASSERT(INVALID_HANDLE_VALUE == usb_device_handle_); 42} 43 44ADBAPIHANDLE 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 119bool 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 132bool 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 166bool 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 261bool 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 277bool 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 295bool 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 312bool 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 369ADBAPIHANDLE 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 392ADBAPIHANDLE 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} 414