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