Disable vendor id filtering for OS X.

Companion patch for change I2bf583a27f9a3f98ef006ea62b906a4f89960507.

Due to the use of USB class 0xff it's not possible to register a listener
which uses the OS methods for filtering notifications, so this patch
also introduces a check in the notification listener which checks the
class, subclass, and protocol for the interface each notification relates 
to.

Change-Id: I380cc80f96addc5057660efb2179b35f9378886a
diff --git a/adb/usb_osx.c b/adb/usb_osx.c
index ee893f5..ba157f1 100644
--- a/adb/usb_osx.c
+++ b/adb/usb_osx.c
@@ -28,12 +28,11 @@
 
 #define TRACE_TAG   TRACE_USB
 #include "adb.h"
-#include "usb_vendors.h"
 
 #define  DBG   D
 
 static IONotificationPortRef    notificationPort = 0;
-static io_iterator_t*           notificationIterators;
+static io_iterator_t            notificationIterator;
 
 struct usb_handle
 {
@@ -61,8 +60,6 @@
 {
     CFMutableDictionaryRef  matchingDict;
     CFRunLoopSourceRef      runLoopSource;
-    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
@@ -70,47 +67,33 @@
     runLoopSource = IONotificationPortGetRunLoopSource(notificationPort);
     CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopDefaultMode);
 
-    memset(notificationIterators, 0, sizeof(notificationIterators));
+    //* 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);
 
-    //* 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;
-        }
-
-        //* 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,
-                AndroidInterfaceAdded,
-                NULL,
-                &notificationIterators[i]);
-
-        //* Iterate over set of matching interfaces to access already-present
-        //* devices and to arm the notification
-        AndroidInterfaceAdded(NULL, notificationIterators[i]);
+    if (!matchingDict) {
+        DBG("ERR: Couldn't create USB matching dictionary.\n");
+        return -1;
     }
 
+    //* We have to get notifications for all potential candidates and test them
+    //* at connection time because the matching rules don't allow for a
+    //* USB interface class of 0xff for class+subclass+protocol matches
+    //* See https://developer.apple.com/library/mac/qa/qa1076/_index.html
+    IOServiceAddMatchingNotification(
+            notificationPort,
+            kIOFirstMatchNotification,
+            matchingDict,
+            AndroidInterfaceAdded,
+            NULL,
+            &notificationIterator);
+
+    //* Iterate over set of matching interfaces to access already-present
+    //* devices and to arm the notification
+    AndroidInterfaceAdded(NULL, notificationIterator);
+
     return 0;
 }
 
@@ -126,6 +109,7 @@
     HRESULT                  result;
     SInt32                   score;
     UInt32                   locationId;
+    UInt8                    class, subclass, protocol;
     UInt16                   vendor;
     UInt16                   product;
     UInt8                    serialIndex;
@@ -156,6 +140,16 @@
             continue;
         }
 
+        kr = (*iface)->GetInterfaceClass(iface, &class);
+        kr = (*iface)->GetInterfaceSubClass(iface, &subclass);
+        kr = (*iface)->GetInterfaceProtocol(iface, &protocol);
+        if(class != ADB_CLASS || subclass != ADB_SUBCLASS || protocol != ADB_PROTOCOL) {
+            // Ignore non-ADB devices.
+            DBG("Ignoring interface with incorrect class/subclass/protocol - %d, %d, %d\n", class, subclass, protocol);
+            (*iface)->Release(iface);
+            continue;
+        }
+
         //* this gets us an ioservice, with which we will find the actual
         //* device; after getting a plugin, and querying the interface, of
         //* course.
@@ -192,7 +186,6 @@
 
         //* 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)->GetLocationID(dev, &locationId);
@@ -385,8 +378,6 @@
 
 void* RunLoopThread(void* unused)
 {
-    unsigned i;
-
     InitUSB();
 
     currentRunLoop = CFRunLoopGetCurrent();
@@ -399,9 +390,7 @@
     CFRunLoopRun();
     currentRunLoop = 0;
 
-    for (i = 0; i < vendorIdCount; i++) {
-        IOObjectRelease(notificationIterators[i]);
-    }
+    IOObjectRelease(notificationIterator);
     IONotificationPortDestroy(notificationPort);
 
     DBG("RunLoopThread done\n");
@@ -416,9 +405,6 @@
     {
         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);
 
@@ -443,11 +429,6 @@
     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)