diff --git a/firmware/hackrf_usb/usb.c b/firmware/hackrf_usb/usb.c index 8396e1bf..02fb81c3 100644 --- a/firmware/hackrf_usb/usb.c +++ b/firmware/hackrf_usb/usb.c @@ -195,6 +195,39 @@ void usb_endpoint_prime( USB0_ENDPTPRIME = USB0_ENDPTPRIME_PERB(1 << endpoint_number); } } + +// Schedule an already filled-up transfer descriptor for execution on +// the given endpoint. Note that this requires that one knows the tail +// of the endpoint's TD queue +void usb_endpoint_append_td( + const usb_endpoint_t* const endpoint, + usb_transfer_descriptor_t* const tail_td, + usb_transfer_descriptor_t* const new_td +) { + const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); + bool done; + + tail_td->next_dtd_pointer = new_td; + + do { + if( usb_endpoint_is_in(endpoint->address) ) { + if (USB0_ENDPTPRIME & USB0_ENDPTPRIME_PETB(1 << endpoint_number) ) + return; + } else { + if (USB0_ENDPTPRIME & USB0_ENDPTPRIME_PERB(1 << endpoint_number) ) + return; + } + + USB0_USBCMD_D |= USB0_USBCMD_D_ATDTW; + done = usb_endpoint_is_ready(endpoint); + } while (!(USB0_USBCMD_D & USB0_USBCMD_D_ATDTW)); + + USB0_USBCMD_D &= ~USB0_USBCMD_D_ATDTW; + if(!done) { + usb_endpoint_prime(endpoint, new_td); + } +} + /* static bool usb_endpoint_is_priming( const usb_endpoint_t* const endpoint diff --git a/firmware/hackrf_usb/usb.h b/firmware/hackrf_usb/usb.h index 4b1d50f4..94372e0c 100644 --- a/firmware/hackrf_usb/usb.h +++ b/firmware/hackrf_usb/usb.h @@ -92,4 +92,10 @@ void usb_endpoint_prime( usb_transfer_descriptor_t* const first_td ); +void usb_endpoint_append_td( + const usb_endpoint_t* const endpoint, + usb_transfer_descriptor_t* const tail_td, + usb_transfer_descriptor_t* const new_td +); + #endif//__USB_H__