[usb proto]Add complete cb as a parameter

With usb request having private regions for each layer in the stack,
the complete callback and their contexts should not be part of the public
part of the usb-request. This changeset modifies usb protocol so that
the complete_cb and its context are passed in as parameters.

Test: zircon build. Will be changing garnet also and then will do basic
sanity test.

Change-Id: I42ab688b3db2aaca56f05d67a69d94b61199c256
diff --git a/system/dev/audio/usb-audio/usb-audio-stream.cpp b/system/dev/audio/usb-audio/usb-audio-stream.cpp
index 4a5bea8..38751de 100644
--- a/system/dev/audio/usb-audio/usb-audio-stream.cpp
+++ b/system/dev/audio/usb-audio/usb-audio-stream.cpp
@@ -138,6 +138,11 @@
     return status;
 }
 
+void UsbAudioStream::RequestCompleteCallback(usb_request_t* request, void* cookie) {
+    ZX_DEBUG_ASSERT(cookie != nullptr);
+    reinterpret_cast<UsbAudioStream*>(cookie)->RequestComplete(request);
+}
+
 void UsbAudioStream::ComputePersistentUniqueId() {
     // Do the best that we can to generate a persistent ID unique to this audio
     // stream by blending information from a number of sources.  In particular,
@@ -1123,7 +1128,8 @@
 
     req->header.frame = usb_frame_num_++;
     req->header.length = todo;
-    usb_request_queue(&parent_.usb_proto(), req);
+    usb_request_queue(&parent_.usb_proto(), req,
+                      UsbAudioStream::RequestCompleteCallback, this);
 }
 
 void UsbAudioStream::CompleteRequestLocked(usb_request_t* req) {
diff --git a/system/dev/audio/usb-audio/usb-audio-stream.h b/system/dev/audio/usb-audio/usb-audio-stream.h
index e3f5a8d..f521487 100644
--- a/system/dev/audio/usb-audio/usb-audio-stream.h
+++ b/system/dev/audio/usb-audio/usb-audio-stream.h
@@ -119,6 +119,7 @@
     void QueueRequestLocked() __TA_REQUIRES(req_lock_);
     void CompleteRequestLocked(usb_request_t* req) __TA_REQUIRES(req_lock_);
 
+    static void RequestCompleteCallback(usb_request_t* request, void* cookie);
     UsbAudioDevice& parent_;
     const fbl::unique_ptr<UsbAudioStreamInterface> ifc_;
     char log_prefix_[LOG_PREFIX_STORAGE] = { 0 };
diff --git a/system/dev/audio/usb-audio/usb-midi-sink.c b/system/dev/audio/usb-audio/usb-midi-sink.c
index 88db5c5..1902c93 100644
--- a/system/dev/audio/usb-audio/usb-midi-sink.c
+++ b/system/dev/audio/usb-audio/usb-midi-sink.c
@@ -161,7 +161,7 @@
 
         usb_request_copy_to(req, buffer, 4, 0);
         req->header.length = 4;
-        usb_request_queue(&sink->usb, req);
+        usb_request_queue(&sink->usb, req, usb_midi_sink_write_complete, sink);
 
         src += message_length;
         length -= message_length;
diff --git a/system/dev/audio/usb-audio/usb-midi-source.c b/system/dev/audio/usb-audio/usb-midi-source.c
index 4c4f0f5..e3b49a0 100644
--- a/system/dev/audio/usb-audio/usb-midi-source.c
+++ b/system/dev/audio/usb-audio/usb-midi-source.c
@@ -68,7 +68,7 @@
                                                    source->parent_req_size);
         ZX_DEBUG_ASSERT(status == ZX_OK);
     } else {
-        usb_request_queue(&source->usb, req);
+        usb_request_queue(&source->usb, req, usb_midi_source_read_complete, source);
     }
     update_signals(source);
     mtx_unlock(&source->mutex);
