usb_windows.c revision 5957c1ffe79b34d8b1859f9f11644d1007193cbc
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*/ 51struct 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 66static const GUID usb_class_id = ANDROID_USB_CLASS_ID; 67 68 69/// Checks if interface (device) matches certain criteria 70int recognized_device(usb_handle* handle, ifc_match_func callback); 71 72/// Opens usb interface (device) by interface (device) name. 73usb_handle* do_usb_open(const wchar_t* interface_name); 74 75/// Writes data to the opened usb handle 76int usb_write(usb_handle* handle, const void* data, int len); 77 78/// Reads data using the opened usb handle 79int usb_read(usb_handle *handle, void* data, int len); 80 81/// Cleans up opened usb handle 82void usb_cleanup_handle(usb_handle* handle); 83 84/// Cleans up (but don't close) opened usb handle 85void usb_kick(usb_handle* handle); 86 87/// Closes opened usb handle 88int usb_close(usb_handle* handle); 89 90 91usb_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 154int usb_write(usb_handle* handle, const void* data, int len) { 155 unsigned long time_out = 5000; 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 = (const char *)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 196int usb_read(usb_handle *handle, void* data, int len) { 197 unsigned long time_out = 0; 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 { 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 233void 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 251void 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 260int 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 272int usb_wait_for_disconnect(usb_handle *usb) { 273 /* TODO: Punt for now */ 274 return 0; 275} 276 277int recognized_device(usb_handle* handle, ifc_match_func callback) { 278 struct usb_ifc_info info; 279 USB_DEVICE_DESCRIPTOR device_desc; 280 USB_INTERFACE_DESCRIPTOR interf_desc; 281 282 if (NULL == handle) 283 return 0; 284 285 // Check vendor and product id first 286 if (!AdbGetUsbDeviceDescriptor(handle->adb_interface, 287 &device_desc)) { 288 return 0; 289 } 290 291 // Then check interface properties 292 if (!AdbGetUsbInterfaceDescriptor(handle->adb_interface, 293 &interf_desc)) { 294 return 0; 295 } 296 297 // Must have two endpoints 298 if (2 != interf_desc.bNumEndpoints) { 299 return 0; 300 } 301 302 info.dev_vendor = device_desc.idVendor; 303 info.dev_product = device_desc.idProduct; 304 info.dev_class = device_desc.bDeviceClass; 305 info.dev_subclass = device_desc.bDeviceSubClass; 306 info.dev_protocol = device_desc.bDeviceProtocol; 307 info.ifc_class = interf_desc.bInterfaceClass; 308 info.ifc_subclass = interf_desc.bInterfaceSubClass; 309 info.ifc_protocol = interf_desc.bInterfaceProtocol; 310 info.writable = 1; 311 312 // read serial number (if there is one) 313 unsigned long serial_number_len = sizeof(info.serial_number); 314 if (!AdbGetSerialNumber(handle->adb_interface, info.serial_number, 315 &serial_number_len, true)) { 316 info.serial_number[0] = 0; 317 } 318 319 info.device_path[0] = 0; 320 321 if (callback(&info) == 0) { 322 return 1; 323 } 324 325 return 0; 326} 327 328static usb_handle *find_usb_device(ifc_match_func callback) { 329 usb_handle* handle = NULL; 330 char entry_buffer[2048]; 331 char interf_name[2048]; 332 AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]); 333 unsigned long entry_buffer_size = sizeof(entry_buffer); 334 char* copy_name; 335 336 // Enumerate all present and active interfaces. 337 ADBAPIHANDLE enum_handle = 338 AdbEnumInterfaces(usb_class_id, true, true, true); 339 340 if (NULL == enum_handle) 341 return NULL; 342 343 while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) { 344 // TODO(vchtchetkine): FIXME - temp hack converting wchar_t into char. 345 // It would be better to change AdbNextInterface so it will return 346 // interface name as single char string. 347 const wchar_t* wchar_name = next_interface->device_name; 348 for(copy_name = interf_name; 349 L'\0' != *wchar_name; 350 wchar_name++, copy_name++) { 351 *copy_name = (char)(*wchar_name); 352 } 353 *copy_name = '\0'; 354 355 handle = do_usb_open(next_interface->device_name); 356 if (NULL != handle) { 357 // Lets see if this interface (device) belongs to us 358 if (recognized_device(handle, callback)) { 359 // found it! 360 break; 361 } else { 362 usb_cleanup_handle(handle); 363 free(handle); 364 handle = NULL; 365 } 366 } 367 368 entry_buffer_size = sizeof(entry_buffer); 369 } 370 371 AdbCloseHandle(enum_handle); 372 return handle; 373} 374 375usb_handle *usb_open(ifc_match_func callback) 376{ 377 return find_usb_device(callback); 378} 379 380// called from fastboot.c 381void sleep(int seconds) 382{ 383 Sleep(seconds * 1000); 384} 385