usb composite protocol

Change-Id: If33a1de86e8ff0dfdd0d4e802548f97a5d99ae5d
diff --git a/system/dev/audio/usb-audio/usb-audio-device.cpp b/system/dev/audio/usb-audio/usb-audio-device.cpp
index 1f3c8d6..dcb0745 100644
--- a/system/dev/audio/usb-audio/usb-audio-device.cpp
+++ b/system/dev/audio/usb-audio/usb-audio-device.cpp
@@ -62,6 +62,13 @@
         return status;
     }
 
+    usb_composite_protocol_t usb_composite_proto;
+    status = device_get_protocol(parent(), ZX_PROTOCOL_USB_COMPOSITE, &usb_composite_proto);
+    if (status != ZX_OK) {
+        LOG(ERROR, "Failed to get USB protocol thunks (status %d)\n", status);
+        return status;
+    }
+
     // Fetch our top level device descriptor, so we know stuff like the values
     // of our VID/PID.
     usb_get_device_descriptor(&usb_proto_, &usb_dev_desc_);
@@ -86,7 +93,7 @@
     // class of of "audio"; this is where we will find our Audio and MIDI
     // streaming interfaces.
     status = usb_claim_additional_interfaces(
-            &usb_proto_,
+            &usb_composite_proto,
             [](usb_interface_descriptor_t* intf, void* arg) -> bool {
                 return (intf->bInterfaceClass == USB_CLASS_AUDIO &&
                         intf->bInterfaceSubClass != USB_SUBCLASS_AUDIO_CONTROL);
diff --git a/system/dev/ethernet/usb-cdc-ecm/usb-cdc-ecm.c b/system/dev/ethernet/usb-cdc-ecm/usb-cdc-ecm.c
index d224113..4138d32 100644
--- a/system/dev/ethernet/usb-cdc-ecm/usb-cdc-ecm.c
+++ b/system/dev/ethernet/usb-cdc-ecm/usb-cdc-ecm.c
@@ -8,6 +8,7 @@
 #include <ddk/driver.h>
 #include <ddk/protocol/ethernet.h>
 #include <ddk/protocol/usb.h>
+#include <ddk/protocol/usb-composite.h>
 #include <ddk/usb/usb.h>
 #include <zircon/hw/usb-cdc.h>
 #include <lib/sync/completion.h>
@@ -516,6 +517,11 @@
     if (result != ZX_OK) {
         return result;
     }
+    usb_composite_protocol_t usb_composite;
+    result = device_get_protocol(device, ZX_PROTOCOL_USB_COMPOSITE, &usb_composite);
+    if (result != ZX_OK) {
+        return result;
+    }
 
     // Allocate context
     ecm_ctx_t* ecm_ctx = calloc(1, sizeof(ecm_ctx_t));
@@ -524,7 +530,7 @@
         return ZX_ERR_NO_MEMORY;
     }
 
-    result = usb_claim_additional_interfaces(&usb, want_interface, NULL);
+    result = usb_claim_additional_interfaces(&usb_composite, want_interface, NULL);
     if (result != ZX_OK) {
         goto fail;
     }
diff --git a/system/dev/lib/usb/include/ddk/usb/usb.h b/system/dev/lib/usb/include/ddk/usb/usb.h
index 11943cb..e2fb956 100644
--- a/system/dev/lib/usb/include/ddk/usb/usb.h
+++ b/system/dev/lib/usb/include/ddk/usb/usb.h
@@ -5,6 +5,7 @@
 #pragma once
 
 #include <ddk/protocol/usb.h>
+#include <ddk/protocol/usb-composite.h>
 #include <zircon/compiler.h>
 #include <zircon/hw/usb.h>
 
@@ -12,7 +13,7 @@
 
 // helper function for claiming additional interfaces that satisfy the want_interface predicate,
 // want_interface will be passed the supplied arg
-zx_status_t usb_claim_additional_interfaces(usb_protocol_t *usb,
+zx_status_t usb_claim_additional_interfaces(usb_composite_protocol_t* comp,
                                             bool (*want_interface)(usb_interface_descriptor_t*, void*),
                                             void* arg);
 
diff --git a/system/dev/lib/usb/usb.c b/system/dev/lib/usb/usb.c
index 2a5645a..702d091 100644
--- a/system/dev/lib/usb/usb.c
+++ b/system/dev/lib/usb/usb.c
@@ -3,19 +3,20 @@
 // found in the LICENSE file.
 
 #include <ddk/usb/usb.h>
+#include <ddk/protocol/usb-composite.h>
 #include <zircon/compiler.h>
 #include <stdlib.h>
 #include <string.h>
 
 // initializes a usb_desc_iter_t for iterating on descriptors past the
 // interface's existing descriptors.
-static zx_status_t usb_desc_iter_additional_init(usb_protocol_t* usb,
+static zx_status_t usb_desc_iter_additional_init(usb_composite_protocol_t* comp,
                                                  usb_desc_iter_t* iter) {
     memset(iter, 0, sizeof(*iter));
 
     void* descriptors;
     size_t length;
-    zx_status_t status = usb_get_additional_descriptor_list(usb, &descriptors, &length);
+    zx_status_t status = usb_composite_get_additional_descriptor_list(comp, &descriptors, &length);
     if (status != ZX_OK) {
         return status;
     }
@@ -28,11 +29,11 @@
 
 // helper function for claiming additional interfaces that satisfy the want_interface predicate,
 // want_interface will be passed the supplied arg
-__EXPORT zx_status_t usb_claim_additional_interfaces(usb_protocol_t* usb,
+__EXPORT zx_status_t usb_claim_additional_interfaces(usb_composite_protocol_t* comp,
                                                      bool (*want_interface)(usb_interface_descriptor_t*, void*),
                                                      void* arg) {
     usb_desc_iter_t iter;
-    zx_status_t status = usb_desc_iter_additional_init(usb, &iter);
+    zx_status_t status = usb_desc_iter_additional_init(comp, &iter);
     if (status != ZX_OK) {
         return status;
     }
@@ -46,7 +47,7 @@
         void* intf_end = next ? next : (void*)iter.desc_end;
         size_t length = intf_end - (void*)intf;
 
-        status = usb_claim_interface(usb, intf, length);
+        status = usb_composite_claim_interface(comp, intf, length);
         if (status != ZX_OK) {
             break;
         }
diff --git a/system/dev/usb/usb-bus/usb-device.c b/system/dev/usb/usb-bus/usb-device.c
index 33f449a..ad7d02d 100644
--- a/system/dev/usb/usb-bus/usb-device.c
+++ b/system/dev/usb/usb-bus/usb-device.c
@@ -543,23 +543,12 @@
     return ZX_OK;
 }
 
-static zx_status_t usb_device_get_additional_descriptor_list(void* ctx, void** out_descriptors,
-                                                                size_t* out_length) {
-    return ZX_ERR_NOT_SUPPORTED;
-}
-
 zx_status_t usb_device_get_string_descriptor(void* ctx, uint8_t desc_id, uint16_t* inout_lang_id,
                                              uint8_t* buf, size_t* inout_buflen) {
     usb_device_t* dev = ctx;
     return usb_util_get_string_descriptor(dev, desc_id, inout_lang_id, buf, inout_buflen);
 }
 
-static zx_status_t usb_device_claim_device_interface(void* ctx,
-                                                     usb_interface_descriptor_t* claim_intf,
-                                                     size_t claim_length) {
-    return ZX_ERR_NOT_SUPPORTED;
-}
-
 static zx_status_t usb_device_cancel_all(void* ctx, uint8_t ep_address) {
     usb_device_t* dev = ctx;
     return usb_hci_cancel_all(&dev->hci, dev->device_id, ep_address);
@@ -597,9 +586,7 @@
     .get_device_descriptor = usb_device_get_device_descriptor,
     .get_configuration_descriptor = usb_device_get_configuration_descriptor,
     .get_descriptor_list = usb_device_get_descriptor_list,
-    .get_additional_descriptor_list = usb_device_get_additional_descriptor_list,
     .get_string_descriptor = usb_device_get_string_descriptor,
-    .claim_interface = usb_device_claim_device_interface,
     .cancel_all = usb_device_cancel_all,
     .get_current_frame = usb_device_get_current_frame,
 };
diff --git a/system/dev/usb/usb-composite/usb-composite.c b/system/dev/usb/usb-composite/usb-composite.c
index 4c9dcfb..019e85e 100644
--- a/system/dev/usb/usb-composite/usb-composite.c
+++ b/system/dev/usb/usb-composite/usb-composite.c
@@ -303,7 +303,7 @@
     mtx_unlock(&comp->interface_mutex);
 }
 
-zx_status_t usb_composite_claim_interface(usb_composite_t* comp, uint8_t interface_id) {
+zx_status_t usb_composite_do_claim_interface(usb_composite_t* comp, uint8_t interface_id) {
     mtx_lock(&comp->interface_mutex);
 
     interface_status_t status = comp->interface_statuses[interface_id];
diff --git a/system/dev/usb/usb-composite/usb-composite.h b/system/dev/usb/usb-composite/usb-composite.h
index f3e36b7..f8f3124 100644
--- a/system/dev/usb/usb-composite/usb-composite.h
+++ b/system/dev/usb/usb-composite/usb-composite.h
@@ -42,7 +42,7 @@
 
 // Marks the interface as claimed, removing the device if it exists.
 // Returns an error if the interface was already claimed by another interface.
-zx_status_t usb_composite_claim_interface(usb_composite_t* comp, uint8_t interface_id);
+zx_status_t usb_composite_do_claim_interface(usb_composite_t* comp, uint8_t interface_id);
 
 zx_status_t usb_composite_set_interface(usb_composite_t* comp, uint8_t interface_id,
                                         uint8_t alt_setting);
diff --git a/system/dev/usb/usb-composite/usb-interface.c b/system/dev/usb/usb-composite/usb-interface.c
index 2d27cac..1bce528 100644
--- a/system/dev/usb/usb-composite/usb-interface.c
+++ b/system/dev/usb/usb-composite/usb-interface.c
@@ -5,6 +5,7 @@
 #include <ddk/binding.h>
 #include <ddk/debug.h>
 #include <ddk/protocol/usb.h>
+#include <ddk/protocol/usb-composite.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -310,7 +311,7 @@
                                                         size_t claim_length) {
     usb_interface_t* intf = ctx;
 
-    zx_status_t status = usb_composite_claim_interface(intf->comp, claim_intf->bInterfaceNumber);
+    zx_status_t status = usb_composite_do_claim_interface(intf->comp, claim_intf->bInterfaceNumber);
     if (status != ZX_OK) {
         return status;
     }
@@ -367,13 +368,16 @@
     .get_device_descriptor = usb_interface_get_device_descriptor,
     .get_configuration_descriptor = usb_interface_get_configuration_descriptor,
     .get_descriptor_list = usb_interface_get_descriptor_list,
-    .get_additional_descriptor_list = usb_interface_get_additional_descriptor_list,
     .get_string_descriptor = usb_interface_get_string_descriptor,
-    .claim_interface = usb_interface_claim_device_interface,
     .cancel_all = usb_interface_cancel_all,
     .get_current_frame = usb_interface_get_current_frame,
 };
 
+usb_composite_protocol_ops_t composite_device_protocol = {
+    .get_additional_descriptor_list = usb_interface_get_additional_descriptor_list,
+    .claim_interface = usb_interface_claim_device_interface,
+};
+
 bool usb_interface_contains_interface(usb_interface_t* intf, uint8_t interface_id) {
     usb_descriptor_header_t* header = intf->descriptor;
     usb_descriptor_header_t* end = (usb_descriptor_header_t*)((void*)header +
diff --git a/system/dev/usb/usb-test/usb-tester/usb-tester.c b/system/dev/usb/usb-test/usb-tester/usb-tester.c
index 2b8f781..6371167 100644
--- a/system/dev/usb/usb-test/usb-tester/usb-tester.c
+++ b/system/dev/usb/usb-test/usb-tester/usb-tester.c
@@ -5,6 +5,7 @@
 #include <ddk/binding.h>
 #include <ddk/debug.h>
 #include <ddk/device.h>
+#include <ddk/protocol/usb-composite.h>
 #include <ddk/usb/usb.h>
 #include <lib/sync/completion.h>
 #include <zircon/device/usb-device.h>
@@ -470,7 +471,13 @@
     if (status != ZX_OK) {
         goto error_return;
     }
-    status = usb_claim_additional_interfaces(&usb_tester->usb, want_interface, NULL);
+
+    usb_composite_protocol_t usb_composite;
+    status = device_get_protocol(device, ZX_PROTOCOL_USB, &usb_composite);
+    if (status != ZX_OK) {
+        goto error_return;
+    }
+    status = usb_claim_additional_interfaces(&usb_composite, want_interface, NULL);
     if (status != ZX_OK) {
         goto error_return;
     }
diff --git a/system/ulib/ddk/include/ddk/protocol/usb-composite.h b/system/ulib/ddk/include/ddk/protocol/usb-composite.h
new file mode 100644
index 0000000..871a1aa
--- /dev/null
+++ b/system/ulib/ddk/include/ddk/protocol/usb-composite.h
@@ -0,0 +1,43 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <sys/types.h>
+#include <zircon/compiler.h>
+#include <zircon/types.h>
+#include <zircon/hw/usb.h>
+
+__BEGIN_CDECLS;
+
+typedef struct {
+    zx_status_t (*get_additional_descriptor_list)(void* ctx, void** out_descriptors,
+                                                  size_t* out_length);
+    zx_status_t (*claim_interface)(void* ctx, usb_interface_descriptor_t* intf, size_t length);
+} usb_composite_protocol_ops_t;
+
+typedef struct {
+    usb_composite_protocol_ops_t* ops;
+    void* ctx;
+} usb_composite_protocol_t;
+
+// returns the USB descriptors following the interface's existing descriptors
+// the returned value is de-allocated with free()
+static inline zx_status_t usb_composite_get_additional_descriptor_list(
+                                                        const usb_composite_protocol_t* comp,
+                                                        void** out_descriptors,
+                                                        size_t* out_length) {
+    return comp->ops->get_additional_descriptor_list(comp->ctx, out_descriptors, out_length);
+}
+
+// marks the interface as claimed and appends the interface descriptor to the
+// interface's existing descriptors.
+static inline zx_status_t usb_composite_claim_interface(const usb_composite_protocol_t* comp,
+                                                         usb_interface_descriptor_t* intf,
+                                                         size_t length) {
+    return comp->ops->claim_interface(comp->ctx, intf, length);
+}
+
+
+__END_CDECLS;
diff --git a/system/ulib/ddk/include/ddk/protocol/usb.h b/system/ulib/ddk/include/ddk/protocol/usb.h
index 7728daa..0c882eb 100644
--- a/system/ulib/ddk/include/ddk/protocol/usb.h
+++ b/system/ulib/ddk/include/ddk/protocol/usb.h
@@ -76,7 +76,7 @@
     // callback.
     usb_request_complete_cb complete_cb;
 
-    // Set by the requestor for opting out of the complete_cb()
+    // Set by the requestor for opting out of the comlete_cb()
     // callback for successfully completed requests. The callback
     // will still be invoked if an error is encountered.
     // This is useful for isochronous requests, where the requestor
@@ -114,7 +114,7 @@
 } usb_request_t;
 
 
-typedef struct usb_protocol_ops {
+typedef struct {
     zx_status_t (*req_alloc)(void* ctx, usb_request_t** out, uint64_t data_size,
                              uint8_t ep_address);
     zx_status_t (*req_alloc_vmo)(void* ctx, usb_request_t** out, zx_handle_t vmo_handle,
@@ -156,12 +156,8 @@
                                                 usb_configuration_descriptor_t** out,
                                                 size_t* out_length);
     zx_status_t (*get_descriptor_list)(void* ctx, void** out_descriptors, size_t* out_length);
-    zx_status_t (*get_additional_descriptor_list)(void* ctx, void** out_descriptors,
-                                                  size_t* out_length);
-    zx_status_t (*get_string_descriptor)(void* ctx,
-                                         uint8_t desc_id, uint16_t* inout_lang_id,
+    zx_status_t (*get_string_descriptor)(void* ctx, uint8_t desc_id, uint16_t* inout_lang_id,
                                          uint8_t* buf, size_t* inout_buflen);
-    zx_status_t (*claim_interface)(void* ctx, usb_interface_descriptor_t* intf, size_t length);
     zx_status_t (*cancel_all)(void* ctx, uint8_t ep_address);
     uint64_t (*get_current_frame)(void* ctx);
 } usb_protocol_ops_t;
@@ -340,14 +336,6 @@
     return usb->ops->get_descriptor_list(usb->ctx, out_descriptors, out_length);
 }
 
-// returns the USB descriptors following the interface's existing descriptors
-// the returned value is de-allocated with free()
-static inline zx_status_t usb_get_additional_descriptor_list(const usb_protocol_t* usb,
-                                                             void** out_descriptors,
-                                                             size_t* out_length) {
-    return usb->ops->get_additional_descriptor_list(usb->ctx, out_descriptors, out_length);
-}
-
 // Fetch the descriptor using the provided descriptor ID and language ID.  If
 // the language ID requested is not available, the first entry of the language
 // ID table will be used instead and be provided in the updated version of the
@@ -366,13 +354,6 @@
     return usb->ops->get_string_descriptor(usb->ctx, desc_id, inout_lang_id, buf, inout_buflen);
 }
 
-// marks the interface as claimed and appends the interface descriptor to the
-// interface's existing descriptors.
-static inline zx_status_t usb_claim_interface(const usb_protocol_t* usb,
-                                              usb_interface_descriptor_t* intf, size_t length) {
-    return usb->ops->claim_interface(usb->ctx, intf, length);
-}
-
 static inline zx_status_t usb_cancel_all(const usb_protocol_t* usb, uint8_t ep_address) {
     return usb->ops->cancel_all(usb->ctx, ep_address);
 }
diff --git a/system/ulib/ddk/include/ddk/protodefs.h b/system/ulib/ddk/include/ddk/protodefs.h
index 18d2c3e..f176621 100644
--- a/system/ulib/ddk/include/ddk/protodefs.h
+++ b/system/ulib/ddk/include/ddk/protodefs.h
@@ -34,6 +34,7 @@
 DDK_PROTOCOL_DEF(TPM,            'pTPM', "tpm", 0)
 DDK_PROTOCOL_DEF(USB,            'pUSB', "usb", PF_NOPUB)
 DDK_PROTOCOL_DEF(USB_BUS,        'pUBS', "usb-bus", PF_NOPUB)
+DDK_PROTOCOL_DEF(USB_COMPOSITE,  'pUBC', "usb-composite", PF_NOPUB)
 DDK_PROTOCOL_DEF(USB_DCI,        'pUDC', "usb-dci", 0)  // Device Controller Interface
 DDK_PROTOCOL_DEF(USB_DEVICE,     'pUSD', "usb-device", 0)
 DDK_PROTOCOL_DEF(USB_PERIPHERAL, 'pUSP', "usb-peripheral", 0)