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     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 
    277 static void
    278 AndroidInterfaceNotify(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
    295 static usb_handle*
    296 CheckInterface(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 
    367 err_get_pipe_props:
    368     free(handle);
    369 err_bad_adb_interface:
    370 err_get_interface_class:
    371 err_get_num_ep:
    372     (*interface)->USBInterfaceClose(interface);
    373     return NULL;
    374 }
    375 
    376 
    377 void* 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 
    403 static int initialized = 0;
    404 void 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 
    431 void 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 
    444 int 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 
    484 int 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 
    520 int usb_close(usb_handle *handle)
    521 {
    522     return 0;
    523 }
    524 
    525 void 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