@@ -115,11 +115,11 @@
     usb_request_t* req;
     while ((req = usb_req_list_remove_head(&source->completed_reads,
                                            source->parent_req_size)) != NULL) {
-        usb_request_queue(&source->usb, req);
+        usb_request_queue(&source->usb, req, usb_midi_source_read_complete, source);
     }
     while ((req = usb_req_list_remove_head(&source->free_read_reqs,
                                            source->parent_req_size)) != NULL) {
-        usb_request_queue(&source->usb, req);
+        usb_request_queue(&source->usb, req, usb_midi_source_read_complete, source);
     }
     mtx_unlock(&source->mutex);
 
@@ -165,7 +165,7 @@
     ZX_DEBUG_ASSERT(status == ZX_OK);
     while ((req = usb_req_list_remove_head(&source->free_read_reqs,
                                            source->parent_req_size)) != NULL) {
-        usb_request_queue(&source->usb, req);
+        usb_request_queue(&source->usb, req, usb_midi_source_read_complete, source);
     }
 
 out:
diff --git a/system/dev/block/usb-mass-storage/usb-mass-storage.c b/system/dev/block/usb-mass-storage/usb-mass-storage.c
index 432db13..a6b3ad1 100644
--- a/system/dev/block/usb-mass-storage/usb-mass-storage.c
+++ b/system/dev/block/usb-mass-storage/usb-mass-storage.c
@@ -92,7 +92,7 @@
 
     sync_completion_t completion = SYNC_COMPLETION_INIT;
     req->cookie = &completion;
-    usb_request_queue(&ums->usb, req);
+    usb_request_queue(&ums->usb, req, ums_req_complete, &completion);
     sync_completion_wait(&completion, ZX_TIME_INFINITE);
 }
 
@@ -100,7 +100,7 @@
     sync_completion_t completion = SYNC_COMPLETION_INIT;
     usb_request_t* csw_request = ums->csw_req;
     csw_request->cookie = &completion;
-    usb_request_queue(&ums->usb, csw_request);
+    usb_request_queue(&ums->usb, csw_request, ums_req_complete, &completion);
     sync_completion_wait(&completion, ZX_TIME_INFINITE);
 
     csw_status_t csw_error = ums_verify_csw(ums, csw_request, out_residue);
@@ -151,7 +151,7 @@
     usb_request_t* read_request = ums->data_req;
     read_request->header.length = transfer_length;
     read_request->cookie = NULL;
-    usb_request_queue(&ums->usb, read_request);
+    usb_request_queue(&ums->usb, read_request, ums_req_complete, NULL);
 }
 
 static zx_status_t ums_inquiry(ums_t* ums, uint8_t lun, uint8_t* out_data) {
@@ -272,7 +272,7 @@
 
     sync_completion_t completion = SYNC_COMPLETION_INIT;
     req->cookie = &completion;
-    usb_request_queue(&ums->usb, req);
+    usb_request_queue(&ums->usb, req, ums_req_complete, &completion);
     sync_completion_wait(&completion, ZX_TIME_INFINITE);
 
     status = req->response.status;
diff --git a/system/dev/bluetooth/bt-transport-usb/bt-transport-usb.c b/system/dev/bluetooth/bt-transport-usb/bt-transport-usb.c
index 47ac71b..8a51326 100644
--- a/system/dev/bluetooth/bt-transport-usb/bt-transport-usb.c
+++ b/system/dev/bluetooth/bt-transport-usb/bt-transport-usb.c
@@ -81,17 +81,20 @@
     size_t parent_req_size;
 } hci_t;
 
