auto import from //depot/cupcake/@135843
diff --git a/usb_osx.c b/usb_osx.c
new file mode 100644
index 0000000..49e1eef
--- /dev/null
+++ b/usb_osx.c
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/usb/IOUSBLib.h>
+#include <IOKit/IOMessage.h>
+#include <mach/mach_port.h>
+
+#include "sysdeps.h"
+
+#include <stdio.h>
+
+#define TRACE_TAG   TRACE_USB
+#include "adb.h"
+
+#define  DBG   D
+
+typedef struct {
+    int vid;
+    int pid;
+} VendorProduct;
+
+#define kSupportedDeviceCount   4
+VendorProduct kSupportedDevices[kSupportedDeviceCount] = {
+    { VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER },
+    { VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER_COMP },
+    { VENDOR_ID_HTC, PRODUCT_ID_DREAM },
+    { VENDOR_ID_HTC, PRODUCT_ID_DREAM_COMP },
+};
+
+static IONotificationPortRef    notificationPort = 0;
+static io_iterator_t            notificationIterators[kSupportedDeviceCount];
+
+struct usb_handle
+{
+    UInt8                     bulkIn;
+    UInt8                     bulkOut;
+    IOUSBInterfaceInterface   **interface;
+    io_object_t               usbNotification;
+    unsigned int              zero_mask;
+};
+
+static CFRunLoopRef currentRunLoop = 0;
+static pthread_mutex_t start_lock;
+static pthread_cond_t start_cond;
+
+
+static void AndroidDeviceAdded(void *refCon, io_iterator_t iterator);
+static void AndroidDeviceNotify(void *refCon, io_iterator_t iterator, natural_t messageType, void *messageArgument);
+static usb_handle* FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product);
+
+static int
+InitUSB()
+{
+    CFMutableDictionaryRef  matchingDict;
+    CFRunLoopSourceRef      runLoopSource;
+    SInt32					vendor, product;
+    int                     i;
+
+    //* To set up asynchronous notifications, create a notification port and
+    //* add its run loop event source to the program's run loop
+    notificationPort = IONotificationPortCreate(kIOMasterPortDefault);
+    runLoopSource = IONotificationPortGetRunLoopSource(notificationPort);
+    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
+
+    memset(notificationIterators, 0, sizeof(notificationIterators));
+
+    //* loop through all supported vendor/product pairs
+    for (i = 0; i < kSupportedDeviceCount; i++) {
+        //* Create our matching dictionary to find the Android device
+        //* IOServiceAddMatchingNotification consumes the reference, so we do not need to release this
+        matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
+
+        if (!matchingDict) {
+            DBG("ERR: Couldn't create USB matching dictionary.\n");
+            return -1;
+        }
+
+        //* Set up two matching dictionaries, one for each product ID we support.
+        //* This will cause the kernel to notify us only if the vendor and product IDs match.
+        vendor = kSupportedDevices[i].vid;
+        product = kSupportedDevices[i].pid;
+        CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor));
+        CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product));
+
+        //* Now set up two notifications: one to be called when a raw device
+        //* is first matched by the I/O Kit and another to be called when the
+        //* device is terminated.
+        //* we need to do this with each matching dictionary.
+        IOServiceAddMatchingNotification(
+                notificationPort,
+                kIOFirstMatchNotification,
+                matchingDict,
+                AndroidDeviceAdded,
+                NULL,
+                &notificationIterators[i]);
+
+        //* Iterate over set of matching devices to access already-present devices
+        //* and to arm the notification
+        AndroidDeviceAdded(NULL, notificationIterators[i]);
+    }
+
+    return 0;
+}
+
+static void
+AndroidDeviceAdded(void *refCon, io_iterator_t iterator)
+{
+    kern_return_t            kr;
+    io_service_t             usbDevice;
+    IOCFPlugInInterface      **plugInInterface = NULL;
+    IOUSBDeviceInterface182  **dev = NULL;
+    HRESULT                  result;
+    SInt32                   score;
+    UInt16                   vendor;
+    UInt16                   product;
+    UInt8                    serialIndex;
+    char                     serial[256];
+
+    while ((usbDevice = IOIteratorNext(iterator))) {
+        //* Create an intermediate plugin
+        kr = IOCreatePlugInInterfaceForService(usbDevice,
+                                               kIOUSBDeviceUserClientTypeID,
+                                               kIOCFPlugInInterfaceID,
+                                               &plugInInterface, &score);
+
+        if ((kIOReturnSuccess != kr) || (!plugInInterface)) {
+            DBG("ERR: Unable to create a plug-in (%08x)\n", kr);
+            goto continue1;
+        }
+
+        //* Now create the device interface
+        result = (*plugInInterface)->QueryInterface(plugInInterface,
+                CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev);
+
+        if (result || !dev) {
+            DBG("ERR: Couldn't create a device interface (%08x)\n", (int) result);
+            goto continue2;
+        }
+
+        //* Check the device to see if it's ours
+        kr = (*dev)->GetDeviceVendor(dev, &vendor);
+        kr = (*dev)->GetDeviceProduct(dev, &product);
+        kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex);
+
+        if (serialIndex > 0) {
+            IOUSBDevRequest req;
+            UInt16          buffer[256];
+
+            req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
+            req.bRequest = kUSBRqGetDescriptor;
+            req.wValue = (kUSBStringDesc << 8) | serialIndex;
+            req.wIndex = 0;
+            req.pData = buffer;
+            req.wLength = sizeof(buffer);
+            kr = (*dev)->DeviceRequest(dev, &req);
+
+            if (kr == kIOReturnSuccess && req.wLenDone > 0) {
+                int i, count;
+
+                // skip first word, and copy the rest to the serial string, changing shorts to bytes.
+                count = (req.wLenDone - 1) / 2;
+                for (i = 0; i < count; i++)
+                  serial[i] = buffer[i + 1];
+                serial[i] = 0;
+            }
+        }
+
+        usb_handle* handle = NULL;
+
+        //* Open the device
+        kr = (*dev)->USBDeviceOpen(dev);
+
+        if (kr != kIOReturnSuccess) {
+            DBG("ERR: Could not open device: %08x\n", kr);
+            goto continue3;
+        } else {
+            //* Find an interface for the device
+            handle = FindDeviceInterface((IOUSBDeviceInterface**)dev, vendor, product);
+        }
+
+        if (handle == NULL) {
+            DBG("ERR: Could not find device interface: %08x\n", kr);
+            (*dev)->USBDeviceClose(dev);
+            goto continue3;
+        }
+
+        DBG("AndroidDeviceAdded calling register_usb_transport\n");
+        register_usb_transport(handle, (serial[0] ? serial : NULL));
+
+        // Register for an interest notification of this device being removed. Pass the reference to our
+        // private data as the refCon for the notification.
+        kr = IOServiceAddInterestNotification(notificationPort,
+                usbDevice,
+                kIOGeneralInterest,
+                AndroidDeviceNotify,
+                handle,
+                &handle->usbNotification);
+        if (kIOReturnSuccess != kr) {
+            DBG("ERR: Unable to create interest notification (%08x)\n", kr);
+        }
+
+continue3:
+        (void)(*dev)->Release(dev);
+continue2:
+        IODestroyPlugInInterface(plugInInterface);
+continue1:
+        IOObjectRelease(usbDevice);
+    }
+}
+
+static void
+AndroidDeviceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument)
+{
+    usb_handle *handle = (usb_handle *)refCon;
+
+    if (messageType == kIOMessageServiceIsTerminated) {
+        DBG("AndroidDeviceNotify\n");
+        IOObjectRelease(handle->usbNotification);
+        usb_kick(handle);
+    }
+}
+
+static usb_handle*
+FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product)
+{
+    usb_handle*                 handle = NULL;
+    IOReturn                    kr;
+    IOUSBFindInterfaceRequest   request;
+    io_iterator_t               iterator;
+    io_service_t                usbInterface;
+    IOCFPlugInInterface         **plugInInterface;
+    IOUSBInterfaceInterface     **interface = NULL;
+    HRESULT                     result;
+    SInt32                      score;
+    UInt8  interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol;
+    UInt8  endpoint, configuration;
+
+    //* Placing the constant KIOUSBFindInterfaceDontCare into the following
+    //* fields of the IOUSBFindInterfaceRequest structure will allow us to
+    //* find all of the interfaces
+    request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
+    request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
+    request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
+    request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
+
+    //* SetConfiguration will kill an existing UMS connection, so let's not do this if not necessary.
+    configuration = 0;
+    (*dev)->GetConfiguration(dev, &configuration);
+    if (configuration != 1)
+        (*dev)->SetConfiguration(dev, 1);
+
+    //* Get an iterator for the interfaces on the device
+    kr = (*dev)->CreateInterfaceIterator(dev, &request, &iterator);
+
+    if (kr != kIOReturnSuccess) {
+        DBG("ERR: Couldn't create a device interface iterator: (%08x)\n", kr);
+        return NULL;
+    }
+
+    while ((usbInterface = IOIteratorNext(iterator))) {
+    //* Create an intermediate plugin
+        kr = IOCreatePlugInInterfaceForService(
+                usbInterface,
+                kIOUSBInterfaceUserClientTypeID,
+                kIOCFPlugInInterfaceID,
+                &plugInInterface,
+                &score);
+
+        //* No longer need the usbInterface object now that we have the plugin
+        (void) IOObjectRelease(usbInterface);
+
+        if ((kr != kIOReturnSuccess) || (!plugInInterface)) {
+            DBG("ERR: Unable to create plugin (%08x)\n", kr);
+            break;
+        }
+
+        //* Now create the interface interface for the interface
+        result = (*plugInInterface)->QueryInterface(
+                plugInInterface,
+                CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
+                (LPVOID) &interface);
+
+        //* No longer need the intermediate plugin
+        (*plugInInterface)->Release(plugInInterface);
+
+        if (result || !interface) {
+            DBG("ERR: Couldn't create interface interface: (%08x)\n",
+               (unsigned int) result);
+            break;
+        }
+
+        //* Now open the interface.  This will cause the pipes associated with
+        //* the endpoints in the interface descriptor to be instantiated
+        kr = (*interface)->USBInterfaceOpen(interface);
+
+        if (kr != kIOReturnSuccess)
+        {
+            DBG("ERR: Could not open interface: (%08x)\n", kr);
+            (void) (*interface)->Release(interface);
+            //* continue so we can try the next interface
+            continue;
+        }
+
+        //* Get the number of endpoints associated with this interface
+        kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints);
+
+        if (kr != kIOReturnSuccess) {
+            DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr);
+            goto next_interface;
+        }
+
+        //* Get interface class, subclass and protocol
+        if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess ||
+            (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess ||
+            (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess)
+        {
+            DBG("ERR: Unable to get interface class, subclass and protocol\n");
+            goto next_interface;
+        }
+
+        //* check to make sure interface class, subclass and protocol match ADB
+        //* avoid opening mass storage endpoints
+        if (is_adb_interface(vendor, product, interfaceClass, interfaceSubClass, interfaceProtocol)) {
+            handle = calloc(1, sizeof(usb_handle));
+
+            //* Iterate over the endpoints for this interface and find the first
+            //* bulk in/out pipes available.  These will be our read/write pipes.
+            for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) {
+                UInt8   transferType;
+                UInt16  maxPacketSize;
+                UInt8   interval;
+                UInt8   number;
+                UInt8   direction;
+
+                kr = (*interface)->GetPipeProperties(interface, endpoint, &direction,
+                        &number, &transferType, &maxPacketSize, &interval);
+
+                if (kIOReturnSuccess == kr) {
+                    if (kUSBBulk != transferType)
+                        continue;
+
+                    if (kUSBIn == direction)
+                        handle->bulkIn = endpoint;
+
+                    if (kUSBOut == direction)
+                        handle->bulkOut = endpoint;
+
+                    if (interfaceProtocol == 0x01) {
+                        handle->zero_mask = maxPacketSize - 1;
+                    }
+
+                } else {
+                    DBG("ERR: FindDeviceInterface - could not get pipe properties\n");
+                }
+            }
+
+            handle->interface = interface;
+            break;
+        }
+
+next_interface:
+        (*interface)->USBInterfaceClose(interface);
+        (*interface)->Release(interface);
+    }
+
+    return handle;
+}
+
+
+void* RunLoopThread(void* unused)
+{
+    int i;
+
+    InitUSB();
+
+    currentRunLoop = CFRunLoopGetCurrent();
+
+    // Signal the parent that we are running
+    adb_mutex_lock(&start_lock);
+    adb_cond_signal(&start_cond);
+    adb_mutex_unlock(&start_lock);
+
+    CFRunLoopRun();
+    currentRunLoop = 0;
+
+    for (i = 0; i < kSupportedDeviceCount; i++) {
+        IOObjectRelease(notificationIterators[i]);
+    }
+    IONotificationPortDestroy(notificationPort);
+
+    DBG("RunLoopThread done\n");
+    return NULL;    
+}
+
+
+static int initialized = 0;
+void usb_init()
+{
+    if (!initialized)
+    {
+        adb_thread_t    tid;
+
+        adb_mutex_init(&start_lock, NULL);
+        adb_cond_init(&start_cond, NULL);
+
+        if(adb_thread_create(&tid, RunLoopThread, NULL))
+            fatal_errno("cannot create input thread");
+
+        // Wait for initialization to finish
+        adb_mutex_lock(&start_lock);
+        adb_cond_wait(&start_cond, &start_lock);
+        adb_mutex_unlock(&start_lock);
+
+        adb_mutex_destroy(&start_lock);
+        adb_cond_destroy(&start_cond);
+
+        initialized = 1;
+    }
+}
+
+void usb_cleanup()
+{
+    DBG("usb_cleanup\n");
+    close_usb_devices();
+    if (currentRunLoop)
+        CFRunLoopStop(currentRunLoop);
+}
+
+int usb_write(usb_handle *handle, const void *buf, int len)
+{
+    IOReturn    result;
+
+    if (!len)
+        return 0;
+
+    if (!handle)
+        return -1;
+
+    if (NULL == handle->interface) {
+        DBG("ERR: usb_write interface was null\n");
+        return -1;
+    }
+
+    if (0 == handle->bulkOut) {
+        DBG("ERR: bulkOut endpoint not assigned\n");
+        return -1;
+    }
+
+    result =
+        (*handle->interface)->WritePipe(
+                              handle->interface, handle->bulkOut, (void *)buf, len);
+
+    if ((result == 0) && (handle->zero_mask)) {
+        /* we need 0-markers and our transfer */
+        if(!(len & handle->zero_mask)) {
+            result =
+                (*handle->interface)->WritePipe(
+                        handle->interface, handle->bulkOut, (void *)buf, 0);
+        }
+    }
+
+    if (0 == result)
+        return 0;
+
+    DBG("ERR: usb_write failed with status %d\n", result);
+    return -1;
+}
+
+int usb_read(usb_handle *handle, void *buf, int len)
+{
+    IOReturn result;
+    UInt32  numBytes = len;
+
+    if (!len) {
+        return 0;
+    }
+
+    if (!handle) {
+        return -1;
+    }
+
+    if (NULL == handle->interface) {
+        DBG("ERR: usb_read interface was null\n");
+        return -1;
+    }
+
+    if (0 == handle->bulkIn) {
+        DBG("ERR: bulkIn endpoint not assigned\n");
+        return -1;
+    }
+
+    result =
+      (*handle->interface)->ReadPipe(handle->interface,
+                                    handle->bulkIn, buf, &numBytes);
+
+    if (0 == result)
+        return 0;
+    else {
+        DBG("ERR: usb_read failed with status %d\n", result);
+    }
+
+    return -1;
+}
+
+int usb_close(usb_handle *handle)
+{
+    return 0;
+}
+
+void usb_kick(usb_handle *handle)
+{
+    /* release the interface */
+    if (handle->interface)
+    {
+        (*handle->interface)->USBInterfaceClose(handle->interface);
+        (*handle->interface)->Release(handle->interface);
+        handle->interface = 0;
+    }
+}