1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <CoreFoundation/CoreFoundation.h>
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <IOKit/IOKitLib.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <IOKit/IOCFPlugIn.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <IOKit/usb/IOUSBLib.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <IOKit/IOMessage.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <mach/mach_port.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "sysdeps.h"
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define TRACE_TAG   TRACE_USB
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "adb.h"
31a09fbd164d2e088bc5433d310e25640ae048d47dXavier Ducrohet#include "usb_vendors.h"
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define  DBG   D
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic IONotificationPortRef    notificationPort = 0;
36a09fbd164d2e088bc5433d310e25640ae048d47dXavier Ducrohetstatic io_iterator_t*           notificationIterators;
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct usb_handle
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8                     bulkIn;
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8                     bulkOut;
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOUSBInterfaceInterface   **interface;
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    io_object_t               usbNotification;
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned int              zero_mask;
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic CFRunLoopRef currentRunLoop = 0;
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic pthread_mutex_t start_lock;
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic pthread_cond_t start_cond;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
523fd82b8861aa410fab7785074941b459d92220c1Dima Zavinstatic void AndroidInterfaceAdded(void *refCon, io_iterator_t iterator);
533fd82b8861aa410fab7785074941b459d92220c1Dima Zavinstatic void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator,
543fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                   natural_t messageType,
553fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                   void *messageArgument);
563fd82b8861aa410fab7785074941b459d92220c1Dima Zavinstatic usb_handle* CheckInterface(IOUSBInterfaceInterface **iface,
573fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                  UInt16 vendor, UInt16 product);
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectInitUSB()
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CFMutableDictionaryRef  matchingDict;
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CFRunLoopSourceRef      runLoopSource;
643fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    SInt32                  vendor, if_subclass, if_protocol;
653fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    unsigned                i;
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* To set up asynchronous notifications, create a notification port and
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* add its run loop event source to the program's run loop
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    runLoopSource = IONotificationPortGetRunLoopSource(notificationPort);
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(notificationIterators, 0, sizeof(notificationIterators));
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
753fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* loop through all supported vendors
76a09fbd164d2e088bc5433d310e25640ae048d47dXavier Ducrohet    for (i = 0; i < vendorIdCount; i++) {
773fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* Create our matching dictionary to find the Android device's
783fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* adb interface
793fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* IOServiceAddMatchingNotification consumes the reference, so we do
803fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* not need to release this
813fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        matchingDict = IOServiceMatching(kIOUSBInterfaceClassName);
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!matchingDict) {
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Couldn't create USB matching dictionary.\n");
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
883fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* Match based on vendor id, interface subclass and protocol
893fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        vendor = vendorIds[i];
903fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if_subclass = ADB_SUBCLASS;
913fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if_protocol = ADB_PROTOCOL;
923fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID),
933fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                             CFNumberCreate(kCFAllocatorDefault,
943fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                            kCFNumberSInt32Type, &vendor));
953fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceSubClass),
963fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                             CFNumberCreate(kCFAllocatorDefault,
973fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                            kCFNumberSInt32Type, &if_subclass));
983fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceProtocol),
993fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                             CFNumberCreate(kCFAllocatorDefault,
1003fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                            kCFNumberSInt32Type, &if_protocol));
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IOServiceAddMatchingNotification(
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                notificationPort,
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kIOFirstMatchNotification,
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                matchingDict,
1053fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                AndroidInterfaceAdded,
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                NULL,
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                &notificationIterators[i]);
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1093fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* Iterate over set of matching interfaces to access already-present
1103fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* devices and to arm the notification
1113fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        AndroidInterfaceAdded(NULL, notificationIterators[i]);
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
1183fd82b8861aa410fab7785074941b459d92220c1Dima ZavinAndroidInterfaceAdded(void *refCon, io_iterator_t iterator)
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    kern_return_t            kr;
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    io_service_t             usbDevice;
1223fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    io_service_t             usbInterface;
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOCFPlugInInterface      **plugInInterface = NULL;
1243fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    IOUSBInterfaceInterface220  **iface = NULL;
1253fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    IOUSBDeviceInterface197  **dev = NULL;
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    HRESULT                  result;
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SInt32                   score;
128e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson    UInt32                   locationId;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt16                   vendor;
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt16                   product;
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8                    serialIndex;
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char                     serial[256];
133e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson    char                     devpathBuf[64];
134e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson    char                     *devpath = NULL;
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1363fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    while ((usbInterface = IOIteratorNext(iterator))) {
1373fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* Create an intermediate interface plugin
1383fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        kr = IOCreatePlugInInterfaceForService(usbInterface,
1393fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                               kIOUSBInterfaceUserClientTypeID,
1403fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                               kIOCFPlugInInterfaceID,
1413fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                               &plugInInterface, &score);
1423fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        IOObjectRelease(usbInterface);
1433fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
1443fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr);
1453fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            continue;
1463fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        }
1473fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
1483fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* This gets us the interface object
1493fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        result = (*plugInInterface)->QueryInterface(plugInInterface,
1503fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID)
1513fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                &iface);
1523fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* We only needed the plugin to get the interface, so discard it
1533fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        (*plugInInterface)->Release(plugInInterface);
1543fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if (result || !iface) {
1553fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: Couldn't query the interface (%08x)\n", (int) result);
1563fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            continue;
1573fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        }
1583fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
1593fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* this gets us an ioservice, with which we will find the actual
1603fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* device; after getting a plugin, and querying the interface, of
1613fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* course.
1623fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* Gotta love OS X
1633fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        kr = (*iface)->GetDevice(iface, &usbDevice);
1643fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if (kIOReturnSuccess != kr || !usbDevice) {
1653fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: Couldn't grab device from interface (%08x)\n", kr);
1663fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            continue;
1673fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        }
1683fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
1693fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        plugInInterface = NULL;
1703fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        score = 0;
1713fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* create an intermediate device plugin
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = IOCreatePlugInInterfaceForService(usbDevice,
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               kIOUSBDeviceUserClientTypeID,
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               kIOCFPlugInInterfaceID,
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               &plugInInterface, &score);
1763fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* only needed this to find the plugin
1773fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        (void)IOObjectRelease(usbDevice);
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
1793fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: Unable to create a device plug-in (%08x)\n", kr);
1803fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            continue;
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        result = (*plugInInterface)->QueryInterface(plugInInterface,
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev);
1853fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* only needed this to query the plugin
1863fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        (*plugInInterface)->Release(plugInInterface);
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (result || !dev) {
1883fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: Couldn't create a device interface (%08x)\n",
1893fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                (int) result);
1903fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            continue;
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1933fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* Now after all that, we actually have a ref to the device and
1943fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* the interface that matched our criteria
1953fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = (*dev)->GetDeviceVendor(dev, &vendor);
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = (*dev)->GetDeviceProduct(dev, &product);
198e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        kr = (*dev)->GetLocationID(dev, &locationId);
199e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        if (kr == 0) {
200e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson            snprintf(devpathBuf, sizeof(devpathBuf), "usb:%lX", locationId);
201e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson            devpath = devpathBuf;
202e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        }
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2051a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu	if (serialIndex > 0) {
2061a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		IOUSBDevRequest req;
2071a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		UInt16          buffer[256];
2081a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		UInt16          languages[128];
2091a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu
2101a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		memset(languages, 0, sizeof(languages));
2111a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu
2121a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		req.bmRequestType =
2131a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu			USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
2141a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		req.bRequest = kUSBRqGetDescriptor;
2151a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		req.wValue = (kUSBStringDesc << 8) | 0;
2161a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		req.wIndex = 0;
2171a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		req.pData = languages;
2181a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		req.wLength = sizeof(languages);
2191a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		kr = (*dev)->DeviceRequest(dev, &req);
2201a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu
2211a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		if (kr == kIOReturnSuccess && req.wLenDone > 0) {
2221a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu
2231a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu			int langCount = (req.wLenDone - 2) / 2, lang;
2241a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu
2251a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu			for (lang = 1; lang <= langCount; lang++) {
2261a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu
2271a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu                                memset(buffer, 0, sizeof(buffer));
2281a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu                                memset(&req, 0, sizeof(req));
2291a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu
2301a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu				req.bmRequestType =
2311a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu					USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
2321a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu				req.bRequest = kUSBRqGetDescriptor;
2331a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu				req.wValue = (kUSBStringDesc << 8) | serialIndex;
2341a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu				req.wIndex = languages[lang];
2351a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu				req.pData = buffer;
2361a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu				req.wLength = sizeof(buffer);
2371a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu				kr = (*dev)->DeviceRequest(dev, &req);
2381a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu
2391a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu				if (kr == kIOReturnSuccess && req.wLenDone > 0) {
2401a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu					int i, count;
2411a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu
2421a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu					// skip first word, and copy the rest to the serial string,
2431a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu					// changing shorts to bytes.
2441a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu					count = (req.wLenDone - 1) / 2;
2451a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu					for (i = 0; i < count; i++)
2461a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu						serial[i] = buffer[i + 1];
2471a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu					serial[i] = 0;
2481a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu                                        break;
2491a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu				}
2501a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu			}
2511a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu		}
2521a1f8189866196c5bd1ace378cf6b0ca69bff267Guang Zhu	}
2533fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        (*dev)->Release(dev);
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2553fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product,
2563fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            serial);
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2583fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface,
2593fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                            vendor, product);
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (handle == NULL) {
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Could not find device interface: %08x\n", kr);
2623fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            (*iface)->Release(iface);
2633fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            continue;
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("AndroidDeviceAdded calling register_usb_transport\n");
267e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        register_usb_transport(handle, (serial[0] ? serial : NULL), devpath, 1);
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2693fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        // Register for an interest notification of this device being removed.
2703fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        // Pass the reference to our private data as the refCon for the
2713fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        // notification.
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = IOServiceAddInterestNotification(notificationPort,
2733fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                usbInterface,
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kIOGeneralInterest,
2753fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                AndroidInterfaceNotify,
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                handle,
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                &handle->usbNotification);
2783fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (kIOReturnSuccess != kr) {
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Unable to create interest notification (%08x)\n", kr);
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
2863fd82b8861aa410fab7785074941b459d92220c1Dima ZavinAndroidInterfaceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_handle *handle = (usb_handle *)refCon;
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (messageType == kIOMessageServiceIsTerminated) {
2913fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if (!handle) {
2923fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: NULL handle\n");
2933fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            return;
2943fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        }
2953fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        DBG("AndroidInterfaceNotify\n");
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IOObjectRelease(handle->usbNotification);
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb_kick(handle);
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3013fd82b8861aa410fab7785074941b459d92220c1Dima Zavin//* TODO: simplify this further since we only register to get ADB interface
3023fd82b8861aa410fab7785074941b459d92220c1Dima Zavin//* subclass+protocol events
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic usb_handle*
3043fd82b8861aa410fab7785074941b459d92220c1Dima ZavinCheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product)
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_handle*                 handle = NULL;
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOReturn                    kr;
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8  interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol;
3093fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    UInt8  endpoint;
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3123fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* Now open the interface.  This will cause the pipes associated with
3133fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* the endpoints in the interface descriptor to be instantiated
3143fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    kr = (*interface)->USBInterfaceOpen(interface);
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (kr != kIOReturnSuccess) {
3163fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        DBG("ERR: Could not open interface: (%08x)\n", kr);
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3203fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* Get the number of endpoints associated with this interface
3213fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints);
3223fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    if (kr != kIOReturnSuccess) {
3233fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr);
3243fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        goto err_get_num_ep;
3253fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    }
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3273fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* Get interface class, subclass and protocol
3283fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess ||
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess ||
3303fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) {
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Unable to get interface class, subclass and protocol\n");
3323fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            goto err_get_interface_class;
3333fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    }
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3353fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* check to make sure interface class, subclass and protocol match ADB
3363fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* avoid opening mass storage endpoints
3373fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    if (!is_adb_interface(vendor, product, interfaceClass,
3383fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                interfaceSubClass, interfaceProtocol))
3393fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        goto err_bad_adb_interface;
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3413fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    handle = calloc(1, sizeof(usb_handle));
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3433fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* Iterate over the endpoints for this interface and find the first
3443fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* bulk in/out pipes available.  These will be our read/write pipes.
3453fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) {
3463fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        UInt8   transferType;
3473fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        UInt16  maxPacketSize;
3483fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        UInt8   interval;
3493fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        UInt8   number;
3503fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        UInt8   direction;
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3523fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        kr = (*interface)->GetPipeProperties(interface, endpoint, &direction,
3533fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                &number, &transferType, &maxPacketSize, &interval);
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3553fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if (kIOReturnSuccess == kr) {
3563fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            if (kUSBBulk != transferType)
3573fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                continue;
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3593fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            if (kUSBIn == direction)
3603fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                handle->bulkIn = endpoint;
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3623fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            if (kUSBOut == direction)
3633fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                handle->bulkOut = endpoint;
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3653fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            handle->zero_mask = maxPacketSize - 1;
3663fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        } else {
3673fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: FindDeviceInterface - could not get pipe properties\n");
3683fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            goto err_get_pipe_props;
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3723fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    handle->interface = interface;
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return handle;
3743fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
3753fd82b8861aa410fab7785074941b459d92220c1Dima Zavinerr_get_pipe_props:
3763fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    free(handle);
3773fd82b8861aa410fab7785074941b459d92220c1Dima Zavinerr_bad_adb_interface:
3783fd82b8861aa410fab7785074941b459d92220c1Dima Zavinerr_get_interface_class:
3793fd82b8861aa410fab7785074941b459d92220c1Dima Zavinerr_get_num_ep:
3803fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    (*interface)->USBInterfaceClose(interface);
3813fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    return NULL;
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid* RunLoopThread(void* unused)
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
3873fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    unsigned i;
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    InitUSB();
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    currentRunLoop = CFRunLoopGetCurrent();
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Signal the parent that we are running
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_lock(&start_lock);
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_cond_signal(&start_cond);
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_unlock(&start_lock);
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CFRunLoopRun();
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    currentRunLoop = 0;
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
401a09fbd164d2e088bc5433d310e25640ae048d47dXavier Ducrohet    for (i = 0; i < vendorIdCount; i++) {
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IOObjectRelease(notificationIterators[i]);
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IONotificationPortDestroy(notificationPort);
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("RunLoopThread done\n");
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return NULL;
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int initialized = 0;
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_init()
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!initialized)
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_thread_t    tid;
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
418a09fbd164d2e088bc5433d310e25640ae048d47dXavier Ducrohet        notificationIterators = (io_iterator_t*)malloc(
419a09fbd164d2e088bc5433d310e25640ae048d47dXavier Ducrohet            vendorIdCount * sizeof(io_iterator_t));
420a09fbd164d2e088bc5433d310e25640ae048d47dXavier Ducrohet
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_init(&start_lock, NULL);
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_cond_init(&start_cond, NULL);
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(adb_thread_create(&tid, RunLoopThread, NULL))
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fatal_errno("cannot create input thread");
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Wait for initialization to finish
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_lock(&start_lock);
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_cond_wait(&start_cond, &start_lock);
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_unlock(&start_lock);
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_destroy(&start_lock);
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_cond_destroy(&start_cond);
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        initialized = 1;
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_cleanup()
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_cleanup\n");
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close_usb_devices();
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (currentRunLoop)
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        CFRunLoopStop(currentRunLoop);
445a09fbd164d2e088bc5433d310e25640ae048d47dXavier Ducrohet
446a09fbd164d2e088bc5433d310e25640ae048d47dXavier Ducrohet    if (notificationIterators != NULL) {
447a09fbd164d2e088bc5433d310e25640ae048d47dXavier Ducrohet        free(notificationIterators);
448a09fbd164d2e088bc5433d310e25640ae048d47dXavier Ducrohet        notificationIterators = NULL;
449a09fbd164d2e088bc5433d310e25640ae048d47dXavier Ducrohet    }
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_write(usb_handle *handle, const void *buf, int len)
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOReturn    result;
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!len)
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!handle)
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == handle->interface) {
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: usb_write interface was null\n");
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (0 == handle->bulkOut) {
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: bulkOut endpoint not assigned\n");
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    result =
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*handle->interface)->WritePipe(
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                              handle->interface, handle->bulkOut, (void *)buf, len);
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ((result == 0) && (handle->zero_mask)) {
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* we need 0-markers and our transfer */
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(!(len & handle->zero_mask)) {
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            result =
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                (*handle->interface)->WritePipe(
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        handle->interface, handle->bulkOut, (void *)buf, 0);
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (0 == result)
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("ERR: usb_write failed with status %d\n", result);
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_read(usb_handle *handle, void *buf, int len)
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOReturn result;
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt32  numBytes = len;
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!len) {
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!handle) {
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == handle->interface) {
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: usb_read interface was null\n");
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (0 == handle->bulkIn) {
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: bulkIn endpoint not assigned\n");
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    result =
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      (*handle->interface)->ReadPipe(handle->interface,
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                    handle->bulkIn, buf, &numBytes);
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (0 == result)
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else {
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: usb_read failed with status %d\n", result);
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_close(usb_handle *handle)
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_kick(usb_handle *handle)
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* release the interface */
5363fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    if (!handle)
5373fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        return;
5383fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (handle->interface)
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*handle->interface)->USBInterfaceClose(handle->interface);
542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*handle->interface)->Release(handle->interface);
543dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle->interface = 0;
544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
546