+static void hci_event_complete(usb_request_t* req, void* cookie);
+static void hci_acl_read_complete(usb_request_t* req, void* cookie);
+
 static void queue_acl_read_requests_locked(hci_t* hci) {
     usb_request_t* req = NULL;
     while ((req = usb_req_list_remove_head(&hci->free_acl_read_reqs, hci->parent_req_size)) != NULL) {
-        usb_request_queue(&hci->usb, req);
+        usb_request_queue(&hci->usb, req, hci_acl_read_complete, hci);
     }
 }
 
 static void queue_interrupt_requests_locked(hci_t* hci) {
     usb_request_t* req = NULL;
     while ((req = usb_req_list_remove_head(&hci->free_event_reqs, hci->parent_req_size)) != NULL) {
-        usb_request_queue(&hci->usb, req);
+        usb_request_queue(&hci->usb, req, hci_event_complete, hci);
     }
 }
 
@@ -353,7 +356,7 @@
         usb_request_t* req = REQ_INTERNAL_TO_USB_REQ(req_int, hci->parent_req_size);
         usb_request_copy_to(req, buf, length, 0);
         req->header.length = length;
-        usb_request_queue(&hci->usb, req);
+        usb_request_queue(&hci->usb, req, hci_acl_write_complete, hci);
     }
 
     return;
diff --git a/system/dev/ethernet/asix-88179/asix-88179.c b/system/dev/ethernet/asix-88179/asix-88179.c
index 088a0f1..7879ae4 100644
--- a/system/dev/ethernet/asix-88179/asix-88179.c
+++ b/system/dev/ethernet/asix-88179/asix-88179.c
@@ -338,7 +338,7 @@
 
     if (eth->online) {
         zx_nanosleep(zx_deadline_after(ZX_USEC(eth->rx_endpoint_delay)));
-        usb_request_queue(&eth->usb, request);
+        usb_request_queue(&eth->usb, request, ax88179_read_complete, eth);
     } else {
         zx_status_t status = usb_req_list_add_head(&eth->free_read_reqs, request,
                                                    eth->parent_req_size);
@@ -415,7 +415,7 @@
         zxlogf(DEBUG1, "ax88179: queuing request (%p) of length %lu, %u outstanding\n",
                  next, next->header.length, eth->usb_tx_in_flight);
         zx_nanosleep(zx_deadline_after(ZX_USEC(eth->tx_endpoint_delay)));
-        usb_request_queue(&eth->usb, next);
+        usb_request_queue(&eth->usb, next, ax88179_write_complete, eth);
     }
     ZX_DEBUG_ASSERT(eth->usb_tx_in_flight <= MAX_TX_IN_FLIGHT);
     mtx_unlock(&eth->tx_lock);
