1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <windows.h> 30 #include <winerror.h> 31 #include <errno.h> 32 #include <usb100.h> 33 #include <adb_api.h> 34 #include <stdio.h> 35 36 #include "usb.h" 37 38 //#define TRACE_USB 1 39 #if TRACE_USB 40 #define DBG(x...) fprintf(stderr, x) 41 #else 42 #define DBG(x...) 43 #endif 44 45 #define MAX_USBFS_BULK_SIZE (1024 * 1024) 46 47 /** Structure usb_handle describes our connection to the usb device via 48 AdbWinApi.dll. This structure is returned from usb_open() routine and 49 is expected in each subsequent call that is accessing the device. 50 */ 51 struct usb_handle { 52 /// Handle to USB interface 53 ADBAPIHANDLE adb_interface; 54 55 /// Handle to USB read pipe (endpoint) 56 ADBAPIHANDLE adb_read_pipe; 57 58 /// Handle to USB write pipe (endpoint) 59 ADBAPIHANDLE adb_write_pipe; 60 61 /// Interface name 62 char* interface_name; 63 }; 64 65 /// Class ID assigned to the device by androidusb.sys 66 static const GUID usb_class_id = ANDROID_USB_CLASS_ID; 67 68 69 /// Checks if interface (device) matches certain criteria 70 int recognized_device(usb_handle* handle, ifc_match_func callback); 71 72 /// Opens usb interface (device) by interface (device) name. 73 usb_handle* do_usb_open(const wchar_t* interface_name); 74 75 /// Writes data to the opened usb handle 76 int usb_write(usb_handle* handle, const void* data, int len); 77 78 /// Reads data using the opened usb handle 79 int usb_read(usb_handle *handle, void* data, int len); 80 81 /// Cleans up opened usb handle 82 void usb_cleanup_handle(usb_handle* handle); 83 84 /// Cleans up (but don't close) opened usb handle 85 void usb_kick(usb_handle* handle); 86 87 /// Closes opened usb handle 88 int usb_close(usb_handle* handle); 89 90 91 usb_handle* do_usb_open(const wchar_t* interface_name) { 92 // Allocate our handle 93 usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle)); 94 if (NULL == ret) 95 return NULL; 96 97 // Create interface. 98 ret->adb_interface = AdbCreateInterfaceByName(interface_name); 99 100 if (NULL == ret->adb_interface) { 101 free(ret); 102 errno = GetLastError(); 103 return NULL; 104 } 105 106 // Open read pipe (endpoint) 107 ret->adb_read_pipe = 108 AdbOpenDefaultBulkReadEndpoint(ret->adb_interface, 109 AdbOpenAccessTypeReadWrite, 110 AdbOpenSharingModeReadWrite); 111 if (NULL != ret->adb_read_pipe) { 112 // Open write pipe (endpoint) 113 ret->adb_write_pipe = 114 AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface, 115 AdbOpenAccessTypeReadWrite, 116 AdbOpenSharingModeReadWrite); 117 if (NULL != ret->adb_write_pipe) { 118 // Save interface name 119 unsigned long name_len = 0; 120 121 // First get expected name length 122 AdbGetInterfaceName(ret->adb_interface, 123 NULL, 124 &name_len, 125 true); 126 if (0 != name_len) { 127 ret->interface_name = (char*)malloc(name_len); 128 129 if (NULL != ret->interface_name) { 130 // Now save the name 131 if (AdbGetInterfaceName(ret->adb_interface, 132 ret->interface_name, 133 &name_len, 134 true)) { 135 // We're done at this point 136 return ret; 137 } 138 } else { 139 SetLastError(ERROR_OUTOFMEMORY); 140 } 141 } 142 } 143 } 144 145 // Something went wrong. 146 errno = GetLastError(); 147 usb_cleanup_handle(ret); 148 free(ret); 149 SetLastError(errno); 150 151 return NULL; 152 } 153 154 int usb_write(usb_handle* handle, const void* data, int len) { 155 unsigned long time_out = 500 + len * 8; 156 unsigned long written = 0; 157 unsigned count = 0; 158 int ret; 159 160 DBG("usb_write %d\n", len); 161 if (NULL != handle) { 162 // Perform write 163 while(len > 0) { 164 int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; 165 ret = AdbWriteEndpointSync(handle->adb_write_pipe, 166 (void*)data, 167 (unsigned long)xfer, 168 &written, 169 time_out); 170 errno = GetLastError(); 171 DBG("AdbWriteEndpointSync returned %d, errno: %d\n", ret, errno); 172 if (ret == 0) { 173 // assume ERROR_INVALID_HANDLE indicates we are disconnected 174 if (errno == ERROR_INVALID_HANDLE) 175 usb_kick(handle); 176 return -1; 177 } 178 179 count += written; 180 len -= written; 181 data += written; 182 183 if (len == 0) 184 return count; 185 } 186 } else { 187 DBG("usb_write NULL handle\n"); 188 SetLastError(ERROR_INVALID_HANDLE); 189 } 190 191 DBG("usb_write failed: %d\n", errno); 192 193 return -1; 194 } 195 196 int usb_read(usb_handle *handle, void* data, int len) { 197 unsigned long time_out = 500 + len * 8; 198 unsigned long read = 0; 199 int ret; 200 201 DBG("usb_read %d\n", len); 202 if (NULL != handle) { 203 while (1) { 204 int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; 205 206 ret = AdbReadEndpointSync(handle->adb_read_pipe, 207 (void*)data, 208 (unsigned long)xfer, 209 &read, 210 time_out); 211 errno = GetLastError(); 212 DBG("usb_read got: %ld, expected: %d, errno: %d\n", read, xfer, errno); 213 if (ret) { 214 return read; 215 } else if (errno != ERROR_SEM_TIMEOUT) { 216 // assume ERROR_INVALID_HANDLE indicates we are disconnected 217 if (errno == ERROR_INVALID_HANDLE) 218 usb_kick(handle); 219 break; 220 } 221 // else we timed out - try again 222 } 223 } else { 224 DBG("usb_read NULL handle\n"); 225 SetLastError(ERROR_INVALID_HANDLE); 226 } 227 228 DBG("usb_read failed: %d\n", errno); 229 230 return -1; 231 } 232 233 void usb_cleanup_handle(usb_handle* handle) { 234 if (NULL != handle) { 235 if (NULL != handle->interface_name) 236 free(handle->interface_name); 237 if (NULL != handle->adb_write_pipe) 238 AdbCloseHandle(handle->adb_write_pipe); 239 if (NULL != handle->adb_read_pipe) 240 AdbCloseHandle(handle->adb_read_pipe); 241 if (NULL != handle->adb_interface) 242 AdbCloseHandle(handle->adb_interface); 243 244 handle->interface_name = NULL; 245 handle->adb_write_pipe = NULL; 246 handle->adb_read_pipe = NULL; 247 handle->adb_interface = NULL; 248 } 249 } 250 251 void usb_kick(usb_handle* handle) { 252 if (NULL != handle) { 253 usb_cleanup_handle(handle); 254 } else { 255 SetLastError(ERROR_INVALID_HANDLE); 256 errno = ERROR_INVALID_HANDLE; 257 } 258 } 259 260 int usb_close(usb_handle* handle) { 261 DBG("usb_close\n"); 262 263 if (NULL != handle) { 264 // Cleanup handle 265 usb_cleanup_handle(handle); 266 free(handle); 267 } 268 269 return 0; 270 } 271 272 int recognized_device(usb_handle* handle, ifc_match_func callback) { 273 struct usb_ifc_info info; 274 USB_DEVICE_DESCRIPTOR device_desc; 275 USB_INTERFACE_DESCRIPTOR interf_desc; 276 277 if (NULL == handle) 278 return 0; 279 280 // Check vendor and product id first 281 if (!AdbGetUsbDeviceDescriptor(handle->adb_interface, 282 &device_desc)) { 283 return 0; 284 } 285 286 // Then check interface properties 287 if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface, 288 &interf_desc)) { 289 return 0; 290 } 291 292 // Must have two endpoints 293 if (2 != interf_desc.bNumEndpoints) { 294 return 0; 295 } 296 297 info.dev_vendor = device_desc.idVendor; 298 info.dev_product = device_desc.idProduct; 299 info.dev_class = device_desc.bDeviceClass; 300 info.dev_subclass = device_desc.bDeviceSubClass; 301 info.dev_protocol = device_desc.bDeviceProtocol; 302 info.ifc_class = interf_desc.bInterfaceClass; 303 info.ifc_subclass = interf_desc.bInterfaceSubClass; 304 info.ifc_protocol = interf_desc.bInterfaceProtocol; 305 info.writable = 1; 306 307 // read serial number (if there is one) 308 unsigned long serial_number_len = sizeof(info.serial_number); 309 if (!AdbGetSerialNumber(handle->adb_interface, info.serial_number, 310 &serial_number_len, true)) { 311 info.serial_number[0] = 0; 312 } 313 314 info.device_path[0] = 0; 315 316 if (callback(&info) == 0) { 317 return 1; 318 } 319 320 return 0; 321 } 322 323 static usb_handle *find_usb_device(ifc_match_func callback) { 324 usb_handle* handle = NULL; 325 char entry_buffer[2048]; 326 char interf_name[2048]; 327 AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]); 328 unsigned long entry_buffer_size = sizeof(entry_buffer); 329 char* copy_name; 330 331 // Enumerate all present and active interfaces. 332 ADBAPIHANDLE enum_handle = 333 AdbEnumInterfaces(usb_class_id, true, true, true); 334 335 if (NULL == enum_handle) 336 return NULL; 337 338 while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) { 339 // TODO(vchtchetkine): FIXME - temp hack converting wchar_t into char. 340 // It would be better to change AdbNextInterface so it will return 341 // interface name as single char string. 342 const wchar_t* wchar_name = next_interface->device_name; 343 for(copy_name = interf_name; 344 L'\0' != *wchar_name; 345 wchar_name++, copy_name++) { 346 *copy_name = (char)(*wchar_name); 347 } 348 *copy_name = '\0'; 349 350 handle = do_usb_open(next_interface->device_name); 351 if (NULL != handle) { 352 // Lets see if this interface (device) belongs to us 353 if (recognized_device(handle, callback)) { 354 // found it! 355 break; 356 } else { 357 usb_cleanup_handle(handle); 358 free(handle); 359 handle = NULL; 360 } 361 } 362 363 entry_buffer_size = sizeof(entry_buffer); 364 } 365 366 AdbCloseHandle(enum_handle); 367 return handle; 368 } 369 370 usb_handle *usb_open(ifc_match_func callback) 371 { 372 return find_usb_device(callback); 373 } 374 375 // called from fastboot.c 376 void sleep(int seconds) 377 { 378 Sleep(seconds * 1000); 379 } 380