Merge pull request #1069 from martinling/error-handling

Overhaul handling of transfer errors and use of streaming flag.
This commit is contained in:
Michael Ossmann
2022-06-14 10:42:19 -04:00
committed by GitHub

View File

@ -181,11 +181,6 @@ static int create_transfer_thread(hackrf_device* device);
static libusb_context* g_libusb_context = NULL; static libusb_context* g_libusb_context = NULL;
int last_libusb_error = LIBUSB_SUCCESS; int last_libusb_error = LIBUSB_SUCCESS;
static void request_exit(hackrf_device* device)
{
device->do_exit = true;
}
/* /*
* Check if the transfers are setup and owned by libusb. * Check if the transfers are setup and owned by libusb.
* *
@ -218,6 +213,9 @@ static int cancel_transfers(hackrf_device* device)
uint32_t transfer_index; uint32_t transfer_index;
int i; int i;
// If we're cancelling transfers for any reason, we're shutting down.
device->streaming = false;
if(transfers_check_setup(device) == true) if(transfers_check_setup(device) == true)
{ {
// Take lock while cancelling transfers. This blocks the // Take lock while cancelling transfers. This blocks the
@ -348,6 +346,7 @@ static int prepare_transfers(
} }
} }
device->transfers_setup = true; device->transfers_setup = true;
device->streaming = true;
return HACKRF_SUCCESS; return HACKRF_SUCCESS;
} else { } else {
// This shouldn't happen. // This shouldn't happen.
@ -1704,6 +1703,9 @@ static void transfer_finished(struct hackrf_device* device, struct libusb_transf
int i; int i;
bool all_finished = true; bool all_finished = true;
// If a transfer finished for any reason, we're shutting down.
device->streaming = false;
for (i = 0; i < TRANSFER_COUNT; i++) { for (i = 0; i < TRANSFER_COUNT; i++) {
if (device->transfers[i] == finished_transfer) { if (device->transfers[i] == finished_transfer) {
device->transfer_finished[i] = true; device->transfer_finished[i] = true;
@ -1737,7 +1739,7 @@ static void LIBUSB_CALL hackrf_libusb_transfer_callback(struct libusb_transfer*
.tx_ctx = device->tx_ctx .tx_ctx = device->tx_ctx
}; };
if( device->callback(&transfer) == 0 ) if (device->streaming && device->callback(&transfer) == 0)
{ {
// Take lock to make sure that we don't restart a // Take lock to make sure that we don't restart a
// transfer whilst cancel_transfers() is in the middle // transfer whilst cancel_transfers() is in the middle
@ -1752,23 +1754,14 @@ static void LIBUSB_CALL hackrf_libusb_transfer_callback(struct libusb_transfer*
// cancelled or restarted, not both. // cancelled or restarted, not both.
pthread_mutex_unlock(&device->transfer_lock); pthread_mutex_unlock(&device->transfer_lock);
if (!resubmit || result < 0) { if (resubmit && result == LIBUSB_SUCCESS)
transfer_finished(device, usb_transfer); return;
} }
} else {
transfer_finished(device, usb_transfer);
device->streaming = false;
} }
} else if(usb_transfer->status == LIBUSB_TRANSFER_CANCELLED) {
// Unless we resubmitted this transfer and returned above,
// it's now finished.
transfer_finished(device, usb_transfer); transfer_finished(device, usb_transfer);
} else {
/* Other cases LIBUSB_TRANSFER_NO_DEVICE
LIBUSB_TRANSFER_ERROR, LIBUSB_TRANSFER_TIMED_OUT
LIBUSB_TRANSFER_STALL, LIBUSB_TRANSFER_OVERFLOW ....
*/
request_exit(device); /* Fatal error stop transfer */
device->streaming = false;
}
} }
static int kill_transfer_thread(hackrf_device* device) static int kill_transfer_thread(hackrf_device* device)
@ -1783,10 +1776,10 @@ static int kill_transfer_thread(hackrf_device* device)
* thread has handled all completion callbacks. * thread has handled all completion callbacks.
*/ */
cancel_transfers(device); cancel_transfers(device);
/*
* Now call request_exit() to halt the main loop. // Set flag to tell the thread to exit.
*/ device->do_exit = true;
request_exit(device);
/* /*
* Interrupt the event handling thread instead of * Interrupt the event handling thread instead of
* waiting for timeout. * waiting for timeout.
@ -1816,25 +1809,16 @@ static int prepare_setup_transfers(hackrf_device* device,
const uint8_t endpoint_address, const uint8_t endpoint_address,
hackrf_sample_block_cb_fn callback) hackrf_sample_block_cb_fn callback)
{ {
int result;
if( device->transfers_setup == true ) if( device->transfers_setup == true )
{ {
return HACKRF_ERROR_BUSY; return HACKRF_ERROR_BUSY;
} }
device->callback = callback; device->callback = callback;
result = prepare_transfers( return prepare_transfers(
device, endpoint_address, device, endpoint_address,
hackrf_libusb_transfer_callback hackrf_libusb_transfer_callback
); );
if( result != HACKRF_SUCCESS )
{
return result;
}
return HACKRF_SUCCESS;
} }
static int create_transfer_thread(hackrf_device* device) static int create_transfer_thread(hackrf_device* device)
@ -1897,9 +1881,6 @@ int ADDCALL hackrf_start_rx(hackrf_device* device, hackrf_sample_block_cb_fn cal
{ {
result = prepare_setup_transfers(device, endpoint_address, callback); result = prepare_setup_transfers(device, endpoint_address, callback);
} }
if (result == HACKRF_SUCCESS) {
device->streaming = true;
}
return result; return result;
} }
@ -1928,7 +1909,6 @@ int ADDCALL hackrf_stop_rx(hackrf_device* device)
{ {
int result; int result;
device->streaming = false;
result = cancel_transfers(device); result = cancel_transfers(device);
if (result != HACKRF_SUCCESS) if (result != HACKRF_SUCCESS)
{ {
@ -1948,9 +1928,6 @@ int ADDCALL hackrf_start_tx(hackrf_device* device, hackrf_sample_block_cb_fn cal
device->tx_ctx = tx_ctx; device->tx_ctx = tx_ctx;
result = prepare_setup_transfers(device, endpoint_address, callback); result = prepare_setup_transfers(device, endpoint_address, callback);
} }
if (result == HACKRF_SUCCESS) {
device->streaming = true;
}
return result; return result;
} }
@ -1977,7 +1954,6 @@ static int hackrf_stop_tx_cmd(hackrf_device* device)
int ADDCALL hackrf_stop_tx(hackrf_device* device) int ADDCALL hackrf_stop_tx(hackrf_device* device)
{ {
int result; int result;
device->streaming = false;
result = cancel_transfers(device); result = cancel_transfers(device);
if (result != HACKRF_SUCCESS) if (result != HACKRF_SUCCESS)
{ {
@ -2683,9 +2659,6 @@ int ADDCALL hackrf_start_rx_sweep(hackrf_device* device, hackrf_sample_block_cb_
device->rx_ctx = rx_ctx; device->rx_ctx = rx_ctx;
result = prepare_setup_transfers(device, endpoint_address, callback); result = prepare_setup_transfers(device, endpoint_address, callback);
} }
if (result == HACKRF_SUCCESS) {
device->streaming = true;
}
return result; return result;
} }