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