1/* 2 * Copyright (C) 2007 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#include <CoreFoundation/CoreFoundation.h> 18 19#include <IOKit/IOKitLib.h> 20#include <IOKit/IOCFPlugIn.h> 21#include <IOKit/usb/IOUSBLib.h> 22#include <IOKit/IOMessage.h> 23#include <mach/mach_port.h> 24 25#include "sysdeps.h" 26 27#include <stdio.h> 28 29#define TRACE_TAG TRACE_USB 30#include "adb.h" 31#include "usb_vendors.h" 32 33#define DBG D 34 35static IONotificationPortRef notificationPort = 0; 36static io_iterator_t* notificationIterators; 37 38struct usb_handle 39{ 40 UInt8 bulkIn; 41 UInt8 bulkOut; 42 IOUSBInterfaceInterface **interface; 43 io_object_t usbNotification; 44 unsigned int zero_mask; 45}; 46 47static CFRunLoopRef currentRunLoop = 0; 48static pthread_mutex_t start_lock; 49static pthread_cond_t start_cond; 50 51 52static void AndroidInterfaceAdded(void *refCon, io_iterator_t iterator); 53static void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator, 54 natural_t messageType, 55 void *messageArgument); 56static usb_handle* CheckInterface(IOUSBInterfaceInterface **iface, 57 UInt16 vendor, UInt16 product); 58 59static int 60InitUSB() 61{ 62 CFMutableDictionaryRef matchingDict; 63 CFRunLoopSourceRef runLoopSource; 64 SInt32 vendor, if_subclass, if_protocol; 65 unsigned i; 66 67 //* To set up asynchronous notifications, create a notification port and 68 //* add its run loop event source to the program's run loop 69 notificationPort = IONotificationPortCreate(kIOMasterPortDefault); 70 runLoopSource = IONotificationPortGetRunLoopSource(notificationPort); 71 CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode); 72 73 memset(notificationIterators, 0, sizeof(notificationIterators)); 74 75 //* loop through all supported vendors 76 for (i = 0; i < vendorIdCount; i++) { 77 //* Create our matching dictionary to find the Android device's 78 //* adb interface 79 //* IOServiceAddMatchingNotification consumes the reference, so we do 80 //* not need to release this 81 matchingDict = IOServiceMatching(kIOUSBInterfaceClassName); 82 83 if (!matchingDict) { 84 DBG("ERR: Couldn't create USB matching dictionary.\n"); 85 return -1; 86 } 87 88 //* Match based on vendor id, interface subclass and protocol 89 vendor = vendorIds[i]; 90 if_subclass = ADB_SUBCLASS; 91 if_protocol = ADB_PROTOCOL; 92 CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), 93 CFNumberCreate(kCFAllocatorDefault, 94 kCFNumberSInt32Type, &vendor)); 95 CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceSubClass), 96 CFNumberCreate(kCFAllocatorDefault, 97 kCFNumberSInt32Type, &if_subclass)); 98 CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceProtocol), 99 CFNumberCreate(kCFAllocatorDefault, 100 kCFNumberSInt32Type, &if_protocol)); 101 IOServiceAddMatchingNotification( 102 notificationPort, 103 kIOFirstMatchNotification, 104 matchingDict, 105 AndroidInterfaceAdded, 106 NULL, 107 ¬ificationIterators[i]); 108 109 //* Iterate over set of matching interfaces to access already-present 110 //* devices and to arm the notification 111 AndroidInterfaceAdded(NULL, notificationIterators[i]); 112 } 113 114 return 0; 115} 116 117static void 118AndroidInterfaceAdded(void *refCon, io_iterator_t iterator) 119{ 120 kern_return_t kr; 121 io_service_t usbDevice; 122 io_service_t usbInterface; 123 IOCFPlugInInterface **plugInInterface = NULL; 124 IOUSBInterfaceInterface220 **iface = NULL; 125 IOUSBDeviceInterface197 **dev = NULL; 126 HRESULT result; 127 SInt32 score; 128 UInt16 vendor; 129 UInt16 product; 130 UInt8 serialIndex; 131 char serial[256]; 132 133 while ((usbInterface = IOIteratorNext(iterator))) { 134 //* Create an intermediate interface plugin 135 kr = IOCreatePlugInInterfaceForService(usbInterface, 136 kIOUSBInterfaceUserClientTypeID, 137 kIOCFPlugInInterfaceID, 138 &plugInInterface, &score); 139 IOObjectRelease(usbInterface); 140 if ((kIOReturnSuccess != kr) || (!plugInInterface)) { 141 DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr); 142 continue; 143 } 144 145 //* This gets us the interface object 146 result = (*plugInInterface)->QueryInterface(plugInInterface, 147 CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID) 148 &iface); 149 //* We only needed the plugin to get the interface, so discard it 150 (*plugInInterface)->Release(plugInInterface); 151 if (result || !iface) { 152 DBG("ERR: Couldn't query the interface (%08x)\n", (int) result); 153 continue; 154 } 155 156 //* this gets us an ioservice, with which we will find the actual 157 //* device; after getting a plugin, and querying the interface, of 158 //* course. 159 //* Gotta love OS X 160 kr = (*iface)->GetDevice(iface, &usbDevice); 161 if (kIOReturnSuccess != kr || !usbDevice) { 162 DBG("ERR: Couldn't grab device from interface (%08x)\n", kr); 163 continue; 164 } 165 166 plugInInterface = NULL; 167 score = 0; 168 //* create an intermediate device plugin 169 kr = IOCreatePlugInInterfaceForService(usbDevice, 170 kIOUSBDeviceUserClientTypeID, 171 kIOCFPlugInInterfaceID, 172 &plugInInterface, &score); 173 //* only needed this to find the plugin 174 (void)IOObjectRelease(usbDevice); 175 if ((kIOReturnSuccess != kr) || (!plugInInterface)) { 176 DBG("ERR: Unable to create a device plug-in (%08x)\n", kr); 177 continue; 178 } 179 180 result = (*plugInInterface)->QueryInterface(plugInInterface, 181 CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev); 182 //* only needed this to query the plugin 183 (*plugInInterface)->Release(plugInInterface); 184 if (result || !dev) { 185 DBG("ERR: Couldn't create a device interface (%08x)\n", 186 (int) result); 187 continue; 188 } 189 190 //* Now after all that, we actually have a ref to the device and 191 //* the interface that matched our criteria 192 193 kr = (*dev)->GetDeviceVendor(dev, &vendor); 194 kr = (*dev)->GetDeviceProduct(dev, &product); 195 kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex); 196 197 if (serialIndex > 0) { 198 IOUSBDevRequest req; 199 UInt16 buffer[256]; 200 UInt16 languages[128]; 201 202 memset(languages, 0, sizeof(languages)); 203 204 req.bmRequestType = 205 USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); 206 req.bRequest = kUSBRqGetDescriptor; 207 req.wValue = (kUSBStringDesc << 8) | 0; 208 req.wIndex = 0; 209 req.pData = languages; 210 req.wLength = sizeof(languages); 211 kr = (*dev)->DeviceRequest(dev, &req); 212 213 if (kr == kIOReturnSuccess && req.wLenDone > 0) { 214 215 int langCount = (req.wLenDone - 2) / 2, lang; 216 217 for (lang = 1; lang <= langCount; lang++) { 218 219 memset(buffer, 0, sizeof(buffer)); 220 memset(&req, 0, sizeof(req)); 221 222 req.bmRequestType = 223 USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); 224 req.bRequest = kUSBRqGetDescriptor; 225 req.wValue = (kUSBStringDesc << 8) | serialIndex; 226 req.wIndex = languages[lang]; 227 req.pData = buffer; 228 req.wLength = sizeof(buffer); 229 kr = (*dev)->DeviceRequest(dev, &req); 230 231 if (kr == kIOReturnSuccess && req.wLenDone > 0) { 232 int i, count; 233 234 // skip first word, and copy the rest to the serial string, 235 // changing shorts to bytes. 236 count = (req.wLenDone - 1) / 2; 237 for (i = 0; i < count; i++) 238 serial[i] = buffer[i + 1]; 239 serial[i] = 0; 240 break; 241 } 242 } 243 } 244 } 245 (*dev)->Release(dev); 246 247 DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product, 248 serial); 249 250 usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface, 251 vendor, product); 252 if (handle == NULL) { 253 DBG("ERR: Could not find device interface: %08x\n", kr); 254 (*iface)->Release(iface); 255 continue; 256 } 257 258 DBG("AndroidDeviceAdded calling register_usb_transport\n"); 259 register_usb_transport(handle, (serial[0] ? serial : NULL), 1); 260 261 // Register for an interest notification of this device being removed. 262 // Pass the reference to our private data as the refCon for the 263 // notification. 264 kr = IOServiceAddInterestNotification(notificationPort, 265 usbInterface, 266 kIOGeneralInterest, 267 AndroidInterfaceNotify, 268 handle, 269 &handle->usbNotification); 270 271 if (kIOReturnSuccess != kr) { 272 DBG("ERR: Unable to create interest notification (%08x)\n", kr); 273 } 274 } 275} 276 277static void 278AndroidInterfaceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) 279{ 280 usb_handle *handle = (usb_handle *)refCon; 281 282 if (messageType == kIOMessageServiceIsTerminated) { 283 if (!handle) { 284 DBG("ERR: NULL handle\n"); 285 return; 286 } 287 DBG("AndroidInterfaceNotify\n"); 288 IOObjectRelease(handle->usbNotification); 289 usb_kick(handle); 290 } 291} 292 293//* TODO: simplify this further since we only register to get ADB interface 294//* subclass+protocol events 295static usb_handle* 296CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product) 297{ 298 usb_handle* handle = NULL; 299 IOReturn kr; 300 UInt8 interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol; 301 UInt8 endpoint; 302 303 304 //* Now open the interface. This will cause the pipes associated with 305 //* the endpoints in the interface descriptor to be instantiated 306 kr = (*interface)->USBInterfaceOpen(interface); 307 if (kr != kIOReturnSuccess) { 308 DBG("ERR: Could not open interface: (%08x)\n", kr); 309 return NULL; 310 } 311 312 //* Get the number of endpoints associated with this interface 313 kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints); 314 if (kr != kIOReturnSuccess) { 315 DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr); 316 goto err_get_num_ep; 317 } 318 319 //* Get interface class, subclass and protocol 320 if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess || 321 (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess || 322 (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) { 323 DBG("ERR: Unable to get interface class, subclass and protocol\n"); 324 goto err_get_interface_class; 325 } 326 327 //* check to make sure interface class, subclass and protocol match ADB 328 //* avoid opening mass storage endpoints 329 if (!is_adb_interface(vendor, product, interfaceClass, 330 interfaceSubClass, interfaceProtocol)) 331 goto err_bad_adb_interface; 332 333 handle = calloc(1, sizeof(usb_handle)); 334 335 //* Iterate over the endpoints for this interface and find the first 336 //* bulk in/out pipes available. These will be our read/write pipes. 337 for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) { 338 UInt8 transferType; 339 UInt16 maxPacketSize; 340 UInt8 interval; 341 UInt8 number; 342 UInt8 direction; 343 344 kr = (*interface)->GetPipeProperties(interface, endpoint, &direction, 345 &number, &transferType, &maxPacketSize, &interval); 346 347 if (kIOReturnSuccess == kr) { 348 if (kUSBBulk != transferType) 349 continue; 350 351 if (kUSBIn == direction) 352 handle->bulkIn = endpoint; 353 354 if (kUSBOut == direction) 355 handle->bulkOut = endpoint; 356 357 handle->zero_mask = maxPacketSize - 1; 358 } else { 359 DBG("ERR: FindDeviceInterface - could not get pipe properties\n"); 360 goto err_get_pipe_props; 361 } 362 } 363 364 handle->interface = interface; 365 return handle; 366 367err_get_pipe_props: 368 free(handle); 369err_bad_adb_interface: 370err_get_interface_class: 371err_get_num_ep: 372 (*interface)->USBInterfaceClose(interface); 373 return NULL; 374} 375 376 377void* RunLoopThread(void* unused) 378{ 379 unsigned i; 380 381 InitUSB(); 382 383 currentRunLoop = CFRunLoopGetCurrent(); 384 385 // Signal the parent that we are running 386 adb_mutex_lock(&start_lock); 387 adb_cond_signal(&start_cond); 388 adb_mutex_unlock(&start_lock); 389 390 CFRunLoopRun(); 391 currentRunLoop = 0; 392 393 for (i = 0; i < vendorIdCount; i++) { 394 IOObjectRelease(notificationIterators[i]); 395 } 396 IONotificationPortDestroy(notificationPort); 397 398 DBG("RunLoopThread done\n"); 399 return NULL; 400} 401 402 403static int initialized = 0; 404void usb_init() 405{ 406 if (!initialized) 407 { 408 adb_thread_t tid; 409 410 notificationIterators = (io_iterator_t*)malloc( 411 vendorIdCount * sizeof(io_iterator_t)); 412 413 adb_mutex_init(&start_lock, NULL); 414 adb_cond_init(&start_cond, NULL); 415 416 if(adb_thread_create(&tid, RunLoopThread, NULL)) 417 fatal_errno("cannot create input thread"); 418 419 // Wait for initialization to finish 420 adb_mutex_lock(&start_lock); 421 adb_cond_wait(&start_cond, &start_lock); 422 adb_mutex_unlock(&start_lock); 423 424 adb_mutex_destroy(&start_lock); 425 adb_cond_destroy(&start_cond); 426 427 initialized = 1; 428 } 429} 430 431void usb_cleanup() 432{ 433 DBG("usb_cleanup\n"); 434 close_usb_devices(); 435 if (currentRunLoop) 436 CFRunLoopStop(currentRunLoop); 437 438 if (notificationIterators != NULL) { 439 free(notificationIterators); 440 notificationIterators = NULL; 441 } 442} 443 444int usb_write(usb_handle *handle, const void *buf, int len) 445{ 446 IOReturn result; 447 448 if (!len) 449 return 0; 450 451 if (!handle) 452 return -1; 453 454 if (NULL == handle->interface) { 455 DBG("ERR: usb_write interface was null\n"); 456 return -1; 457 } 458 459 if (0 == handle->bulkOut) { 460 DBG("ERR: bulkOut endpoint not assigned\n"); 461 return -1; 462 } 463 464 result = 465 (*handle->interface)->WritePipe( 466 handle->interface, handle->bulkOut, (void *)buf, len); 467 468 if ((result == 0) && (handle->zero_mask)) { 469 /* we need 0-markers and our transfer */ 470 if(!(len & handle->zero_mask)) { 471 result = 472 (*handle->interface)->WritePipe( 473 handle->interface, handle->bulkOut, (void *)buf, 0); 474 } 475 } 476 477 if (0 == result) 478 return 0; 479 480 DBG("ERR: usb_write failed with status %d\n", result); 481 return -1; 482} 483 484int usb_read(usb_handle *handle, void *buf, int len) 485{ 486 IOReturn result; 487 UInt32 numBytes = len; 488 489 if (!len) { 490 return 0; 491 } 492 493 if (!handle) { 494 return -1; 495 } 496 497 if (NULL == handle->interface) { 498 DBG("ERR: usb_read interface was null\n"); 499 return -1; 500 } 501 502 if (0 == handle->bulkIn) { 503 DBG("ERR: bulkIn endpoint not assigned\n"); 504 return -1; 505 } 506 507 result = 508 (*handle->interface)->ReadPipe(handle->interface, 509 handle->bulkIn, buf, &numBytes); 510 511 if (0 == result) 512 return 0; 513 else { 514 DBG("ERR: usb_read failed with status %d\n", result); 515 } 516 517 return -1; 518} 519 520int usb_close(usb_handle *handle) 521{ 522 return 0; 523} 524 525void usb_kick(usb_handle *handle) 526{ 527 /* release the interface */ 528 if (!handle) 529 return; 530 531 if (handle->interface) 532 { 533 (*handle->interface)->USBInterfaceClose(handle->interface); 534 (*handle->interface)->Release(handle->interface); 535 handle->interface = 0; 536 } 537} 538