From 66e4691ad097cfc37bdb7d3b1705ee9132f3234e Mon Sep 17 00:00:00 2001 From: Xavier Ducrohet Date: Tue, 2 Jun 2009 12:03:55 -0700 Subject: [PATCH] AI 149490: Add support for 3rd party USB Vendor. BUG=1890147 Automated import of CL 149490 --- adb/Android.mk | 1 + adb/adb.c | 3 + adb/adb.h | 17 +- adb/adb_client.c | 2 +- adb/transport_usb.c | 26 +-- adb/usb_osx.c | 401 +++++++++++++++++++++----------------------- adb/usb_vendors.c | 134 +++++++++++++++ adb/usb_vendors.h | 25 +++ 8 files changed, 372 insertions(+), 237 deletions(-) create mode 100644 adb/usb_vendors.c create mode 100644 adb/usb_vendors.h diff --git a/adb/Android.mk b/adb/Android.mk index 2296610a3..ed8b501db 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -54,6 +54,7 @@ LOCAL_SRC_FILES := \ $(USB_SRCS) \ shlist.c \ utils.c \ + usb_vendors.c \ ifneq ($(USE_SYSDEPS_WIN32),) diff --git a/adb/adb.c b/adb/adb.c index 12a36f5c2..36130cd58 100644 --- a/adb/adb.c +++ b/adb/adb.c @@ -29,6 +29,8 @@ #if !ADB_HOST #include +#else +#include "usb_vendors.h" #endif @@ -846,6 +848,7 @@ int adb_main(int is_daemon) #if ADB_HOST HOST = 1; + usb_vendors_init(); usb_init(); local_init(); diff --git a/adb/adb.h b/adb/adb.h index a17c8ddc5..6c5fc7cca 100644 --- a/adb/adb.h +++ b/adb/adb.h @@ -357,18 +357,9 @@ typedef enum { #define ADB_PORT 5037 #define ADB_LOCAL_TRANSPORT_PORT 5555 -// Google's USB Vendor ID -#define VENDOR_ID_GOOGLE 0x18d1 -// HTC's USB Vendor ID -#define VENDOR_ID_HTC 0x0bb4 - -// products for VENDOR_ID_GOOGLE -#define PRODUCT_ID_SOONER 0xd00d // Sooner bootloader -#define PRODUCT_ID_SOONER_COMP 0xdeed // Sooner composite device - -// products for VENDOR_ID_HTC -#define PRODUCT_ID_DREAM 0x0c01 // Dream bootloader -#define PRODUCT_ID_DREAM_COMP 0x0c02 // Dream composite device +#define ADB_CLASS 0xff +#define ADB_SUBCLASS 0x42 +#define ADB_PROTOCOL 0x1 void local_init(); int local_connect(int port); @@ -382,7 +373,9 @@ int usb_close(usb_handle *h); void usb_kick(usb_handle *h); /* used for USB device detection */ +#if ADB_HOST int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol); +#endif unsigned host_to_le32(unsigned n); int adb_commandline(int argc, char **argv); diff --git a/adb/adb_client.c b/adb/adb_client.c index 586874480..243f0fa53 100644 --- a/adb/adb_client.c +++ b/adb/adb_client.c @@ -213,7 +213,7 @@ int adb_connect(const char *service) fprintf(stdout,"* daemon started successfully *\n"); } /* give the server some time to start properly and detect devices */ - adb_sleep_ms(2000); + adb_sleep_ms(3000); // fall through to _adb_connect } else { // if server was running, check its version to make sure it is not out of date diff --git a/adb/transport_usb.c b/adb/transport_usb.c index 01c4a7ede..3737c5c1e 100644 --- a/adb/transport_usb.c +++ b/adb/transport_usb.c @@ -23,6 +23,10 @@ #define TRACE_TAG TRACE_TRANSPORT #include "adb.h" +#if ADB_HOST +#include "usb_vendors.h" +#endif + /* XXX better define? */ #ifdef __ppc__ #define H4(x) (((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24) @@ -125,23 +129,21 @@ void init_usb_transport(atransport *t, usb_handle *h) #endif } +#if ADB_HOST int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol) { - if (vid == VENDOR_ID_GOOGLE) { - /* might support adb */ - } else if (vid == VENDOR_ID_HTC) { - /* might support adb */ - } else { - /* not supported */ - return 0; - } + unsigned i; + for (i = 0; i < vendorIdCount; i++) { + if (vid == vendorIds[i]) { + if (usb_class == ADB_CLASS && usb_subclass == ADB_SUBCLASS && + usb_protocol == ADB_PROTOCOL) { + return 1; + } - /* class:vendor (0xff) subclass:android (0x42) proto:adb (0x01) */ - if(usb_class == 0xff) { - if((usb_subclass == 0x42) && (usb_protocol == 0x01)) { - return 1; + return 0; } } return 0; } +#endif diff --git a/adb/usb_osx.c b/adb/usb_osx.c index 49e1eef5b..4892c38b3 100644 --- a/adb/usb_osx.c +++ b/adb/usb_osx.c @@ -28,24 +28,12 @@ #define TRACE_TAG TRACE_USB #include "adb.h" +#include "usb_vendors.h" #define DBG D -typedef struct { - int vid; - int pid; -} VendorProduct; - -#define kSupportedDeviceCount 4 -VendorProduct kSupportedDevices[kSupportedDeviceCount] = { - { VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER }, - { VENDOR_ID_GOOGLE, PRODUCT_ID_SOONER_COMP }, - { VENDOR_ID_HTC, PRODUCT_ID_DREAM }, - { VENDOR_ID_HTC, PRODUCT_ID_DREAM_COMP }, -}; - static IONotificationPortRef notificationPort = 0; -static io_iterator_t notificationIterators[kSupportedDeviceCount]; +static io_iterator_t* notificationIterators; struct usb_handle { @@ -61,17 +49,20 @@ static pthread_mutex_t start_lock; static pthread_cond_t start_cond; -static void AndroidDeviceAdded(void *refCon, io_iterator_t iterator); -static void AndroidDeviceNotify(void *refCon, io_iterator_t iterator, natural_t messageType, void *messageArgument); -static usb_handle* FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product); +static void AndroidInterfaceAdded(void *refCon, io_iterator_t iterator); +static void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator, + natural_t messageType, + void *messageArgument); +static usb_handle* CheckInterface(IOUSBInterfaceInterface **iface, + UInt16 vendor, UInt16 product); static int InitUSB() { CFMutableDictionaryRef matchingDict; CFRunLoopSourceRef runLoopSource; - SInt32 vendor, product; - int i; + SInt32 vendor, if_subclass, if_protocol; + unsigned i; //* To set up asynchronous notifications, create a notification port and //* add its run loop event source to the program's run loop @@ -81,51 +72,57 @@ InitUSB() memset(notificationIterators, 0, sizeof(notificationIterators)); - //* loop through all supported vendor/product pairs - for (i = 0; i < kSupportedDeviceCount; i++) { - //* Create our matching dictionary to find the Android device - //* IOServiceAddMatchingNotification consumes the reference, so we do not need to release this - matchingDict = IOServiceMatching(kIOUSBDeviceClassName); + //* loop through all supported vendors + for (i = 0; i < vendorIdCount; i++) { + //* Create our matching dictionary to find the Android device's + //* adb interface + //* IOServiceAddMatchingNotification consumes the reference, so we do + //* not need to release this + matchingDict = IOServiceMatching(kIOUSBInterfaceClassName); if (!matchingDict) { DBG("ERR: Couldn't create USB matching dictionary.\n"); return -1; } - //* Set up two matching dictionaries, one for each product ID we support. - //* This will cause the kernel to notify us only if the vendor and product IDs match. - vendor = kSupportedDevices[i].vid; - product = kSupportedDevices[i].pid; - CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vendor)); - CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &product)); - - //* Now set up two notifications: one to be called when a raw device - //* is first matched by the I/O Kit and another to be called when the - //* device is terminated. - //* we need to do this with each matching dictionary. + //* Match based on vendor id, interface subclass and protocol + vendor = vendorIds[i]; + if_subclass = ADB_SUBCLASS; + if_protocol = ADB_PROTOCOL; + CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), + CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt32Type, &vendor)); + CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceSubClass), + CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt32Type, &if_subclass)); + CFDictionarySetValue(matchingDict, CFSTR(kUSBInterfaceProtocol), + CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt32Type, &if_protocol)); IOServiceAddMatchingNotification( notificationPort, kIOFirstMatchNotification, matchingDict, - AndroidDeviceAdded, + AndroidInterfaceAdded, NULL, ¬ificationIterators[i]); - //* Iterate over set of matching devices to access already-present devices - //* and to arm the notification - AndroidDeviceAdded(NULL, notificationIterators[i]); + //* Iterate over set of matching interfaces to access already-present + //* devices and to arm the notification + AndroidInterfaceAdded(NULL, notificationIterators[i]); } return 0; } static void -AndroidDeviceAdded(void *refCon, io_iterator_t iterator) +AndroidInterfaceAdded(void *refCon, io_iterator_t iterator) { kern_return_t kr; io_service_t usbDevice; + io_service_t usbInterface; IOCFPlugInInterface **plugInInterface = NULL; - IOUSBDeviceInterface182 **dev = NULL; + IOUSBInterfaceInterface220 **iface = NULL; + IOUSBDeviceInterface197 **dev = NULL; HRESULT result; SInt32 score; UInt16 vendor; @@ -133,28 +130,66 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator) UInt8 serialIndex; char serial[256]; - while ((usbDevice = IOIteratorNext(iterator))) { - //* Create an intermediate plugin + while ((usbInterface = IOIteratorNext(iterator))) { + //* Create an intermediate interface plugin + kr = IOCreatePlugInInterfaceForService(usbInterface, + kIOUSBInterfaceUserClientTypeID, + kIOCFPlugInInterfaceID, + &plugInInterface, &score); + IOObjectRelease(usbInterface); + if ((kIOReturnSuccess != kr) || (!plugInInterface)) { + DBG("ERR: Unable to create an interface plug-in (%08x)\n", kr); + continue; + } + + //* This gets us the interface object + result = (*plugInInterface)->QueryInterface(plugInInterface, + CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID) + &iface); + //* We only needed the plugin to get the interface, so discard it + (*plugInInterface)->Release(plugInInterface); + if (result || !iface) { + DBG("ERR: Couldn't query the interface (%08x)\n", (int) result); + continue; + } + + //* this gets us an ioservice, with which we will find the actual + //* device; after getting a plugin, and querying the interface, of + //* course. + //* Gotta love OS X + kr = (*iface)->GetDevice(iface, &usbDevice); + if (kIOReturnSuccess != kr || !usbDevice) { + DBG("ERR: Couldn't grab device from interface (%08x)\n", kr); + continue; + } + + plugInInterface = NULL; + score = 0; + //* create an intermediate device plugin kr = IOCreatePlugInInterfaceForService(usbDevice, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); - + //* only needed this to find the plugin + (void)IOObjectRelease(usbDevice); if ((kIOReturnSuccess != kr) || (!plugInInterface)) { - DBG("ERR: Unable to create a plug-in (%08x)\n", kr); - goto continue1; + DBG("ERR: Unable to create a device plug-in (%08x)\n", kr); + continue; } - //* Now create the device interface result = (*plugInInterface)->QueryInterface(plugInInterface, CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID) &dev); - + //* only needed this to query the plugin + (*plugInInterface)->Release(plugInInterface); if (result || !dev) { - DBG("ERR: Couldn't create a device interface (%08x)\n", (int) result); - goto continue2; + DBG("ERR: Couldn't create a device interface (%08x)\n", + (int) result); + continue; } - //* Check the device to see if it's ours + //* Now after all that, we actually have a ref to the device and + //* the interface that matched our criteria + kr = (*dev)->GetDeviceVendor(dev, &vendor); kr = (*dev)->GetDeviceProduct(dev, &product); kr = (*dev)->USBGetSerialNumberStringIndex(dev, &serialIndex); @@ -163,7 +198,8 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator) IOUSBDevRequest req; UInt16 buffer[256]; - req.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); + req.bmRequestType = + USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice); req.bRequest = kUSBRqGetDescriptor; req.wValue = (kUSBStringDesc << 8) | serialIndex; req.wIndex = 0; @@ -174,219 +210,149 @@ AndroidDeviceAdded(void *refCon, io_iterator_t iterator) if (kr == kIOReturnSuccess && req.wLenDone > 0) { int i, count; - // skip first word, and copy the rest to the serial string, changing shorts to bytes. + // skip first word, and copy the rest to the serial string, + // changing shorts to bytes. count = (req.wLenDone - 1) / 2; for (i = 0; i < count; i++) serial[i] = buffer[i + 1]; serial[i] = 0; } } + (*dev)->Release(dev); - usb_handle* handle = NULL; - - //* Open the device - kr = (*dev)->USBDeviceOpen(dev); - - if (kr != kIOReturnSuccess) { - DBG("ERR: Could not open device: %08x\n", kr); - goto continue3; - } else { - //* Find an interface for the device - handle = FindDeviceInterface((IOUSBDeviceInterface**)dev, vendor, product); - } + DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product, + serial); + usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface, + vendor, product); if (handle == NULL) { DBG("ERR: Could not find device interface: %08x\n", kr); - (*dev)->USBDeviceClose(dev); - goto continue3; + (*iface)->Release(iface); + continue; } DBG("AndroidDeviceAdded calling register_usb_transport\n"); register_usb_transport(handle, (serial[0] ? serial : NULL)); - // Register for an interest notification of this device being removed. Pass the reference to our - // private data as the refCon for the notification. + // Register for an interest notification of this device being removed. + // Pass the reference to our private data as the refCon for the + // notification. kr = IOServiceAddInterestNotification(notificationPort, - usbDevice, + usbInterface, kIOGeneralInterest, - AndroidDeviceNotify, + AndroidInterfaceNotify, handle, &handle->usbNotification); + if (kIOReturnSuccess != kr) { DBG("ERR: Unable to create interest notification (%08x)\n", kr); } - -continue3: - (void)(*dev)->Release(dev); -continue2: - IODestroyPlugInInterface(plugInInterface); -continue1: - IOObjectRelease(usbDevice); } } static void -AndroidDeviceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) +AndroidInterfaceNotify(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) { usb_handle *handle = (usb_handle *)refCon; if (messageType == kIOMessageServiceIsTerminated) { - DBG("AndroidDeviceNotify\n"); + if (!handle) { + DBG("ERR: NULL handle\n"); + return; + } + DBG("AndroidInterfaceNotify\n"); IOObjectRelease(handle->usbNotification); usb_kick(handle); } } +//* TODO: simplify this further since we only register to get ADB interface +//* subclass+protocol events static usb_handle* -FindDeviceInterface(IOUSBDeviceInterface **dev, UInt16 vendor, UInt16 product) +CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product) { usb_handle* handle = NULL; IOReturn kr; - IOUSBFindInterfaceRequest request; - io_iterator_t iterator; - io_service_t usbInterface; - IOCFPlugInInterface **plugInInterface; - IOUSBInterfaceInterface **interface = NULL; - HRESULT result; - SInt32 score; UInt8 interfaceNumEndpoints, interfaceClass, interfaceSubClass, interfaceProtocol; - UInt8 endpoint, configuration; + UInt8 endpoint; - //* Placing the constant KIOUSBFindInterfaceDontCare into the following - //* fields of the IOUSBFindInterfaceRequest structure will allow us to - //* find all of the interfaces - request.bInterfaceClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; - request.bAlternateSetting = kIOUSBFindInterfaceDontCare; - - //* SetConfiguration will kill an existing UMS connection, so let's not do this if not necessary. - configuration = 0; - (*dev)->GetConfiguration(dev, &configuration); - if (configuration != 1) - (*dev)->SetConfiguration(dev, 1); - - //* Get an iterator for the interfaces on the device - kr = (*dev)->CreateInterfaceIterator(dev, &request, &iterator); + //* Now open the interface. This will cause the pipes associated with + //* the endpoints in the interface descriptor to be instantiated + kr = (*interface)->USBInterfaceOpen(interface); if (kr != kIOReturnSuccess) { - DBG("ERR: Couldn't create a device interface iterator: (%08x)\n", kr); + DBG("ERR: Could not open interface: (%08x)\n", kr); return NULL; } - while ((usbInterface = IOIteratorNext(iterator))) { - //* Create an intermediate plugin - kr = IOCreatePlugInInterfaceForService( - usbInterface, - kIOUSBInterfaceUserClientTypeID, - kIOCFPlugInInterfaceID, - &plugInInterface, - &score); - - //* No longer need the usbInterface object now that we have the plugin - (void) IOObjectRelease(usbInterface); - - if ((kr != kIOReturnSuccess) || (!plugInInterface)) { - DBG("ERR: Unable to create plugin (%08x)\n", kr); - break; - } - - //* Now create the interface interface for the interface - result = (*plugInInterface)->QueryInterface( - plugInInterface, - CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), - (LPVOID) &interface); - - //* No longer need the intermediate plugin - (*plugInInterface)->Release(plugInInterface); - - if (result || !interface) { - DBG("ERR: Couldn't create interface interface: (%08x)\n", - (unsigned int) result); - break; - } - - //* Now open the interface. This will cause the pipes associated with - //* the endpoints in the interface descriptor to be instantiated - kr = (*interface)->USBInterfaceOpen(interface); - - if (kr != kIOReturnSuccess) - { - DBG("ERR: Could not open interface: (%08x)\n", kr); - (void) (*interface)->Release(interface); - //* continue so we can try the next interface - continue; - } - - //* Get the number of endpoints associated with this interface - kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints); - - if (kr != kIOReturnSuccess) { - DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr); - goto next_interface; - } - - //* Get interface class, subclass and protocol - if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess || - (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess || - (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) - { - DBG("ERR: Unable to get interface class, subclass and protocol\n"); - goto next_interface; - } - - //* check to make sure interface class, subclass and protocol match ADB - //* avoid opening mass storage endpoints - if (is_adb_interface(vendor, product, interfaceClass, interfaceSubClass, interfaceProtocol)) { - handle = calloc(1, sizeof(usb_handle)); - - //* Iterate over the endpoints for this interface and find the first - //* bulk in/out pipes available. These will be our read/write pipes. - for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) { - UInt8 transferType; - UInt16 maxPacketSize; - UInt8 interval; - UInt8 number; - UInt8 direction; - - kr = (*interface)->GetPipeProperties(interface, endpoint, &direction, - &number, &transferType, &maxPacketSize, &interval); - - if (kIOReturnSuccess == kr) { - if (kUSBBulk != transferType) - continue; - - if (kUSBIn == direction) - handle->bulkIn = endpoint; - - if (kUSBOut == direction) - handle->bulkOut = endpoint; - - if (interfaceProtocol == 0x01) { - handle->zero_mask = maxPacketSize - 1; - } - - } else { - DBG("ERR: FindDeviceInterface - could not get pipe properties\n"); - } - } - - handle->interface = interface; - break; - } - -next_interface: - (*interface)->USBInterfaceClose(interface); - (*interface)->Release(interface); + //* Get the number of endpoints associated with this interface + kr = (*interface)->GetNumEndpoints(interface, &interfaceNumEndpoints); + if (kr != kIOReturnSuccess) { + DBG("ERR: Unable to get number of endpoints: (%08x)\n", kr); + goto err_get_num_ep; } + //* Get interface class, subclass and protocol + if ((*interface)->GetInterfaceClass(interface, &interfaceClass) != kIOReturnSuccess || + (*interface)->GetInterfaceSubClass(interface, &interfaceSubClass) != kIOReturnSuccess || + (*interface)->GetInterfaceProtocol(interface, &interfaceProtocol) != kIOReturnSuccess) { + DBG("ERR: Unable to get interface class, subclass and protocol\n"); + goto err_get_interface_class; + } + + //* check to make sure interface class, subclass and protocol match ADB + //* avoid opening mass storage endpoints + if (!is_adb_interface(vendor, product, interfaceClass, + interfaceSubClass, interfaceProtocol)) + goto err_bad_adb_interface; + + handle = calloc(1, sizeof(usb_handle)); + + //* Iterate over the endpoints for this interface and find the first + //* bulk in/out pipes available. These will be our read/write pipes. + for (endpoint = 0; endpoint <= interfaceNumEndpoints; endpoint++) { + UInt8 transferType; + UInt16 maxPacketSize; + UInt8 interval; + UInt8 number; + UInt8 direction; + + kr = (*interface)->GetPipeProperties(interface, endpoint, &direction, + &number, &transferType, &maxPacketSize, &interval); + + if (kIOReturnSuccess == kr) { + if (kUSBBulk != transferType) + continue; + + if (kUSBIn == direction) + handle->bulkIn = endpoint; + + if (kUSBOut == direction) + handle->bulkOut = endpoint; + + handle->zero_mask = maxPacketSize - 1; + } else { + DBG("ERR: FindDeviceInterface - could not get pipe properties\n"); + goto err_get_pipe_props; + } + } + + handle->interface = interface; return handle; + +err_get_pipe_props: + free(handle); +err_bad_adb_interface: +err_get_interface_class: +err_get_num_ep: + (*interface)->USBInterfaceClose(interface); + return NULL; } void* RunLoopThread(void* unused) { - int i; + unsigned i; InitUSB(); @@ -400,7 +366,7 @@ void* RunLoopThread(void* unused) CFRunLoopRun(); currentRunLoop = 0; - for (i = 0; i < kSupportedDeviceCount; i++) { + for (i = 0; i < vendorIdCount; i++) { IOObjectRelease(notificationIterators[i]); } IONotificationPortDestroy(notificationPort); @@ -417,6 +383,9 @@ void usb_init() { adb_thread_t tid; + notificationIterators = (io_iterator_t*)malloc( + vendorIdCount * sizeof(io_iterator_t)); + adb_mutex_init(&start_lock, NULL); adb_cond_init(&start_cond, NULL); @@ -441,6 +410,11 @@ void usb_cleanup() close_usb_devices(); if (currentRunLoop) CFRunLoopStop(currentRunLoop); + + if (notificationIterators != NULL) { + free(notificationIterators); + notificationIterators = NULL; + } } int usb_write(usb_handle *handle, const void *buf, int len) @@ -527,6 +501,9 @@ int usb_close(usb_handle *handle) void usb_kick(usb_handle *handle) { /* release the interface */ + if (!handle) + return; + if (handle->interface) { (*handle->interface)->USBInterfaceClose(handle->interface); diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c new file mode 100644 index 000000000..9a1514612 --- /dev/null +++ b/adb/usb_vendors.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "usb_vendors.h" + +#include + +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include "windows.h" +# include "shlobj.h" +#else +# include +# include +#endif + +#include "sysdeps.h" +#include "adb.h" + +#define ANDROID_PATH ".android" +#define ANDROID_ADB_INI "adb_usb.ini" + +#define TRACE_TAG TRACE_USB + +// Google's USB Vendor ID +#define VENDOR_ID_GOOGLE 0x18d1 +// HTC's USB Vendor ID +#define VENDOR_ID_HTC 0x0bb4 + +/** built-in vendor list */ +int builtInVendorIds[] = { + VENDOR_ID_GOOGLE, + VENDOR_ID_HTC, +}; + +#define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0])) + +/* max number of supported vendor ids (built-in + 3rd party). increase as needed */ +#define VENDOR_COUNT_MAX 128 + +int vendorIds[VENDOR_COUNT_MAX]; +unsigned vendorIdCount = 0; + +int get_adb_usb_ini(char* buff, size_t len); + +void usb_vendors_init(void) +{ + if (VENDOR_COUNT_MAX < BUILT_IN_VENDOR_COUNT) { + fprintf(stderr, "VENDOR_COUNT_MAX not big enough for built-in vendor list.\n"); + exit(2); + } + + /* add the built-in vendors at the beginning of the array */ + memcpy(vendorIds, builtInVendorIds, sizeof(builtInVendorIds)); + + /* default array size is the number of built-in vendors */ + vendorIdCount = BUILT_IN_VENDOR_COUNT; + + if (VENDOR_COUNT_MAX == BUILT_IN_VENDOR_COUNT) + return; + + char temp[PATH_MAX]; + if (get_adb_usb_ini(temp, sizeof(temp)) == 0) { + FILE * f = fopen(temp, "rt"); + + if (f != NULL) { + /* The vendor id file is pretty basic. 1 vendor id per line. + Lines starting with # are comments */ + while (fgets(temp, sizeof(temp), f) != NULL) { + if (temp[0] == '#') + continue; + + long value = strtol(temp, NULL, 0); + if (errno == EINVAL || errno == ERANGE || value > INT_MAX || value < 0) { + fprintf(stderr, "Invalid content in %s. Quitting.\n", ANDROID_ADB_INI); + exit(2); + } + + vendorIds[vendorIdCount++] = (int)value; + + /* make sure we don't go beyond the array */ + if (vendorIdCount == VENDOR_COUNT_MAX) { + break; + } + } + } + } +} + +/* Utils methods */ + +/* builds the path to the adb vendor id file. returns 0 if success */ +int build_path(char* buff, size_t len, const char* format, const char* home) +{ + if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_ADB_INI) >= len) { + return 1; + } + + return 0; +} + +/* fills buff with the path to the adb vendor id file. returns 0 if success */ +int get_adb_usb_ini(char* buff, size_t len) +{ +#ifdef _WIN32 + const char* home = getenv("ANDROID_SDK_HOME"); + if (home != NULL) { + return build_path(buff, len, "%s\\%s\\%s", home); + } else { + char path[MAX_PATH]; + SHGetFolderPath( NULL, CSIDL_PROFILE, NULL, 0, path); + return build_path(buff, len, "%s\\%s\\%s", path); + } +#else + const char* home = getenv("HOME"); + if (home == NULL) + home = "/tmp"; + + return build_path(buff, len, "%s/%s/%s", home); +#endif +} diff --git a/adb/usb_vendors.h b/adb/usb_vendors.h new file mode 100644 index 000000000..43790b904 --- /dev/null +++ b/adb/usb_vendors.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __USB_VENDORS_H +#define __USB_VENDORS_H + +extern int vendorIds[]; +extern unsigned vendorIdCount; + +void usb_vendors_init(void); + +#endif \ No newline at end of file