@@ -451,7 +451,7 @@
                                            node) {
                     list_delete(&req_int->node);
                     req = REQ_INTERNAL_TO_USB_REQ(req_int, eth->parent_req_size);
-                    usb_request_queue(&eth->usb, req);
+                    usb_request_queue(&eth->usb, req, ax88179_read_complete, eth);
                 }
                 zxlogf(TRACE, "ax88179 now online\n");
                 if (eth->ifc.ops) {
@@ -540,7 +540,7 @@
     req = usb_req_list_remove_head(&eth->pending_usb_tx, eth->parent_req_size);
     zxlogf(DEBUG1, "ax88179: queuing request (%p) of length %lu, %u outstanding\n",
              req, req->header.length, eth->usb_tx_in_flight);
-    usb_request_queue(&eth->usb, req);
+    usb_request_queue(&eth->usb, req, ax88179_write_complete, eth);
     eth->usb_tx_in_flight++;
     ZX_DEBUG_ASSERT(eth->usb_tx_in_flight <= MAX_TX_IN_FLIGHT);
     mtx_unlock(&eth->tx_lock);
@@ -886,7 +886,7 @@
     usb_request_t* req = eth->interrupt_req;
     while (true) {
         sync_completion_reset(&eth->completion);
-        usb_request_queue(&eth->usb, req);
+        usb_request_queue(&eth->usb, req, ax88179_interrupt_complete, eth);
         sync_completion_wait(&eth->completion, ZX_TIME_INFINITE);
         if (req->response.status != ZX_OK) {
             return req->response.status;
diff --git a/system/dev/ethernet/asix-88772b/asix-88772b.c b/system/dev/ethernet/asix-88772b/asix-88772b.c
index 8355ae6..e532d5e 100644
--- a/system/dev/ethernet/asix-88772b/asix-88772b.c
+++ b/system/dev/ethernet/asix-88772b/asix-88772b.c
@@ -77,6 +77,9 @@
     list_node_t node;
 } txn_info_t;
 
+static void ax88772b_interrupt_complete(usb_request_t* request, void* cookie);
+static void ax88772b_write_complete(usb_request_t* request, void* cookie);
+
 static zx_status_t ax88772b_set_value(ax88772b_t* eth, uint8_t request, uint16_t value) {
     return usb_control(&eth->usb, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                        request, value, 0, NULL, 0, ZX_TIME_INFINITE, NULL);
@@ -154,7 +157,7 @@
 static void queue_interrupt_requests_locked(ax88772b_t* eth) {
     usb_request_t* req;
     while ((req = usb_req_list_remove_head(&eth->free_intr_reqs, eth->parent_req_size)) != NULL) {
-        usb_request_queue(&eth->usb, req);
+        usb_request_queue(&eth->usb, req, ax88772b_interrupt_complete, eth);
     }
 }
 
@@ -220,7 +223,7 @@
     request->header.length = length + ETH_HEADER_SIZE;
 
     zx_nanosleep(zx_deadline_after(ZX_USEC(eth->tx_endpoint_delay)));
-    usb_request_queue(&eth->usb, request);
+    usb_request_queue(&eth->usb, request, ax88772b_write_complete, eth);
     return ZX_OK;
 }
 
@@ -249,7 +252,7 @@
 
     if (eth->online) {
         zx_nanosleep(zx_deadline_after(ZX_USEC(eth->rx_endpoint_delay)));
-        usb_request_queue(&eth->usb, request);
+        usb_request_queue(&eth->usb, request, ax88772b_read_complete, eth);
     } else {
         zx_status_t status = usb_req_list_add_head(&eth->free_read_reqs, request,
                                                    eth->parent_req_size);
@@ -330,7 +333,7 @@
                                            node) {
                     list_delete(&req_int->node);
                     req = REQ_INTERNAL_TO_USB_REQ(req_int, eth->parent_req_size);
-                    usb_request_queue(&eth->usb, req);
+                    usb_request_queue(&eth->usb, req, ax88772b_read_complete, eth);
                 }
             } else if (!online && was_online) {
                 if (eth->ifc.ops) {
diff --git a/system/dev/ethernet/rndis/rndishost.c b/system/dev/ethernet/rndis/rndishost.c
index 7604da5..c7b273e 100644
--- a/system/dev/ethernet/rndis/rndishost.c
+++ b/system/dev/ethernet/rndis/rndishost.c
@@ -181,7 +181,7 @@
 
     // TODO: Only usb_request_queue if the device is online.
     zx_nanosleep(zx_deadline_after(ZX_USEC(eth->rx_endpoint_delay)));
-    usb_request_queue(&eth->usb, request);
+    usb_request_queue(&eth->usb, request, rndis_read_complete, eth);
 
     mtx_unlock(&eth->mutex);
 }
@@ -309,7 +309,7 @@
         goto done;
     }
     zx_nanosleep(zx_deadline_after(ZX_USEC(eth->tx_endpoint_delay)));
-    usb_request_queue(&eth->usb, req);
+    usb_request_queue(&eth->usb, req, rndis_write_complete, eth);
 
 done:
     mtx_unlock(&eth->mutex);
@@ -456,7 +456,7 @@
     mtx_lock(&eth->mutex);
     usb_request_t* txn;
     while ((txn = usb_req_list_remove_head(&eth->free_read_reqs, eth->parent_req_size)) != NULL) {
-        usb_request_queue(&eth->usb, txn);
+        usb_request_queue(&eth->usb, txn, rndis_read_complete, eth);
     }
     mtx_unlock(&eth->mutex);
 
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 e217b58..b843be2 100644
--- a/system/dev/ethernet/usb-cdc-ecm/usb-cdc-ecm.c
+++ b/system/dev/ethernet/usb-cdc-ecm/usb-cdc-ecm.c
@@ -83,6 +83,8 @@
     list_node_t node;
 } txn_info_t;
 
