usb_windows.c revision 913eb8bf874fcec647667bd7113da65b6e38488a
18ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian/* 28ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * Copyright (C) 2008 The Android Open Source Project 38ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * All rights reserved. 48ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * 58ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * Redistribution and use in source and binary forms, with or without 68ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * modification, are permitted provided that the following conditions 78ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * are met: 88ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * * Redistributions of source code must retain the above copyright 98ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * notice, this list of conditions and the following disclaimer. 108ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * * Redistributions in binary form must reproduce the above copyright 118ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * notice, this list of conditions and the following disclaimer in 128ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * the documentation and/or other materials provided with the 138ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * distribution. 148ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * 158ae2335a3c93d0c00e998fdec18f64dfe43b94cbMathias Agopian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16d2110dbce071a236b6176de344ca797b737542ebJoe Onorato * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17b13b9bdad2baf6ad1ec2e56b6b7598fa20f55fc4Mathias Agopian * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18d2110dbce071a236b6176de344ca797b737542ebJoe Onorato * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19d2110dbce071a236b6176de344ca797b737542ebJoe Onorato * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20d2110dbce071a236b6176de344ca797b737542ebJoe Onorato * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21d2110dbce071a236b6176de344ca797b737542ebJoe Onorato * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22d2110dbce071a236b6176de344ca797b737542ebJoe Onorato * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23d2110dbce071a236b6176de344ca797b737542ebJoe Onorato * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24d2110dbce071a236b6176de344ca797b737542ebJoe Onorato * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25d2110dbce071a236b6176de344ca797b737542ebJoe Onorato * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26d2110dbce071a236b6176de344ca797b737542ebJoe Onorato * SUCH DAMAGE. 27d2110dbce071a236b6176de344ca797b737542ebJoe Onorato */ 28d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 29d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#include <windows.h> 30d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#include <winerror.h> 31d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#include <errno.h> 32d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#include <usb100.h> 33d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#include <adb_api.h> 34d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#include <stdio.h> 35d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 36d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#include "usb.h" 37d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 38d2110dbce071a236b6176de344ca797b737542ebJoe Onorato//#define TRACE_USB 1 39d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#if TRACE_USB 40d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#define DBG(x...) fprintf(stderr, x) 41d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#else 42d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#define DBG(x...) 43d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#endif 44d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 45d2110dbce071a236b6176de344ca797b737542ebJoe Onorato#define MAX_USBFS_BULK_SIZE (1024 * 1024) 46d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 47d2110dbce071a236b6176de344ca797b737542ebJoe Onorato/** Structure usb_handle describes our connection to the usb device via 48d2110dbce071a236b6176de344ca797b737542ebJoe Onorato AdbWinApi.dll. This structure is returned from usb_open() routine and 49d2110dbce071a236b6176de344ca797b737542ebJoe Onorato is expected in each subsequent call that is accessing the device. 50d2110dbce071a236b6176de344ca797b737542ebJoe Onorato*/ 51d2110dbce071a236b6176de344ca797b737542ebJoe Onoratostruct usb_handle { 52d2110dbce071a236b6176de344ca797b737542ebJoe Onorato /// Handle to USB interface 53d2110dbce071a236b6176de344ca797b737542ebJoe Onorato ADBAPIHANDLE adb_interface; 54d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 55d2110dbce071a236b6176de344ca797b737542ebJoe Onorato /// Handle to USB read pipe (endpoint) 56d2110dbce071a236b6176de344ca797b737542ebJoe Onorato ADBAPIHANDLE adb_read_pipe; 57d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 58d2110dbce071a236b6176de344ca797b737542ebJoe Onorato /// Handle to USB write pipe (endpoint) 59d2110dbce071a236b6176de344ca797b737542ebJoe Onorato ADBAPIHANDLE adb_write_pipe; 60d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 61d2110dbce071a236b6176de344ca797b737542ebJoe Onorato /// Interface name 62d2110dbce071a236b6176de344ca797b737542ebJoe Onorato char* interface_name; 63d2110dbce071a236b6176de344ca797b737542ebJoe Onorato}; 64d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 65d2110dbce071a236b6176de344ca797b737542ebJoe Onorato/// Class ID assigned to the device by androidusb.sys 66d2110dbce071a236b6176de344ca797b737542ebJoe Onoratostatic const GUID usb_class_id = ANDROID_USB_CLASS_ID; 675f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato 68d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 69d2110dbce071a236b6176de344ca797b737542ebJoe Onorato/// Checks if interface (device) matches certain criteria 705f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onoratoint recognized_device(usb_handle* handle, ifc_match_func callback); 715f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato 725f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onorato/// Opens usb interface (device) by interface (device) name. 735f15d151b5101fadfe6cba1e8f4aa6367e8c603eJoe Onoratousb_handle* do_usb_open(const wchar_t* interface_name); 74d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 75d2110dbce071a236b6176de344ca797b737542ebJoe Onorato/// Writes data to the opened usb handle 76d2110dbce071a236b6176de344ca797b737542ebJoe Onoratoint usb_write(usb_handle* handle, const void* data, int len); 77d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 78d2110dbce071a236b6176de344ca797b737542ebJoe Onorato/// Reads data using the opened usb handle 79d2110dbce071a236b6176de344ca797b737542ebJoe Onoratoint usb_read(usb_handle *handle, void* data, int len); 80d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 81d2110dbce071a236b6176de344ca797b737542ebJoe Onorato/// Cleans up opened usb handle 82d2110dbce071a236b6176de344ca797b737542ebJoe Onoratovoid usb_cleanup_handle(usb_handle* handle); 83d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 84d2110dbce071a236b6176de344ca797b737542ebJoe Onorato/// Cleans up (but don't close) opened usb handle 85d2110dbce071a236b6176de344ca797b737542ebJoe Onoratovoid usb_kick(usb_handle* handle); 86d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 87d2110dbce071a236b6176de344ca797b737542ebJoe Onorato/// Closes opened usb handle 88d2110dbce071a236b6176de344ca797b737542ebJoe Onoratoint usb_close(usb_handle* handle); 89d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 90d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 91d2110dbce071a236b6176de344ca797b737542ebJoe Onoratousb_handle* do_usb_open(const wchar_t* interface_name) { 92d2110dbce071a236b6176de344ca797b737542ebJoe Onorato // Allocate our handle 93d2110dbce071a236b6176de344ca797b737542ebJoe Onorato usb_handle* ret = (usb_handle*)malloc(sizeof(usb_handle)); 94d2110dbce071a236b6176de344ca797b737542ebJoe Onorato if (NULL == ret) 95d2110dbce071a236b6176de344ca797b737542ebJoe Onorato return NULL; 96d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 97d2110dbce071a236b6176de344ca797b737542ebJoe Onorato // Create interface. 98d2110dbce071a236b6176de344ca797b737542ebJoe Onorato ret->adb_interface = AdbCreateInterfaceByName(interface_name); 99d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 100d2110dbce071a236b6176de344ca797b737542ebJoe Onorato if (NULL == ret->adb_interface) { 101d2110dbce071a236b6176de344ca797b737542ebJoe Onorato free(ret); 102d2110dbce071a236b6176de344ca797b737542ebJoe Onorato errno = GetLastError(); 103d2110dbce071a236b6176de344ca797b737542ebJoe Onorato return NULL; 104d2110dbce071a236b6176de344ca797b737542ebJoe Onorato } 105d2110dbce071a236b6176de344ca797b737542ebJoe Onorato 106d2110dbce071a236b6176de344ca797b737542ebJoe Onorato // Open read pipe (endpoint) 107d2110dbce071a236b6176de344ca797b737542ebJoe Onorato ret->adb_read_pipe = 108d2110dbce071a236b6176de344ca797b737542ebJoe Onorato AdbOpenDefaultBulkReadEndpoint(ret->adb_interface, 109d2110dbce071a236b6176de344ca797b737542ebJoe Onorato AdbOpenAccessTypeReadWrite, 110d2110dbce071a236b6176de344ca797b737542ebJoe Onorato AdbOpenSharingModeReadWrite); 111d2110dbce071a236b6176de344ca797b737542ebJoe Onorato if (NULL != ret->adb_read_pipe) { 112d2110dbce071a236b6176de344ca797b737542ebJoe Onorato // Open write pipe (endpoint) 113d2110dbce071a236b6176de344ca797b737542ebJoe Onorato ret->adb_write_pipe = 114d2110dbce071a236b6176de344ca797b737542ebJoe Onorato AdbOpenDefaultBulkWriteEndpoint(ret->adb_interface, 115d2110dbce071a236b6176de344ca797b737542ebJoe Onorato AdbOpenAccessTypeReadWrite, 116d2110dbce071a236b6176de344ca797b737542ebJoe Onorato AdbOpenSharingModeReadWrite); 117d2110dbce071a236b6176de344ca797b737542ebJoe Onorato if (NULL != ret->adb_write_pipe) { 118d2110dbce071a236b6176de344ca797b737542ebJoe Onorato // 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 = 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 196int 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 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 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 if (callback(&info) == 0) { 315 return 1; 316 } 317 318 return 0; 319} 320 321static usb_handle *find_usb_device(ifc_match_func callback) { 322 usb_handle* handle = NULL; 323 char entry_buffer[2048]; 324 char interf_name[2048]; 325 AdbInterfaceInfo* next_interface = (AdbInterfaceInfo*)(&entry_buffer[0]); 326 unsigned long entry_buffer_size = sizeof(entry_buffer); 327 char* copy_name; 328 329 // Enumerate all present and active interfaces. 330 ADBAPIHANDLE enum_handle = 331 AdbEnumInterfaces(usb_class_id, true, true, true); 332 333 if (NULL == enum_handle) 334 return NULL; 335 336 while (AdbNextInterface(enum_handle, next_interface, &entry_buffer_size)) { 337 // TODO(vchtchetkine): FIXME - temp hack converting wchar_t into char. 338 // It would be better to change AdbNextInterface so it will return 339 // interface name as single char string. 340 const wchar_t* wchar_name = next_interface->device_name; 341 for(copy_name = interf_name; 342 L'\0' != *wchar_name; 343 wchar_name++, copy_name++) { 344 *copy_name = (char)(*wchar_name); 345 } 346 *copy_name = '\0'; 347 348 handle = do_usb_open(next_interface->device_name); 349 if (NULL != handle) { 350 // Lets see if this interface (device) belongs to us 351 if (recognized_device(handle, callback)) { 352 // found it! 353 break; 354 } else { 355 usb_cleanup_handle(handle); 356 free(handle); 357 handle = NULL; 358 } 359 } 360 361 entry_buffer_size = sizeof(entry_buffer); 362 } 363 364 AdbCloseHandle(enum_handle); 365 return handle; 366} 367 368usb_handle *usb_open(ifc_match_func callback) 369{ 370 return find_usb_device(callback); 371} 372 373// called from fastboot.c 374void sleep(int seconds) 375{ 376 Sleep(seconds * 1000); 377} 378