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 #include <stdlib.h> 36 37 #include "usb.h" 38 39 //#define TRACE_USB 1 40 #if TRACE_USB 41 #define DBG(x...) fprintf(stderr, x) 42 #else 43 #define DBG(x...) 44 #endif 45 46 #define MAX_USBFS_BULK_SIZE (1024 * 1024) 47 48 /** Structure usb_handle describes our connection to the usb device via 49 AdbWinApi.dll. This structure is returned from usb_open() routine and 50 is expected in each subsequent call that is accessing the device. 51 */ 52 struct usb_handle { 53 /// Handle to USB interface 54 ADBAPIHANDLE adb_interface; 55 56 /// Handle to USB read pipe (endpoint) 57 ADBAPIHANDLE adb_read_pipe; 58 59 /// Handle to USB write pipe (endpoint) 60 ADBAPIHANDLE adb_write_pipe; 61 62 /// Interface name 63 char* interface_name; 64 }; 65 66 /// Class ID assigned to the device by androidusb.sys 67 static const GUID usb_class_id = ANDROID_USB_CLASS_ID; 68 69 70 /// Checks if interface (device) matches certain criteria 71 int recognized_device(usb_handle* handle, ifc_match_func callback); 72 73 /// Opens usb interface (device) by interface (device) name. 74 usb_handle* do_usb_open(const wchar_t* interface_name); 75 76 /// Writes data to the opened usb handle 77 int usb_write(usb_handle* handle, const void* data, int len); 78 79 /// Reads data using the opened usb handle 80 int usb_read(usb_handle *handle, void* data, int len); 81 82 /// Cleans up opened usb handle 83 void usb_cleanup_handle(usb_handle* handle); 84 85 /// Cleans up (but don't close) opened usb handle 86 void usb_kick(usb_handle* handle); 87 88 /// Closes opened usb handle 89 int usb_close(usb_handle* handle); 90 91 92 usb_handle* do_usb_open(const wchar_t* interface_name) { 93 // Allocate our handle 94 usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle)); 95 if (NULL == ret) 96 return NULL; 97 98 // Create interface. 99 ret->adb_interface = AdbCreateInterfaceByName(interface_name); 100 101 if (NULL == ret->adb_interface) { 102 free(ret); 103 errno = GetLastError(); 104 return NULL; 105 } 106 107 // Open read pipe (endpoint) 108 ret->adb_read_pipe = 109 AdbOpenDefaultBulkReadEndpoint(ret->adb_interface, 110 AdbOpenAccessTypeReadWrite, 111 AdbOpenSharingModeReadWrite); 112 if (NULL != ret->adb_read_pipe) { 113 // Open write pipe (endpoint) 114 ret->adb_write_pipe = 115 AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface, 116 AdbOpenAccessTypeReadWrite, 117 AdbOpenSharingModeReadWrite); 118 if (NULL != ret->adb_write_pipe) { 119 // Save interface name 120 unsigned long name_len = 0; 121 122 // First get expected name length 123 AdbGetInterfaceName(ret->adb_interface, 124 NULL, 125 &name_len, 126 true); 127 if (0 != name_len) { 128 ret->interface_name = (char*)malloc(name_len); 129 130 if (NULL != ret->interface_name) { 131 // Now save the name 132 if (AdbGetInterfaceName(ret->adb_interface, 133 ret->interface_name, 134 &name_len, 135 true)) { 136 // We're done at this point 137 return ret; 138 } 139 } else { 140 SetLastError(ERROR_OUTOFMEMORY); 141 } 142 } 143 } 144 } 145 146 // Something went wrong. 147 errno = GetLastError(); 148 usb_cleanup_handle(ret); 149 free(ret); 150 SetLastError(errno); 151 152 return NULL; 153 } 154 155 int usb_write(usb_handle* handle, const void* data, int len) { 156 unsigned long time_out = 5000; 157 unsigned long written = 0; 158 unsigned count = 0; 159 int ret; 160 161 DBG("usb_write %d\n", len); 162 if (NULL != handle) { 163 // Perform write 164 while(len > 0) { 165 int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; 166 ret = AdbWriteEndpointSync(handle->adb_write_pipe, 167 (void*)data, 168 (unsigned long)xfer, 169 &written, 170 time_out); 171 errno = GetLastError(); 172 DBG("AdbWriteEndpointSync returned %d, errno: %d\n", ret, errno); 173 if (ret == 0) { 174 // assume ERROR_INVALID_HANDLE indicates we are disconnected 175 if (errno == ERROR_INVALID_HANDLE) 176 usb_kick(handle); 177 return -1; 178 } 179 180 count += written; 181 len -= written; 182 data = (const char *)data + written; 183 184 if (len == 0) 185 return count; 186 } 187 } else { 188 DBG("usb_write NULL handle\n"); 189 SetLastError(ERROR_INVALID_HANDLE); 190 } 191 192 DBG("usb_write failed: %d\n", errno); 193 194 return -1; 195 } 196 197 int usb_read(usb_handle *handle, void* data, int len) { 198 unsigned long time_out = 0; 199 unsigned long read = 0; 200 int ret; 201 202 DBG("usb_read %d\n", len); 203 if (NULL != handle) { 204 while (1) { 205 int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; 206 207 ret = AdbReadEndpointSync(handle->adb_read_pipe, 208 (void*)data, 209 (unsigned long)xfer, 210 &read, 211 time_out); 212 errno = GetLastError(); 213 DBG("usb_read got: %ld, expected: %d, errno: %d\n", read, xfer, errno); 214 if (ret) { 215 return read; 216 } else { 217 // assume ERROR_INVALID_HANDLE indicates we are disconnected 218 if (errno == ERROR_INVALID_HANDLE) 219 usb_kick(handle); 220 break; 221 } 222 // else we timed out - try again 223 } 224 } else { 225 DBG("usb_read NULL handle\n"); 226 SetLastError(ERROR_INVALID_HANDLE); 227 } 228 229 DBG("usb_read failed: %d\n", errno); 230 231 return -1; 232 } 233 234 void usb_cleanup_handle(usb_handle* handle) { 235 if (NULL != handle) { 236 if (NULL != handle->interface_name) 237 free(handle->interface_name); 238 if (NULL != handle->adb_write_pipe) 239 AdbCloseHandle(handle->adb_write_pipe); 240 if (NULL != handle->adb_read_pipe) 241 AdbCloseHandle(handle->adb_read_pipe); 242 if (NULL != handle->adb_interface) 243 AdbCloseHandle(handle->adb_interface); 244 245 handle->interface_name = NULL; 246 handle->adb_write_pipe = NULL; 247 handle->adb_read_pipe = NULL; 248 handle->adb_interface = NULL; 249 } 250 } 251 252 void usb_kick(usb_handle* handle) { 253 if (NULL != handle) { 254 usb_cleanup_handle(handle); 255 } else { 256 SetLastError(ERROR_INVALID_HANDLE); 257 errno = ERROR_INVALID_HANDLE; 258 } 259 } 260 261 int usb_close(usb_handle* handle) { 262 DBG("usb_close\n"); 263 264 if (NULL != handle) { 265 // Cleanup handle 266 usb_cleanup_handle(handle); 267 free(handle); 268 } 269 270 return 0; 271 } 272 273 int usb_wait_for_disconnect(usb_handle *usb) { 274 /* TODO: Punt for now */ 275 return 0; 276 } 277 278 int recognized_device(usb_handle* handle, ifc_match_func callback) { 279 struct usb_ifc_info info; 280 USB_DEVICE_DESCRIPTOR device_desc; 281 USB_INTERFACE_DESCRIPTOR interf_desc; 282 283 if (NULL == handle) 284 return 0; 285 286 // Check vendor and product id first 287 if (!AdbGetUsbDeviceDescriptor(handle->adb_interface, 288 &device_desc)) { 289 return 0; 290 } 291 292 // Then check interface properties 293 if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface, 294 &interf_desc)) { 295 return 0; 296 } 297 298 // Must have two endpoints 299 if (2 != interf_desc.bNumEndpoints) { 300 return 0; 301 } 302 303 info.dev_vendor = device_desc.idVendor; 304 info.dev_product = device_desc.idProduct; 305 info.dev_class = device_desc.bDeviceClass; 306 info.dev_subclass = device_desc.bDeviceSubClass; 307 info.dev_protocol = device_desc.bDeviceProtocol; 308 info.ifc_class = interf_desc.bInterfaceClass; 309 info.ifc_subclass = interf_desc.bInterfaceSubClass; 310 info.ifc_protocol = interf_desc.bInterfaceProtocol; 311 info.writable = 1; 312 313 // read serial number (if there is one) 314 unsigned long serial_number_len = sizeof(info.serial_number); 315 if (!AdbGetSerialNumber(handle->adb_interface, info.serial_number, 316 &serial_number_len, true)) { 317 info.serial_number[0] = 0; 318 } 319 320 info.device_path[0] = 0; 321 322 if (callback(&info) == 0) { 323 return 1; 324 } 325 326 return 0; 327 } 328 329 static usb_handle *find_usb_device(ifc_match_func callback) { 330 usb_handle* handle = NULL; 331 char entry_buffer[2048]; 332 char interf_name[2048]; 333 AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]); 334 unsigned long entry_buffer_size = sizeof(entry_buffer); 335 char* copy_name; 336 337 // Enumerate all present and active interfaces. 338 ADBAPIHANDLE enum_handle = 339 AdbEnumInterfaces(usb_class_id, true, true, true); 340 341 if (NULL == enum_handle) 342 return NULL; 343 344 while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) { 345 // TODO(vchtchetkine): FIXME - temp hack converting wchar_t into char. 346 // It would be better to change AdbNextInterface so it will return 347 // interface name as single char string. 348 const wchar_t* wchar_name = next_interface->device_name; 349 for(copy_name = interf_name; 350 L'\0' != *wchar_name; 351 wchar_name++, copy_name++) { 352 *copy_name = (char)(*wchar_name); 353 } 354 *copy_name = '\0'; 355 356 handle = do_usb_open(next_interface->device_name); 357 if (NULL != handle) { 358 // Lets see if this interface (device) belongs to us 359 if (recognized_device(handle, callback)) { 360 // found it! 361 break; 362 } else { 363 usb_cleanup_handle(handle); 364 free(handle); 365 handle = NULL; 366 } 367 } 368 369 entry_buffer_size = sizeof(entry_buffer); 370 } 371 372 AdbCloseHandle(enum_handle); 373 return handle; 374 } 375 376 usb_handle *usb_open(ifc_match_func callback) 377 { 378 return find_usb_device(callback); 379 } 380 381 // called from fastboot.c 382 void sleep(int seconds) 383 { 384 Sleep(seconds * 1000); 385 } 386