+static void usb_write_complete(usb_request_t* request, void* cookie);
+
 static void ecm_unbind(void* cookie) {
     zxlogf(TRACE, "%s: unbinding\n", module_name);
     ecm_ctx_t* ctx = cookie;
@@ -208,7 +210,7 @@
         zxlogf(ERROR, "%s: failed to copy data into send txn (error %zd)\n", module_name, bytes_copied);
         return ZX_ERR_IO;
     }
-    usb_request_queue(&ctx->usb, req);
+    usb_request_queue(&ctx->usb, req, usb_write_complete, ctx);
     return ZX_OK;
 }
 
@@ -335,7 +337,7 @@
     }
 
     zx_nanosleep(zx_deadline_after(ZX_USEC(ctx->rx_endpoint_delay)));
-    usb_request_queue(&ctx->usb, request);
+    usb_request_queue(&ctx->usb, request, usb_read_complete, ctx);
 }
 
 static zx_status_t ecm_ethmac_queue_tx(void* cookie, uint32_t options, ethmac_netbuf_t* netbuf) {
@@ -431,7 +433,7 @@
 
     while (true) {
         sync_completion_reset(&ctx->completion);
-        usb_request_queue(&ctx->usb, txn);
+        usb_request_queue(&ctx->usb, txn, ecm_interrupt_complete, ctx);
         sync_completion_wait(&ctx->completion, ZX_TIME_INFINITE);
         if (txn->response.status == ZX_OK) {
             ecm_handle_interrupt(ctx, txn);
@@ -742,7 +744,7 @@
 
         rx_buf->complete_cb = usb_read_complete;
         rx_buf->cookie = ecm_ctx;
-        usb_request_queue(&ecm_ctx->usb, rx_buf);
+        usb_request_queue(&ecm_ctx->usb, rx_buf, usb_read_complete, ecm_ctx);
         rx_buf_remain -= rx_buf_sz;
     }
 
diff --git a/system/dev/input/usb-hid/usb-hid.c b/system/dev/input/usb-hid/usb-hid.c
index 93371a9..84d0c56 100644
--- a/system/dev/input/usb-hid/usb-hid.c
+++ b/system/dev/input/usb-hid/usb-hid.c
@@ -79,7 +79,7 @@
     }
 
     if (requeue) {
-        usb_request_queue(&hid->usb, req);
+        usb_request_queue(&hid->usb, req, usb_interrupt_callback, hid);
     } else {
         hid->req_queued = false;
     }
@@ -106,7 +106,7 @@
     hid->ifc = *ifc;
     if (!hid->req_queued) {
         hid->req_queued = true;
-        usb_request_queue(&hid->usb, hid->req);
+        usb_request_queue(&hid->usb, hid->req, usb_interrupt_callback, hid);
     }
     mtx_unlock(&hid->lock);
     return ZX_OK;
diff --git a/system/dev/serial/ftdi/ftdi.c b/system/dev/serial/ftdi/ftdi.c
index 4da0e13..a830748 100644
--- a/system/dev/serial/ftdi/ftdi.c
+++ b/system/dev/serial/ftdi/ftdi.c
@@ -94,7 +94,7 @@
         ZX_DEBUG_ASSERT(status == ZX_OK);
         ftdi_check_state(ftdi);
     } else {
-        usb_request_queue(&ftdi->usb, request);
+        usb_request_queue(&ftdi->usb, request, ftdi_read_complete, ftdi);
     }
     mtx_unlock(&ftdi->mutex);
 }
