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