Home | History | Annotate | Download | only in adb
      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                 &notificationIterators[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