Add API to support flushing the device buffer when TX finishes.

This commit is contained in:
Martin Ling
2022-08-24 23:20:13 +01:00
parent 5881b3b6a1
commit d556f0abab
2 changed files with 83 additions and 2 deletions

View File

@ -123,6 +123,7 @@ typedef enum {
#define TRANSFER_COUNT 4
#define TRANSFER_BUFFER_SIZE 262144
#define DEVICE_BUFFER_SIZE 32768
#define USB_MAX_SERIAL_LENGTH 32
struct hackrf_device {
@ -142,6 +143,8 @@ struct hackrf_device {
volatile int active_transfers; /* number of active transfers */
pthread_cond_t all_finished_cv; /* signalled when all transfers have finished */
pthread_mutex_t all_finished_lock; /* used to protect all_finished */
bool flush;
struct libusb_transfer* flush_transfer;
};
typedef struct {
@ -272,6 +275,9 @@ static int free_transfers(hackrf_device* device)
free(device->transfers);
device->transfers = NULL;
}
libusb_free_transfer(device->flush_transfer);
return HACKRF_SUCCESS;
}
@ -653,6 +659,8 @@ static int hackrf_open_setup(libusb_device_handle* usb_device, hackrf_device** d
lib_device->streaming = false;
lib_device->do_exit = false;
lib_device->active_transfers = 0;
lib_device->flush = false;
lib_device->flush_transfer = NULL;
result = pthread_mutex_init(&lib_device->transfer_lock, NULL);
if (result != 0) {
@ -1692,20 +1700,44 @@ 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) {
device->active_transfers = 0;
pthread_cond_signal(&device->all_finished_cv);
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 {
device->active_transfers = 0;
pthread_cond_broadcast(&device->all_finished_cv);
}
} else {
device->active_transfers--;
}
pthread_mutex_unlock(&device->all_finished_lock);
}
static void LIBUSB_CALL hackrf_libusb_flush_callback(struct libusb_transfer* usb_transfer)
{
// TX buffer is now flushed, so proceed with signalling completion.
hackrf_device* device = (hackrf_device*) usb_transfer->user_data;
pthread_mutex_lock(&device->all_finished_lock);
device->flush = false;
device->active_transfers = 0;
pthread_cond_broadcast(&device->all_finished_cv);
pthread_mutex_unlock(&device->all_finished_lock);
}
static void LIBUSB_CALL
hackrf_libusb_transfer_callback(struct libusb_transfer* usb_transfer)
{
@ -1893,6 +1925,9 @@ int ADDCALL hackrf_start_tx(
{
int result;
const uint8_t endpoint_address = TX_ENDPOINT_ADDRESS;
if (device->flush_transfer != NULL) {
device->flush = true;
}
result = hackrf_set_transceiver_mode(device, HACKRF_TRANSCEIVER_MODE_TRANSMIT);
if (result == HACKRF_SUCCESS) {
device->tx_ctx = tx_ctx;
@ -1901,6 +1936,49 @@ int ADDCALL hackrf_start_tx(
return result;
}
int ADDCALL hackrf_enable_tx_flush(hackrf_device* device, int enable)
{
if (enable) {
if (device->flush_transfer) {
return HACKRF_SUCCESS;
}
if ((device->flush_transfer = libusb_alloc_transfer(0)) == NULL) {
return HACKRF_ERROR_LIBUSB;
}
libusb_fill_bulk_transfer(
device->flush_transfer,
device->usb_device,
TX_ENDPOINT_ADDRESS,
calloc(1, DEVICE_BUFFER_SIZE),
DEVICE_BUFFER_SIZE,
hackrf_libusb_flush_callback,
device,
0);
device->flush_transfer->flags = LIBUSB_TRANSFER_FREE_BUFFER;
} else {
libusb_free_transfer(device->flush_transfer);
device->flush_transfer = NULL;
}
return HACKRF_SUCCESS;
}
int ADDCALL hackrf_await_tx_flush(hackrf_device* device)
{
// Wait for the transfer thread to signal that all transfers
// have finished.
pthread_mutex_lock(&device->all_finished_lock);
while (device->active_transfers > 0) {
pthread_cond_wait(&device->all_finished_cv, &device->all_finished_lock);
}
pthread_mutex_unlock(&device->all_finished_lock);
return HACKRF_SUCCESS;
}
/*
* Stop any pending transmit.
*

View File

@ -237,6 +237,9 @@ extern ADDAPI int ADDCALL hackrf_start_tx(
hackrf_sample_block_cb_fn callback,
void* tx_ctx);
extern ADDAPI int ADDCALL hackrf_enable_tx_flush(hackrf_device* device, int enable);
extern ADDAPI int ADDCALL hackrf_await_tx_flush(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_stop_tx(hackrf_device* device);
extern ADDAPI int ADDCALL hackrf_get_m0_state(