From 9d2e163a2dd1b59fa425a464a70f0c5b6df0f153 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 23 Aug 2022 13:19:03 +0100 Subject: [PATCH] Call TX callback to fill transfers before initial submission. --- host/libhackrf/src/hackrf.c | 46 +++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 2c77bdeb..ab49a920 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -322,13 +322,50 @@ static int prepare_transfers( { int error; uint32_t transfer_index; + uint32_t ready_transfers = 0; if (device->transfers == NULL) { // This shouldn't happen. return HACKRF_ERROR_OTHER; } - for (transfer_index = 0; transfer_index < TRANSFER_COUNT; transfer_index++) { + // If setting up for TX, call the TX callback to fill each + // transfer buffer. + + // All transfers must be filled before any are submitted. + // Otherwise a transfer might complete whilst the others are + // still being filled, causing the transfer thread to make a + // concurrent call to the TX callback. + + // We also need to handle the case where the callback returns + // nonzero to indicate completion, so keep count of how many + // transfers were made ready to submit at this stage. + + if (endpoint_address == TX_ENDPOINT_ADDRESS) { + for (transfer_index = 0; transfer_index < TRANSFER_COUNT; + transfer_index++) { + hackrf_transfer transfer = { + .device = device, + .buffer = device->transfers[transfer_index]->buffer, + .buffer_length = TRANSFER_BUFFER_SIZE, + .valid_length = TRANSFER_BUFFER_SIZE, + .rx_ctx = device->rx_ctx, + .tx_ctx = device->tx_ctx, + }; + if (device->callback(&transfer) == 0) { + ready_transfers++; + } else { + break; + } + } + + } else { + // For RX, all transfers are already ready for use. + ready_transfers = TRANSFER_COUNT; + } + + // Now everything is ready, go ahead and submit the ready transfers. + for (transfer_index = 0; transfer_index < ready_transfers; transfer_index++) { device->transfers[transfer_index]->endpoint = endpoint_address; device->transfers[transfer_index]->callback = callback; @@ -339,8 +376,13 @@ static int prepare_transfers( } device->active_transfers++; } + + // We should only continue streaming if all transfers were made ready + // and submitted above. Otherwise, set streaming to false so that the + // libusb completion callback won't submit further transfers. + device->streaming = (ready_transfers == TRANSFER_COUNT); device->transfers_setup = true; - device->streaming = true; + return HACKRF_SUCCESS; }