@@ -161,7 +161,7 @@
     *actual = usb_request_copy_to(req, buf, length, 0);
     req->header.length = length;
 
-    usb_request_queue(&ftdi->usb,req);
+    usb_request_queue(&ftdi->usb,req, ftdi_write_complete, ftdi);
     ftdi_check_state(ftdi);
 
 out:
@@ -201,7 +201,7 @@
         } else {
             list_remove_head(&ftdi->completed_reads);
             // requeue the read request
-            usb_request_queue(&ftdi->usb, req);
+            usb_request_queue(&ftdi->usb, req, ftdi_read_complete, ftdi);
             offset = 0;
         }
 
@@ -472,7 +472,7 @@
                                usb_req_internal_t, node) {
         list_delete(&req_int->node);
         req = REQ_INTERNAL_TO_USB_REQ(req_int, ftdi->parent_req_size);
-        usb_request_queue(&ftdi->usb, req);
+        usb_request_queue(&ftdi->usb, req, ftdi_read_complete, ftdi);
     }
 
     zxlogf(INFO,"ftdi bind successful\n");
diff --git a/system/dev/usb/usb-bus/usb-device.c b/system/dev/usb/usb-bus/usb-device.c
index c1c454f..3503599 100644
--- a/system/dev/usb/usb-bus/usb-device.c
+++ b/system/dev/usb/usb-bus/usb-device.c
@@ -233,7 +233,8 @@
     return status;
 }
 
-static void usb_device_request_queue(void* ctx, usb_request_t* req) {
+static void usb_device_request_queue(void* ctx, usb_request_t* req, usb_request_complete_cb cb,
+                                     void* cookie) {
     usb_device_t* dev = ctx;
 
     req->header.device_id = dev->device_id;
diff --git a/system/dev/usb/usb-composite/usb-interface.c b/system/dev/usb/usb-composite/usb-interface.c
index 377b601..8fb4fe5 100644
--- a/system/dev/usb/usb-composite/usb-interface.c
+++ b/system/dev/usb/usb-composite/usb-interface.c
@@ -129,9 +129,10 @@
                               timeout, out_length);
 }
 
-static void usb_interface_request_queue(void* ctx, usb_request_t* usb_request) {
+static void usb_interface_request_queue(void* ctx, usb_request_t* usb_request,
+                                        usb_request_complete_cb cb, void* cookie) {
     usb_interface_t* intf = ctx;
-    usb_request_queue(&intf->comp->usb, usb_request);
+    usb_request_queue(&intf->comp->usb, usb_request, cb, cookie);
 }
 
 static zx_status_t usb_interface_configure_batch_callback(void* ctx, uint8_t ep_address,
diff --git a/system/dev/usb/usb-hub/usb-hub.c b/system/dev/usb/usb-hub/usb-hub.c
index c6f631d..84a5635 100644
--- a/system/dev/usb/usb-hub/usb-hub.c
+++ b/system/dev/usb/usb-hub/usb-hub.c
@@ -363,7 +363,7 @@
     // This loop handles events from our interrupt endpoint
     while (1) {
         sync_completion_reset(&hub->completion);
-        usb_request_queue(&hub->usb, req);
+        usb_request_queue(&hub->usb, req, usb_hub_interrupt_complete, hub);
         sync_completion_wait(&hub->completion, ZX_TIME_INFINITE);
         if (req->response.status != ZX_OK || atomic_load(&hub->thread_done)) {
             break;
diff --git a/system/dev/usb/usb-test/usb-tester/usb-tester.cpp b/system/dev/usb/usb-test/usb-tester/usb-tester.cpp
index 54b073d..edd0d2d 100644
--- a/system/dev/usb/usb-test/usb-tester/usb-tester.cpp
+++ b/system/dev/usb/usb-test/usb-tester/usb-tester.cpp
@@ -90,6 +90,11 @@
     }
 }
 
+void TestRequest::RequestCompleteCallback(usb_request_t* request, void* cookie) {
+    ZX_DEBUG_ASSERT(cookie != nullptr);
+    sync_completion_signal(reinterpret_cast<sync_completion_t*>(cookie));
+}
+
 zx_status_t TestRequest::WaitComplete(usb_protocol_t* usb) {
     usb_request_t* req = Get();
     zx_status_t status = sync_completion_wait(&completion_, ZX_SEC(kReqTimeoutSecs));
@@ -200,7 +205,8 @@
             usb_req->header.frame = start_frame;
             first = false;
         }
-        usb_request_queue(&usb_, usb_req);
+        usb_request_queue(&usb_, usb_req, test_req.GetCompleteCb(),
+                          test_req.GetCompletionEvent());
     }
 }
 
