usb_osx.c revision dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0
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
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttypedef struct {
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int vid;
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int pid;
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} VendorProduct;
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define kSupportedDeviceCount   4
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectVendorProduct kSupportedDevices[kSupportedDeviceCount] = {
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    { VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER },
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    { VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER_COMP },
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    { VENDOR_ID_HTC, PRODUCT_ID_DREAM },
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    { VENDOR_ID_HTC, PRODUCT_ID_DREAM_COMP },
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic IONotificationPortRef    notificationPort = 0;
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic io_iterator_t            notificationIterators[kSupportedDeviceCount];
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct usb_handle
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8                     bulkIn;
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8                     bulkOut;
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOUSBInterfaceInterface   **interface;
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    io_object_t               usbNotification;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned int              zero_mask;
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic CFRunLoopRef currentRunLoop = 0;
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic pthread_mutex_t start_lock;
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic pthread_cond_t start_cond;
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void AndroidDeviceAdded(void *refCon, io_iterator_t iterator);
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void AndroidDeviceNotify(void *refCon, io_iterator_t iterator, natural_t messageType, void *messageArgument);
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic usb_handle* FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product);
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectInitUSB()
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CFMutableDictionaryRef  matchingDict;
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CFRunLoopSourceRef      runLoopSource;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SInt32					vendor, product;
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int                     i;
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* To set up asynchronous notifications, create a notification port and
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* add its run loop event source to the program's run loop
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    runLoopSource = IONotificationPortGetRunLoopSource(notificationPort);
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(notificationIterators, 0, sizeof(notificationIterators));
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* loop through all supported vendor/product pairs
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < kSupportedDeviceCount; i++) {
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* Create our matching dictionary to find the Android device
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* IOServiceAddMatchingNotification consumes the reference, so we do not need to release this
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!matchingDict) {
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Couldn't create USB matching dictionary.\n");
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* Set up two matching dictionaries, one for each product ID we support.
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* This will cause the kernel to notify us only if the vendor and product IDs match.
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        vendor = kSupportedDevices[i].vid;
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        product = kSupportedDevices[i].pid;
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor));
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product));
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* Now set up two notifications: one to be called when a raw device
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* is first matched by the I/O Kit and another to be called when the
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* device is terminated.
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* we need to do this with each matching dictionary.
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IOServiceAddMatchingNotification(
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                notificationPort,
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kIOFirstMatchNotification,
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                matchingDict,
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                AndroidDeviceAdded,
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                NULL,
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                &notificationIterators[i]);
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* Iterate over set of matching devices to access already-present devices
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* and to arm the notification
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        AndroidDeviceAdded(NULL, notificationIterators[i]);
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectAndroidDeviceAdded(void *refCon, io_iterator_t iterator)
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    kern_return_t            kr;
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    io_service_t             usbDevice;
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOCFPlugInInterface      **plugInInterface = NULL;
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOUSBDeviceInterface182  **dev = NULL;
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    HRESULT                  result;
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SInt32                   score;
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt16                   vendor;
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt16                   product;
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8                    serialIndex;
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char                     serial[256];
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while ((usbDevice = IOIteratorNext(iterator))) {
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* Create an intermediate plugin
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = IOCreatePlugInInterfaceForService(usbDevice,
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               kIOUSBDeviceUserClientTypeID,
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               kIOCFPlugInInterfaceID,
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                               &plugInInterface, &score);
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Unable to create a plug-in (%08x)\n", kr);
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto continue1;
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* Now create the device interface
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        result = (*plugInInterface)->QueryInterface(plugInInterface,
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev);
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (result || !dev) {
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Couldn't create a device interface (%08x)\n", (int) result);
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto continue2;
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* Check the device to see if it's ours
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = (*dev)->GetDeviceVendor(dev, &vendor);
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = (*dev)->GetDeviceProduct(dev, &product);
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (serialIndex > 0) {
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            IOUSBDevRequest req;
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            UInt16          buffer[256];
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            req.bRequest = kUSBRqGetDescriptor;
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            req.wValue = (kUSBStringDesc << 8) | serialIndex;
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            req.wIndex = 0;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            req.pData = buffer;
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            req.wLength = sizeof(buffer);
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            kr = (*dev)->DeviceRequest(dev, &req);
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (kr == kIOReturnSuccess && req.wLenDone > 0) {
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int i, count;
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                // skip first word, and copy the rest to the serial string, changing shorts to bytes.
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                count = (req.wLenDone - 1) / 2;
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                for (i = 0; i < count; i++)
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                  serial[i] = buffer[i + 1];
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                serial[i] = 0;
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb_handle* handle = NULL;
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* Open the device
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = (*dev)->USBDeviceOpen(dev);
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (kr != kIOReturnSuccess) {
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Could not open device: %08x\n", kr);
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto continue3;
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            //* Find an interface for the device
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            handle = FindDeviceInterface((IOUSBDeviceInterface**)dev, vendor, product);
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (handle == NULL) {
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Could not find device interface: %08x\n", kr);
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (*dev)->USBDeviceClose(dev);
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto continue3;
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("AndroidDeviceAdded calling register_usb_transport\n");
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        register_usb_transport(handle, (serial[0] ? serial : NULL));
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Register for an interest notification of this device being removed. Pass the reference to our
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // private data as the refCon for the notification.
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = IOServiceAddInterestNotification(notificationPort,
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                usbDevice,
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kIOGeneralInterest,
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                AndroidDeviceNotify,
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                handle,
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                &handle->usbNotification);
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (kIOReturnSuccess != kr) {
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Unable to create interest notification (%08x)\n", kr);
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectcontinue3:
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (void)(*dev)->Release(dev);
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectcontinue2:
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IODestroyPlugInInterface(plugInInterface);
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectcontinue1:
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IOObjectRelease(usbDevice);
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectAndroidDeviceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_handle *handle = (usb_handle *)refCon;
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (messageType == kIOMessageServiceIsTerminated) {
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("AndroidDeviceNotify\n");
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IOObjectRelease(handle->usbNotification);
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb_kick(handle);
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic usb_handle*
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectFindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product)
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    usb_handle*                 handle = NULL;
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOReturn                    kr;
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOUSBFindInterfaceRequest   request;
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    io_iterator_t               iterator;
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    io_service_t                usbInterface;
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOCFPlugInInterface         **plugInInterface;
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOUSBInterfaceInterface     **interface = NULL;
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    HRESULT                     result;
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SInt32                      score;
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8  interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol;
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt8  endpoint, configuration;
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* Placing the constant KIOUSBFindInterfaceDontCare into the following
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* fields of the IOUSBFindInterfaceRequest structure will allow us to
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* find all of the interfaces
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* SetConfiguration will kill an existing UMS connection, so let's not do this if not necessary.
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    configuration = 0;
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    (*dev)->GetConfiguration(dev, &configuration);
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (configuration != 1)
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*dev)->SetConfiguration(dev, 1);
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* Get an iterator for the interfaces on the device
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    kr = (*dev)->CreateInterfaceIterator(dev, &request, &iterator);
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (kr != kIOReturnSuccess) {
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: Couldn't create a device interface iterator: (%08x)\n", kr);
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return NULL;
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while ((usbInterface = IOIteratorNext(iterator))) {
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //* Create an intermediate plugin
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = IOCreatePlugInInterfaceForService(
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                usbInterface,
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kIOUSBInterfaceUserClientTypeID,
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kIOCFPlugInInterfaceID,
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                &plugInInterface,
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                &score);
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* No longer need the usbInterface object now that we have the plugin
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (void) IOObjectRelease(usbInterface);
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((kr != kIOReturnSuccess) || (!plugInInterface)) {
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Unable to create plugin (%08x)\n", kr);
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* Now create the interface interface for the interface
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        result = (*plugInInterface)->QueryInterface(
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                plugInInterface,
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                (LPVOID) &interface);
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* No longer need the intermediate plugin
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*plugInInterface)->Release(plugInInterface);
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (result || !interface) {
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Couldn't create interface interface: (%08x)\n",
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               (unsigned int) result);
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* Now open the interface.  This will cause the pipes associated with
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* the endpoints in the interface descriptor to be instantiated
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = (*interface)->USBInterfaceOpen(interface);
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (kr != kIOReturnSuccess)
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        {
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Could not open interface: (%08x)\n", kr);
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (void) (*interface)->Release(interface);
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            //* continue so we can try the next interface
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* Get the number of endpoints associated with this interface
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints);
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (kr != kIOReturnSuccess) {
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr);
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto next_interface;
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* Get interface class, subclass and protocol
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess ||
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess ||
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess)
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        {
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DBG("ERR: Unable to get interface class, subclass and protocol\n");
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto next_interface;
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* check to make sure interface class, subclass and protocol match ADB
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        //* avoid opening mass storage endpoints
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (is_adb_interface(vendor, product, interfaceClass, interfaceSubClass, interfaceProtocol)) {
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            handle = calloc(1, sizeof(usb_handle));
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            //* Iterate over the endpoints for this interface and find the first
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            //* bulk in/out pipes available.  These will be our read/write pipes.
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) {
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                UInt8   transferType;
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                UInt16  maxPacketSize;
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                UInt8   interval;
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                UInt8   number;
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                UInt8   direction;
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kr = (*interface)->GetPipeProperties(interface, endpoint, &direction,
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        &number, &transferType, &maxPacketSize, &interval);
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (kIOReturnSuccess == kr) {
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (kUSBBulk != transferType)
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        continue;
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (kUSBIn == direction)
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        handle->bulkIn = endpoint;
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (kUSBOut == direction)
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        handle->bulkOut = endpoint;
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (interfaceProtocol == 0x01) {
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        handle->zero_mask = maxPacketSize - 1;
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    }
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else {
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    DBG("ERR: FindDeviceInterface - could not get pipe properties\n");
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            handle->interface = interface;
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectnext_interface:
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*interface)->USBInterfaceClose(interface);
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*interface)->Release(interface);
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return handle;
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid* RunLoopThread(void* unused)
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    InitUSB();
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    currentRunLoop = CFRunLoopGetCurrent();
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Signal the parent that we are running
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_lock(&start_lock);
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_cond_signal(&start_cond);
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_mutex_unlock(&start_lock);
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CFRunLoopRun();
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    currentRunLoop = 0;
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < kSupportedDeviceCount; i++) {
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        IOObjectRelease(notificationIterators[i]);
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IONotificationPortDestroy(notificationPort);
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("RunLoopThread done\n");
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return NULL;
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int initialized = 0;
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_init()
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!initialized)
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_thread_t    tid;
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_init(&start_lock, NULL);
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_cond_init(&start_cond, NULL);
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(adb_thread_create(&tid, RunLoopThread, NULL))
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fatal_errno("cannot create input thread");
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Wait for initialization to finish
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_lock(&start_lock);
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_cond_wait(&start_cond, &start_lock);
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_unlock(&start_lock);
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_mutex_destroy(&start_lock);
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_cond_destroy(&start_cond);
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        initialized = 1;
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_cleanup()
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("usb_cleanup\n");
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    close_usb_devices();
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (currentRunLoop)
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        CFRunLoopStop(currentRunLoop);
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_write(usb_handle *handle, const void *buf, int len)
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOReturn    result;
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!len)
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!handle)
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == handle->interface) {
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: usb_write interface was null\n");
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (0 == handle->bulkOut) {
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: bulkOut endpoint not assigned\n");
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    result =
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*handle->interface)->WritePipe(
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                              handle->interface, handle->bulkOut, (void *)buf, len);
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if ((result == 0) && (handle->zero_mask)) {
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* we need 0-markers and our transfer */
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(!(len & handle->zero_mask)) {
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            result =
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                (*handle->interface)->WritePipe(
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        handle->interface, handle->bulkOut, (void *)buf, 0);
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (0 == result)
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DBG("ERR: usb_write failed with status %d\n", result);
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_read(usb_handle *handle, void *buf, int len)
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    IOReturn result;
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    UInt32  numBytes = len;
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!len) {
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!handle) {
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (NULL == handle->interface) {
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: usb_read interface was null\n");
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (0 == handle->bulkIn) {
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: bulkIn endpoint not assigned\n");
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    result =
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project      (*handle->interface)->ReadPipe(handle->interface,
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                    handle->bulkIn, buf, &numBytes);
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (0 == result)
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    else {
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DBG("ERR: usb_read failed with status %d\n", result);
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_close(usb_handle *handle)
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_kick(usb_handle *handle)
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* release the interface */
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (handle->interface)
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*handle->interface)->USBInterfaceClose(handle->interface);
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        (*handle->interface)->Release(handle->interface);
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        handle->interface = 0;
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
537