From 29787cd29147bf37421f3ebd3d41451bdbc36b4c Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 14 Sep 2022 15:10:13 +0100 Subject: [PATCH 01/11] Clarify variables used in TX callback. The power measurement depends on the number of bytes that were valid from the previous use of the transfer buffer. The number of bytes to be read to fill the next transfer, is the full size of the buffer. --- host/hackrf-tools/src/hackrf_transfer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index 41061ff0..999d1fad 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -486,9 +486,8 @@ int tx_callback(hackrf_transfer* transfer) } /* Accumulate power (magnitude squared). */ - bytes_to_read = transfer->valid_length; uint64_t sum = 0; - for (i = 0; i < bytes_to_read; i++) { + for (i = 0; i < transfer->valid_length; i++) { int8_t value = transfer->buffer[i]; sum += value * value; } @@ -497,6 +496,7 @@ int tx_callback(hackrf_transfer* transfer) byte_count += transfer->valid_length; stream_power += sum; + bytes_to_read = transfer->buffer_length; if (file == NULL) { // transceiver_mode == TRANSCEIVER_MODE_SS /* Transmit continuous wave with specific amplitude */ if (limit_num_samples) { From 16f93d9b27c920a9d57805fdfedfaa74b7133280 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 14 Sep 2022 15:15:34 +0100 Subject: [PATCH 02/11] Move duplicated code to one place. --- host/hackrf-tools/src/hackrf_transfer.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index 999d1fad..8148153f 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -497,15 +497,14 @@ int tx_callback(hackrf_transfer* transfer) stream_power += sum; bytes_to_read = transfer->buffer_length; + if (limit_num_samples) { + if (bytes_to_read >= bytes_to_xfer) { + bytes_to_read = bytes_to_xfer; + } + bytes_to_xfer -= bytes_to_read; + } if (file == NULL) { // transceiver_mode == TRANSCEIVER_MODE_SS /* Transmit continuous wave with specific amplitude */ - if (limit_num_samples) { - if (bytes_to_read >= bytes_to_xfer) { - bytes_to_read = bytes_to_xfer; - } - bytes_to_xfer -= bytes_to_read; - } - for (i = 0; i < bytes_to_read; i++) transfer->buffer[i] = -(uint8_t) amplitude; @@ -517,16 +516,6 @@ int tx_callback(hackrf_transfer* transfer) } } - if (limit_num_samples) { - if (bytes_to_read >= bytes_to_xfer) { - /* - * In this condition, we probably tx some of the previous - * buffer contents at the end. :-( - */ - bytes_to_read = bytes_to_xfer; - } - bytes_to_xfer -= bytes_to_read; - } bytes_read = fread(transfer->buffer, 1, bytes_to_read, file); if (limit_num_samples && (bytes_to_xfer == 0)) { stop_main_loop(); From 9905e960a495b780e5f3789635cea9201344fb9a Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 14 Sep 2022 12:40:41 +0100 Subject: [PATCH 03/11] Rearrange to avoid duplicating sample limit return path. --- host/hackrf-tools/src/hackrf_transfer.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index 8148153f..1699a15b 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -507,16 +507,11 @@ int tx_callback(hackrf_transfer* transfer) /* Transmit continuous wave with specific amplitude */ for (i = 0; i < bytes_to_read; i++) transfer->buffer[i] = -(uint8_t) amplitude; - - if (limit_num_samples && (bytes_to_xfer == 0)) { - stop_main_loop(); - return -1; - } else { - return 0; - } + bytes_read = bytes_to_read; + } else { + bytes_read = fread(transfer->buffer, 1, bytes_to_read, file); } - bytes_read = fread(transfer->buffer, 1, bytes_to_read, file); if (limit_num_samples && (bytes_to_xfer == 0)) { stop_main_loop(); return -1; From 22846b568263cbf5e432adaf9fdf22572148eb5f Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 14 Sep 2022 15:44:48 +0100 Subject: [PATCH 04/11] Make libhackrf honour the valid_length set by TX callback. --- host/libhackrf/src/hackrf.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index eaf3a935..0ccc57e5 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -359,6 +359,8 @@ static int prepare_transfers( .tx_ctx = device->tx_ctx, }; if (device->callback(&transfer) == 0) { + device->transfers[transfer_index]->length = + transfer.valid_length; ready_transfers++; } else { break; @@ -1791,7 +1793,7 @@ hackrf_libusb_transfer_callback(struct libusb_transfer* usb_transfer) hackrf_transfer transfer = { .device = device, .buffer = usb_transfer->buffer, - .buffer_length = usb_transfer->length, + .buffer_length = TRANSFER_BUFFER_SIZE, .valid_length = usb_transfer->actual_length, .rx_ctx = device->rx_ctx, .tx_ctx = device->tx_ctx}; @@ -1803,6 +1805,9 @@ hackrf_libusb_transfer_callback(struct libusb_transfer* usb_transfer) pthread_mutex_lock(&device->transfer_lock); if ((resubmit = device->transfers_setup)) { + if (usb_transfer->endpoint == TX_ENDPOINT_ADDRESS) { + usb_transfer->length = transfer.valid_length; + } result = libusb_submit_transfer(usb_transfer); } From 5ad08cfd96afaf05e0018f2c0246f364c5617f6f Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 14 Sep 2022 15:45:30 +0100 Subject: [PATCH 05/11] Set valid_length correctly in hackrf_transfer TX callback. --- host/hackrf-tools/src/hackrf_transfer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index 1699a15b..78b97f61 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -512,6 +512,8 @@ int tx_callback(hackrf_transfer* transfer) bytes_read = fread(transfer->buffer, 1, bytes_to_read, file); } + transfer->valid_length = bytes_read; + if (limit_num_samples && (bytes_to_xfer == 0)) { stop_main_loop(); return -1; @@ -533,6 +535,7 @@ int tx_callback(hackrf_transfer* transfer) 1, bytes_to_read - bytes_read, file); + transfer->valid_length = bytes_read; } return 0; From e38534b99db15507eaa51e478bc09f3893516da8 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 14 Sep 2022 15:18:32 +0100 Subject: [PATCH 06/11] Don't return -1 from the TX callback that provides the last data. --- host/hackrf-tools/src/hackrf_transfer.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index 78b97f61..5a23277c 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -323,6 +323,7 @@ char* u64toa(uint64_t val, t_u64toa* str) static volatile bool do_exit = false; static volatile bool interrupted = false; +static volatile bool tx_complete = false; #ifdef _WIN32 static HANDLE interrupt_handle; #endif @@ -496,6 +497,11 @@ int tx_callback(hackrf_transfer* transfer) byte_count += transfer->valid_length; stream_power += sum; + if (tx_complete) { + stop_main_loop(); + return -1; + } + bytes_to_read = transfer->buffer_length; if (limit_num_samples) { if (bytes_to_read >= bytes_to_xfer) { @@ -515,8 +521,8 @@ int tx_callback(hackrf_transfer* transfer) transfer->valid_length = bytes_read; if (limit_num_samples && (bytes_to_xfer == 0)) { - stop_main_loop(); - return -1; + tx_complete = true; + return 0; } if (bytes_read == bytes_to_read) { @@ -524,8 +530,8 @@ int tx_callback(hackrf_transfer* transfer) } if (!repeat) { - stop_main_loop(); - return -1; /* not repeat mode, end of file */ + tx_complete = true; + return 0; } while (bytes_read < bytes_to_read) { From f2d00adab81baa55ff016f987662eba5a37fa8e6 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Wed, 14 Sep 2022 15:25:48 +0100 Subject: [PATCH 07/11] Add commentary to TX callback. --- host/hackrf-tools/src/hackrf_transfer.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index 5a23277c..3ccfe892 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -481,6 +481,7 @@ int tx_callback(hackrf_transfer* transfer) size_t bytes_read; unsigned int i; + /* Check we have a valid source of samples. */ if (file == NULL && transceiver_mode != TRANSCEIVER_MODE_SS) { stop_main_loop(); return -1; @@ -497,11 +498,13 @@ int tx_callback(hackrf_transfer* transfer) byte_count += transfer->valid_length; stream_power += sum; + /* If the last data was already buffered, stop. */ if (tx_complete) { stop_main_loop(); return -1; } + /* Determine how many bytes we need to put in the buffer. */ bytes_to_read = transfer->buffer_length; if (limit_num_samples) { if (bytes_to_read >= bytes_to_xfer) { @@ -509,31 +512,37 @@ int tx_callback(hackrf_transfer* transfer) } bytes_to_xfer -= bytes_to_read; } - if (file == NULL) { // transceiver_mode == TRANSCEIVER_MODE_SS + + /* Fill the buffer. */ + if (file == NULL) { /* Transmit continuous wave with specific amplitude */ for (i = 0; i < bytes_to_read; i++) transfer->buffer[i] = -(uint8_t) amplitude; bytes_read = bytes_to_read; } else { + /* Read samples from file. */ bytes_read = fread(transfer->buffer, 1, bytes_to_read, file); } - transfer->valid_length = bytes_read; + /* If the sample limit has been reached, this is the last data. */ if (limit_num_samples && (bytes_to_xfer == 0)) { tx_complete = true; return 0; } + /* If we filled the number of bytes needed, return normally. */ if (bytes_read == bytes_to_read) { return 0; } + /* Otherwise, the file ran short. If not repeating, this is the last data. */ if (!repeat) { tx_complete = true; return 0; } + /* If we get to here, we need to repeat the file until we fill the buffer. */ while (bytes_read < bytes_to_read) { rewind(file); bytes_read += @@ -544,6 +553,7 @@ int tx_callback(hackrf_transfer* transfer) transfer->valid_length = bytes_read; } + /* Then return normally. */ return 0; } From 09c6030ec94e02e5ca4e00e434bb5d054a08f48c Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 15 Sep 2022 09:51:11 +0100 Subject: [PATCH 08/11] Start TX/RX in hackrf_transfer after all other requests. This avoids glitches and lost samples at the start of a transmission. --- host/hackrf-tools/src/hackrf_transfer.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/host/hackrf-tools/src/hackrf_transfer.c b/host/hackrf-tools/src/hackrf_transfer.c index 3ccfe892..5844e42f 100644 --- a/host/hackrf-tools/src/hackrf_transfer.c +++ b/host/hackrf-tools/src/hackrf_transfer.c @@ -1176,15 +1176,6 @@ int main(int argc, char** argv) return EXIT_FAILURE; } - if (transceiver_mode == TRANSCEIVER_MODE_RX) { - result = hackrf_set_vga_gain(device, vga_gain); - result |= hackrf_set_lna_gain(device, lna_gain); - result |= hackrf_start_rx(device, rx_callback, NULL); - } else { - result = hackrf_set_txvga_gain(device, txvga_gain); - result |= hackrf_enable_tx_flush(device, 1); - result |= hackrf_start_tx(device, tx_callback, NULL); - } if (result != HACKRF_SUCCESS) { fprintf(stderr, "hackrf_start_?x() failed: %s (%d)\n", @@ -1255,6 +1246,16 @@ int main(int argc, char** argv) } } + if (transceiver_mode == TRANSCEIVER_MODE_RX) { + result = hackrf_set_vga_gain(device, vga_gain); + result |= hackrf_set_lna_gain(device, lna_gain); + result |= hackrf_start_rx(device, rx_callback, NULL); + } else { + result = hackrf_set_txvga_gain(device, txvga_gain); + result |= hackrf_enable_tx_flush(device, 1); + result |= hackrf_start_tx(device, tx_callback, NULL); + } + if (limit_num_samples) { fprintf(stderr, "samples_to_xfer %s/%sMio\n", From 69823397b1218bc4708ebe41a4299ef9c86e8f3a Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 15 Sep 2022 14:32:15 +0100 Subject: [PATCH 09/11] Submit flush transfer as soon as end of data is reached. --- host/libhackrf/src/hackrf.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 0ccc57e5..40545cde 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -391,6 +391,15 @@ static int prepare_transfers( device->streaming = (ready_transfers == TRANSFER_COUNT); device->transfers_setup = true; + // If we're not continuing streaming, follow up with a flush if needed. + if (!device->streaming && device->flush) { + error = libusb_submit_transfer(device->flush_transfer); + if (error != 0) { + last_libusb_error = error; + return HACKRF_ERROR_LIBUSB; + } + } + return HACKRF_SUCCESS; } @@ -1744,24 +1753,13 @@ static void transfer_finished( struct hackrf_device* device, struct libusb_transfer* finished_transfer) { - int result; - // If a transfer finished for any reason, we're shutting down. device->streaming = false; // If this is the last transfer, signal that all are now finished. pthread_mutex_lock(&device->all_finished_lock); if (device->active_transfers == 1) { - if (device->flush) { - // Don't finish yet - flush the TX buffer first. - result = libusb_submit_transfer(device->flush_transfer); - // If that fails, just shut down. - if (result != LIBUSB_SUCCESS) { - device->flush = false; - device->active_transfers = 0; - pthread_cond_broadcast(&device->all_finished_cv); - } - } else { + if (!device->flush) { device->active_transfers = 0; pthread_cond_broadcast(&device->all_finished_cv); } @@ -1817,6 +1815,8 @@ hackrf_libusb_transfer_callback(struct libusb_transfer* usb_transfer) if (resubmit && result == LIBUSB_SUCCESS) return; + } else if (device->flush) { + libusb_submit_transfer(device->flush_transfer); } } From 1b166a5b0573c8c0b1fd7d74c5f2737ca2b26ec4 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Thu, 15 Sep 2022 15:22:41 +0100 Subject: [PATCH 10/11] Pad the last data in a transmission to the next 512 byte boundary. --- host/libhackrf/src/hackrf.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index 40545cde..31fcb6de 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -374,10 +374,17 @@ static int prepare_transfers( // 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; + struct libusb_transfer* transfer = device->transfers[transfer_index]; + transfer->endpoint = endpoint_address; + transfer->callback = callback; - error = libusb_submit_transfer(device->transfers[transfer_index]); + // Pad the size of a short transfer to the next 512-byte boundary. + if (endpoint_address == TX_ENDPOINT_ADDRESS) { + while (transfer->length % 512 != 0) + transfer->buffer[transfer->length++] = 0; + } + + error = libusb_submit_transfer(transfer); if (error != 0) { last_libusb_error = error; return HACKRF_ERROR_LIBUSB; @@ -1805,6 +1812,10 @@ hackrf_libusb_transfer_callback(struct libusb_transfer* usb_transfer) if ((resubmit = device->transfers_setup)) { if (usb_transfer->endpoint == TX_ENDPOINT_ADDRESS) { usb_transfer->length = transfer.valid_length; + // Pad to the next 512-byte boundary. + uint8_t* buffer = usb_transfer->buffer; + while (usb_transfer->length % 512 != 0) + buffer[usb_transfer->length++] = 0; } result = libusb_submit_transfer(usb_transfer); } From 6ab17209d7bef1c3ad1b76d516db570a0bf7ef83 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 16 Sep 2022 15:55:20 +0100 Subject: [PATCH 11/11] Disable flush when cancelling transfers. --- host/libhackrf/src/hackrf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/host/libhackrf/src/hackrf.c b/host/libhackrf/src/hackrf.c index f7d62aba..1a14ee75 100644 --- a/host/libhackrf/src/hackrf.c +++ b/host/libhackrf/src/hackrf.c @@ -237,6 +237,7 @@ static int cancel_transfers(hackrf_device* device) } device->transfers_setup = false; + device->flush = false; // Now release the lock. It's possible that some transfers were // already complete when we called libusb_cancel_transfer() on