@@ -270,8 +276,10 @@
     if (status != ZX_OK) {
         return status;
     }
-    usb_request_queue(&usb_, out_req->Get());
-    usb_request_queue(&usb_, in_req->Get());
+    usb_request_queue(&usb_, out_req->Get(), out_req->GetCompleteCb(),
+                      out_req->GetCompletionEvent());
+    usb_request_queue(&usb_, in_req->Get(), in_req->GetCompleteCb(),
+                      in_req->GetCompletionEvent());
 
     zx_status_t out_status = out_req->WaitComplete(&usb_);
     zx_status_t in_status = in_req->WaitComplete(&usb_);
diff --git a/system/dev/usb/usb-test/usb-tester/usb-tester.h b/system/dev/usb/usb-test/usb-tester/usb-tester.h
index 6275a68..0043ee2 100644
--- a/system/dev/usb/usb-test/usb-tester/usb-tester.h
+++ b/system/dev/usb/usb-test/usb-tester/usb-tester.h
@@ -63,10 +63,11 @@
 
     // Returns the underlying usb request.
     usb_request_t* Get() const { return usb_req_; }
-
+    sync_completion_t* GetCompletionEvent() { return &completion_; }
+    usb_request_complete_cb GetCompleteCb() { return &RequestCompleteCallback; }
 private:
     explicit TestRequest(usb_request_t* usb_req);
-
+    static void RequestCompleteCallback(usb_request_t* request, void* cookie);
     usb_request_t* usb_req_;
     sync_completion_t completion_;
 };
diff --git a/system/ulib/ddk/include/ddk/protocol/usb.h b/system/ulib/ddk/include/ddk/protocol/usb.h
index 1b948c4..7380ef3 100644
--- a/system/ulib/ddk/include/ddk/protocol/usb.h
+++ b/system/ulib/ddk/include/ddk/protocol/usb.h
@@ -121,7 +121,8 @@
                            uint16_t index, void* data, size_t length, zx_time_t timeout,
                            size_t* out_length);
     // queues a USB request
-    void (*request_queue)(void* ctx, usb_request_t* usb_request);
+    void (*request_queue)(void* ctx, usb_request_t* usb_request, usb_request_complete_cb,
+                          void* cookie);
 
     zx_status_t (*configure_batch_callback)(void* ctx, uint8_t ep_address,
                                             usb_batch_complete_cb cb, void* cookie);
@@ -187,8 +188,9 @@
                        NULL);
 }
 
-static inline void usb_request_queue(const usb_protocol_t* usb, usb_request_t* usb_request) {
-    return usb->ops->request_queue(usb->ctx, usb_request);
+static inline void usb_request_queue(const usb_protocol_t* usb, usb_request_t* usb_request,
+                                     usb_request_complete_cb cb, void* cookie) {
+    return usb->ops->request_queue(usb->ctx, usb_request, cb, cookie);
 }
 
 // Configures an endpoint to batch multiple requests to a single callback.