Merge pull request #1139 from martinling/tx-flush
Support flushing the device TX buffer before ending transmission
This commit is contained in:
@ -322,6 +322,7 @@ char* u64toa(uint64_t val, t_u64toa* str)
|
||||
}
|
||||
|
||||
static volatile bool do_exit = false;
|
||||
static volatile bool interrupted = false;
|
||||
#ifdef _WIN32
|
||||
static HANDLE interrupt_handle;
|
||||
#endif
|
||||
@ -642,6 +643,7 @@ static hackrf_device* device = NULL;
|
||||
BOOL WINAPI sighandler(int signum)
|
||||
{
|
||||
if (CTRL_C_EVENT == signum) {
|
||||
interrupted = true;
|
||||
fprintf(stderr, "Caught signal %d\n", signum);
|
||||
stop_main_loop();
|
||||
return TRUE;
|
||||
@ -651,6 +653,7 @@ BOOL WINAPI sighandler(int signum)
|
||||
#else
|
||||
void sigint_callback_handler(int signum)
|
||||
{
|
||||
interrupted = true;
|
||||
fprintf(stderr, "Caught signal %d\n", signum);
|
||||
do_exit = true;
|
||||
}
|
||||
@ -1176,6 +1179,7 @@ int main(int argc, char** argv)
|
||||
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) {
|
||||
@ -1403,6 +1407,10 @@ int main(int argc, char** argv)
|
||||
interval_timer.it_value.tv_sec = 0;
|
||||
setitimer(ITIMER_REAL, &interval_timer, NULL);
|
||||
#endif
|
||||
if ((transmit || signalsource) && !interrupted) {
|
||||
// Wait for TX to finish.
|
||||
hackrf_await_tx_flush(device);
|
||||
}
|
||||
|
||||
result = hackrf_is_streaming(device);
|
||||
if (do_exit) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -695,6 +701,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) {
|
||||
@ -1734,20 +1742,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) {
|
||||
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_signal(&device->all_finished_cv);
|
||||
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)
|
||||
{
|
||||
@ -1935,6 +1967,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;
|
||||
@ -1943,6 +1978,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.
|
||||
*
|
||||
|
@ -238,6 +238,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(
|
||||
|
Reference in New Issue
Block a user