[usb proto] Make complete_cb as a parameter to usb_request_queue

Already reviewed at
https://fuchsia-review.googlesource.com/c/zircon/+/232612
However, when including that change in integration review test with
garnet change, (patches.json), the dry run fails,
unable to apply the zircon change.Infra team is also unsure about the
reason. I synched to JIRI_HEAD and removed all the associated
dependencies, and generated this change with exact same source and
the dry run now succeeds.

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: Test with garnet change: https://fuchsia-review.googlesource.com/c/garnet/+/232701
pixelbook: fx serve. fx shell. lsusb. iochk on ums device. audio -d 1 tone.
Astro: netboot. lsusb.

Change-Id: I691ca2ccd8eeca35711d501ac7b23be4d91161dd
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 1dbc607..be0b2b5 100644
--- a/system/ulib/ddk/include/ddk/protocol/usb.h
+++ b/system/ulib/ddk/include/ddk/protocol/usb.h
@@ -119,7 +119,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);
@@ -185,8 +186,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.