usb_osx.c revision 3fd82b8861aa410fab7785074941b459d92220c1
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"
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define  DBG   D
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
343fd82b8861aa410fab7785074941b459d92220c1Dima Zavin#define ADB_SUBCLASS           0x42
353fd82b8861aa410fab7785074941b459d92220c1Dima Zavin#define ADB_PROTOCOL           0x1
363fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
373fd82b8861aa410fab7785074941b459d92220c1Dima Zavinint vendorIds[] = {
383fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    VENDOR_ID_GOOGLE,
393fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    VENDOR_ID_HTC,
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
413fd82b8861aa410fab7785074941b459d92220c1Dima Zavin#define NUM_VENDORS             (sizeof(vendorIds)/sizeof(vendorIds[0]))
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic IONotificationPortRef    notificationPort = 0;
443fd82b8861aa410fab7785074941b459d92220c1Dima Zavinstatic io_iterator_t            notificationIterators[NUM_VENDORS];
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct usb_handle
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8                     bulkIn;
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8                     bulkOut;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOUSBInterfaceInterface   **interface;
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    io_object_t               usbNotification;
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned int              zero_mask;
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic CFRunLoopRef currentRunLoop = 0;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic pthread_mutex_t start_lock;
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic pthread_cond_t start_cond;
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
603fd82b8861aa410fab7785074941b459d92220c1Dima Zavinstatic void AndroidInterfaceAdded(void *refCon, io_iterator_t iterator);
613fd82b8861aa410fab7785074941b459d92220c1Dima Zavinstatic void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator,
623fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                   natural_t messageType,
633fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                   void *messageArgument);
643fd82b8861aa410fab7785074941b459d92220c1Dima Zavinstatic usb_handle* CheckInterface(IOUSBInterfaceInterface **iface,
653fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                  UInt16 vendor, UInt16 product);
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectInitUSB()
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CFMutableDictionaryRef  matchingDict;
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CFRunLoopSourceRef      runLoopSource;
723fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    SInt32                  vendor, if_subclass, if_protocol;
733fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    unsigned                i;
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* To set up asynchronous notifications, create a notification port and
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* add its run loop event source to the program's run loop
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    runLoopSource = IONotificationPortGetRunLoopSource(notificationPort);
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(notificationIterators, 0, sizeof(notificationIterators));
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
833fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* loop through all supported vendors
843fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    for (i = 0; i < NUM_VENDORS; i++) {
853fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* Create our matching dictionary to find the Android device's
863fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* adb interface
873fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* IOServiceAddMatchingNotification consumes the reference, so we do
883fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* not need to release this
893fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        matchingDict = IOServiceMatching(kIOUSBInterfaceClassName);
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!matchingDict) {
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Couldn't create USB matching dictionary.\n");
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
963fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* Match based on vendor id, interface subclass and protocol
973fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        vendor = vendorIds[i];
983fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if_subclass = ADB_SUBCLASS;
993fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if_protocol = ADB_PROTOCOL;
1003fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID),
1013fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                             CFNumberCreate(kCFAllocatorDefault,
1023fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                            kCFNumberSInt32Type, &vendor));
1033fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceSubClass),
1043fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                             CFNumberCreate(kCFAllocatorDefault,
1053fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                            kCFNumberSInt32Type, &if_subclass));
1063fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceProtocol),
1073fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                             CFNumberCreate(kCFAllocatorDefault,
1083fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                            kCFNumberSInt32Type, &if_protocol));
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IOServiceAddMatchingNotification(
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                notificationPort,
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kIOFirstMatchNotification,
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                matchingDict,
1133fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                AndroidInterfaceAdded,
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                NULL,
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                &notificationIterators[i]);
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1173fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* Iterate over set of matching interfaces to access already-present
1183fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* devices and to arm the notification
1193fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        AndroidInterfaceAdded(NULL, notificationIterators[i]);
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
1263fd82b8861aa410fab7785074941b459d92220c1Dima ZavinAndroidInterfaceAdded(void *refCon, io_iterator_t iterator)
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    kern_return_t            kr;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    io_service_t             usbDevice;
1303fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    io_service_t             usbInterface;
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOCFPlugInInterface      **plugInInterface = NULL;
1323fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    IOUSBInterfaceInterface220  **iface = NULL;
1333fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    IOUSBDeviceInterface197  **dev = NULL;
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    HRESULT                  result;
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SInt32                   score;
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt16                   vendor;
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt16                   product;
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8                    serialIndex;
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char                     serial[256];
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1413fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    while ((usbInterface = IOIteratorNext(iterator))) {
1423fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* Create an intermediate interface plugin
1433fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        kr = IOCreatePlugInInterfaceForService(usbInterface,
1443fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                               kIOUSBInterfaceUserClientTypeID,
1453fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                               kIOCFPlugInInterfaceID,
1463fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                               &plugInInterface, &score);
1473fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        IOObjectRelease(usbInterface);
1483fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
1493fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr);
1503fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            continue;
1513fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        }
1523fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
1533fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* This gets us the interface object
1543fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        result = (*plugInInterface)->QueryInterface(plugInInterface,
1553fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID)
1563fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                &iface);
1573fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* We only needed the plugin to get the interface, so discard it
1583fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        (*plugInInterface)->Release(plugInInterface);
1593fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if (result || !iface) {
1603fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: Couldn't query the interface (%08x)\n", (int) result);
1613fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            continue;
1623fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        }
1633fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
1643fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* this gets us an ioservice, with which we will find the actual
1653fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* device; after getting a plugin, and querying the interface, of
1663fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* course.
1673fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* Gotta love OS X
1683fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        kr = (*iface)->GetDevice(iface, &usbDevice);
1693fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if (kIOReturnSuccess != kr || !usbDevice) {
1703fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: Couldn't grab device from interface (%08x)\n", kr);
1713fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            continue;
1723fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        }
1733fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
1743fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        plugInInterface = NULL;
1753fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        score = 0;
1763fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* create an intermediate device plugin
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = IOCreatePlugInInterfaceForService(usbDevice,
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               kIOUSBDeviceUserClientTypeID,
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               kIOCFPlugInInterfaceID,
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               &plugInInterface, &score);
1813fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* only needed this to find the plugin
1823fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        (void)IOObjectRelease(usbDevice);
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
1843fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: Unable to create a device plug-in (%08x)\n", kr);
1853fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            continue;
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        result = (*plugInInterface)->QueryInterface(plugInInterface,
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev);
1903fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* only needed this to query the plugin
1913fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        (*plugInInterface)->Release(plugInInterface);
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (result || !dev) {
1933fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: Couldn't create a device interface (%08x)\n",
1943fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                (int) result);
1953fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            continue;
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1983fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* Now after all that, we actually have a ref to the device and
1993fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        //* the interface that matched our criteria
2003fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = (*dev)->GetDeviceVendor(dev, &vendor);
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = (*dev)->GetDeviceProduct(dev, &product);
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (serialIndex > 0) {
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            IOUSBDevRequest req;
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            UInt16          buffer[256];
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2093fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            req.bmRequestType =
2103fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            req.bRequest = kUSBRqGetDescriptor;
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            req.wValue = (kUSBStringDesc << 8) | serialIndex;
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            req.wIndex = 0;
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            req.pData = buffer;
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            req.wLength = sizeof(buffer);
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            kr = (*dev)->DeviceRequest(dev, &req);
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (kr == kIOReturnSuccess && req.wLenDone > 0) {
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int i, count;
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2213fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                // skip first word, and copy the rest to the serial string,
2223fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                // changing shorts to bytes.
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                count = (req.wLenDone - 1) / 2;
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                for (i = 0; i < count; i++)
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                  serial[i] = buffer[i + 1];
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                serial[i] = 0;
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
2293fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        (*dev)->Release(dev);
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2313fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product,
2323fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            serial);
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2343fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface,
2353fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                                            vendor, product);
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (handle == NULL) {
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Could not find device interface: %08x\n", kr);
2383fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            (*iface)->Release(iface);
2393fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            continue;
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("AndroidDeviceAdded calling register_usb_transport\n");
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        register_usb_transport(handle, (serial[0] ? serial : NULL));
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2453fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        // Register for an interest notification of this device being removed.
2463fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        // Pass the reference to our private data as the refCon for the
2473fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        // notification.
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = IOServiceAddInterestNotification(notificationPort,
2493fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                usbInterface,
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kIOGeneralInterest,
2513fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                AndroidInterfaceNotify,
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                handle,
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                &handle->usbNotification);
2543fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (kIOReturnSuccess != kr) {
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Unable to create interest notification (%08x)\n", kr);
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
2623fd82b8861aa410fab7785074941b459d92220c1Dima ZavinAndroidInterfaceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_handle *handle = (usb_handle *)refCon;
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (messageType == kIOMessageServiceIsTerminated) {
2673fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if (!handle) {
2683fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: NULL handle\n");
2693fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            return;
2703fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        }
2713fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        DBG("AndroidInterfaceNotify\n");
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IOObjectRelease(handle->usbNotification);
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb_kick(handle);
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2773fd82b8861aa410fab7785074941b459d92220c1Dima Zavin//* TODO: simplify this further since we only register to get ADB interface
2783fd82b8861aa410fab7785074941b459d92220c1Dima Zavin//* subclass+protocol events
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic usb_handle*
2803fd82b8861aa410fab7785074941b459d92220c1Dima ZavinCheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product)
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_handle*                 handle = NULL;
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOReturn                    kr;
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8  interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol;
2853fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    UInt8  endpoint;
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2883fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* Now open the interface.  This will cause the pipes associated with
2893fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* the endpoints in the interface descriptor to be instantiated
2903fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    kr = (*interface)->USBInterfaceOpen(interface);
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (kr != kIOReturnSuccess) {
2923fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        DBG("ERR: Could not open interface: (%08x)\n", kr);
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2963fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* Get the number of endpoints associated with this interface
2973fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints);
2983fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    if (kr != kIOReturnSuccess) {
2993fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr);
3003fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        goto err_get_num_ep;
3013fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    }
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3033fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* Get interface class, subclass and protocol
3043fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess ||
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess ||
3063fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) {
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Unable to get interface class, subclass and protocol\n");
3083fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            goto err_get_interface_class;
3093fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    }
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3113fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* check to make sure interface class, subclass and protocol match ADB
3123fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* avoid opening mass storage endpoints
3133fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    if (!is_adb_interface(vendor, product, interfaceClass,
3143fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                interfaceSubClass, interfaceProtocol))
3153fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        goto err_bad_adb_interface;
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3173fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    handle = calloc(1, sizeof(usb_handle));
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3193fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* Iterate over the endpoints for this interface and find the first
3203fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    //* bulk in/out pipes available.  These will be our read/write pipes.
3213fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) {
3223fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        UInt8   transferType;
3233fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        UInt16  maxPacketSize;
3243fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        UInt8   interval;
3253fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        UInt8   number;
3263fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        UInt8   direction;
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3283fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        kr = (*interface)->GetPipeProperties(interface, endpoint, &direction,
3293fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                &number, &transferType, &maxPacketSize, &interval);
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3313fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        if (kIOReturnSuccess == kr) {
3323fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            if (kUSBBulk != transferType)
3333fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                continue;
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3353fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            if (kUSBIn == direction)
3363fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                handle->bulkIn = endpoint;
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3383fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            if (kUSBOut == direction)
3393fd82b8861aa410fab7785074941b459d92220c1Dima Zavin                handle->bulkOut = endpoint;
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3413fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            handle->zero_mask = maxPacketSize - 1;
3423fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        } else {
3433fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            DBG("ERR: FindDeviceInterface - could not get pipe properties\n");
3443fd82b8861aa410fab7785074941b459d92220c1Dima Zavin            goto err_get_pipe_props;
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3483fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    handle->interface = interface;
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return handle;
3503fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
3513fd82b8861aa410fab7785074941b459d92220c1Dima Zavinerr_get_pipe_props:
3523fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    free(handle);
3533fd82b8861aa410fab7785074941b459d92220c1Dima Zavinerr_bad_adb_interface:
3543fd82b8861aa410fab7785074941b459d92220c1Dima Zavinerr_get_interface_class:
3553fd82b8861aa410fab7785074941b459d92220c1Dima Zavinerr_get_num_ep:
3563fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    (*interface)->USBInterfaceClose(interface);
3573fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    return NULL;
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid* RunLoopThread(void* unused)
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
3633fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    unsigned i;
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    InitUSB();
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    currentRunLoop = CFRunLoopGetCurrent();
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Signal the parent that we are running
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_lock(&start_lock);
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_cond_signal(&start_cond);
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_unlock(&start_lock);
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CFRunLoopRun();
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    currentRunLoop = 0;
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3773fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    for (i = 0; i < NUM_VENDORS; i++) {
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IOObjectRelease(notificationIterators[i]);
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IONotificationPortDestroy(notificationPort);
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("RunLoopThread done\n");
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return NULL;
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int initialized = 0;
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_init()
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!initialized)
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_thread_t    tid;
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_init(&start_lock, NULL);
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_cond_init(&start_cond, NULL);
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(adb_thread_create(&tid, RunLoopThread, NULL))
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fatal_errno("cannot create input thread");
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Wait for initialization to finish
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_lock(&start_lock);
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_cond_wait(&start_cond, &start_lock);
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_unlock(&start_lock);
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_destroy(&start_lock);
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_cond_destroy(&start_cond);
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        initialized = 1;
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_cleanup()
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_cleanup\n");
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close_usb_devices();
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (currentRunLoop)
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        CFRunLoopStop(currentRunLoop);
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_write(usb_handle *handle, const void *buf, int len)
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOReturn    result;
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!len)
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!handle)
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == handle->interface) {
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: usb_write interface was null\n");
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (0 == handle->bulkOut) {
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: bulkOut endpoint not assigned\n");
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    result =
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*handle->interface)->WritePipe(
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                              handle->interface, handle->bulkOut, (void *)buf, len);
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ((result == 0) && (handle->zero_mask)) {
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* we need 0-markers and our transfer */
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(!(len & handle->zero_mask)) {
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            result =
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                (*handle->interface)->WritePipe(
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        handle->interface, handle->bulkOut, (void *)buf, 0);
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (0 == result)
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("ERR: usb_write failed with status %d\n", result);
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_read(usb_handle *handle, void *buf, int len)
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOReturn result;
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt32  numBytes = len;
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!len) {
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!handle) {
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == handle->interface) {
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: usb_read interface was null\n");
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (0 == handle->bulkIn) {
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: bulkIn endpoint not assigned\n");
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    result =
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      (*handle->interface)->ReadPipe(handle->interface,
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                    handle->bulkIn, buf, &numBytes);
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (0 == result)
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else {
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: usb_read failed with status %d\n", result);
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_close(usb_handle *handle)
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_kick(usb_handle *handle)
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* release the interface */
5043fd82b8861aa410fab7785074941b459d92220c1Dima Zavin    if (!handle)
5053fd82b8861aa410fab7785074941b459d92220c1Dima Zavin        return;
5063fd82b8861aa410fab7785074941b459d92220c1Dima Zavin
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (handle->interface)
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*handle->interface)->USBInterfaceClose(handle->interface);
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*handle->interface)->Release(handle->interface);
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle->interface = 0;
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
514