AI 149490: Add support for 3rd party USB Vendor.
BUG=1890147
Automated import of CL 149490
diff --git a/adb/Android.mk b/adb/Android.mk
index 2296610..ed8b501 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -54,6 +54,7 @@
$(USB_SRCS) \
shlist.c \
utils.c \
+ usb_vendors.c \
ifneq ($(USE_SYSDEPS_WIN32),)
diff --git a/adb/adb.c b/adb/adb.c
index 12a36f5..36130cd 100644
--- a/adb/adb.c
+++ b/adb/adb.c
@@ -29,6 +29,8 @@
#if !ADB_HOST
#include <private/android_filesystem_config.h>
+#else
+#include "usb_vendors.h"
#endif
@@ -846,6 +848,7 @@
#if ADB_HOST
HOST = 1;
+ usb_vendors_init();
usb_init();
local_init();
diff --git a/adb/adb.h b/adb/adb.h
index a17c8dd..6c5fc7c 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -357,18 +357,9 @@
#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 @@
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 5868744..243f0fa 100644
--- a/adb/adb_client.c
+++ b/adb/adb_client.c
@@ -213,7 +213,7 @@
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 01c4a7e..3737c5c 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 @@
#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 49e1eef..4892c38 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_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 @@
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 @@
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 @@
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 @@
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;
+ DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product,
+ serial);
- //* 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);
- }
-
+ 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 @@
CFRunLoopRun();
currentRunLoop = 0;
- for (i = 0; i < kSupportedDeviceCount; i++) {
+ for (i = 0; i < vendorIdCount; i++) {
IOObjectRelease(notificationIterators[i]);
}
IONotificationPortDestroy(notificationPort);
@@ -417,6 +383,9 @@
{
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 @@
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 @@
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 0000000..9a15146
--- /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 <stdio.h>
+
+#ifdef _WIN32
+# define WIN32_LEAN_AND_MEAN
+# include "windows.h"
+# include "shlobj.h"
+#else
+# include <unistd.h>
+# include <sys/stat.h>
+#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 0000000..43790b9
--- /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