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 ¬ificationIterators[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