summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--software/libosmosdr/src/libosmosdr.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/software/libosmosdr/src/libosmosdr.c b/software/libosmosdr/src/libosmosdr.c
index 6fde675..139a96b 100644
--- a/software/libosmosdr/src/libosmosdr.c
+++ b/software/libosmosdr/src/libosmosdr.c
@@ -765,6 +765,10 @@ int osmosdr_close(osmosdr_dev_t *dev)
if (!dev)
return -1;
+ /* block until all async operations have been completed (if any) */
+ while (OSMOSDR_INACTIVE != dev->async_status)
+ usleep(10);
+
libusb_release_interface(dev->devh, 0);
libusb_close(dev->devh);
@@ -802,9 +806,10 @@ static void LIBUSB_CALL _libusb_callback(struct libusb_transfer *xfer)
dev->cb(xfer->buffer, xfer->actual_length, dev->cb_ctx);
libusb_submit_transfer(xfer); /* resubmit transfer */
+ } else if (LIBUSB_TRANSFER_CANCELLED == xfer->status) {
+ /* nothing to do */
} else {
/*fprintf(stderr, "transfer status: %d\n", xfer->status);*/
- osmosdr_cancel_async(dev); /* abort async loop */
}
}
@@ -869,12 +874,18 @@ int osmosdr_read_async(osmosdr_dev_t *dev, osmosdr_read_async_cb_t cb, void *ctx
uint32_t buf_num, uint32_t buf_len)
{
unsigned int i;
- int r;
+ int r = 0;
struct timeval tv = { 1, 0 };
+ enum osmosdr_async_status next_status = OSMOSDR_INACTIVE;
if (!dev)
return -1;
+ if (OSMOSDR_INACTIVE != dev->async_status)
+ return -2;
+
+ dev->async_status = OSMOSDR_RUNNING;
+
dev->cb = cb;
dev->cb_ctx = ctx;
@@ -903,8 +914,6 @@ int osmosdr_read_async(osmosdr_dev_t *dev, osmosdr_read_async_cb_t cb, void *ctx
libusb_submit_transfer(dev->xfer[i]);
}
- dev->async_status = OSMOSDR_RUNNING;
-
while (OSMOSDR_INACTIVE != dev->async_status) {
r = libusb_handle_events_timeout(dev->ctx, &tv);
if (r < 0) {
@@ -915,7 +924,7 @@ int osmosdr_read_async(osmosdr_dev_t *dev, osmosdr_read_async_cb_t cb, void *ctx
}
if (OSMOSDR_CANCELING == dev->async_status) {
- dev->async_status = OSMOSDR_INACTIVE;
+ next_status = OSMOSDR_INACTIVE;
if (!dev->xfer)
break;
@@ -924,19 +933,22 @@ int osmosdr_read_async(osmosdr_dev_t *dev, osmosdr_read_async_cb_t cb, void *ctx
if (!dev->xfer[i])
continue;
- if (dev->xfer[i]->status == LIBUSB_TRANSFER_COMPLETED) {
+ if (LIBUSB_TRANSFER_CANCELLED !=
+ dev->xfer[i]->status) {
libusb_cancel_transfer(dev->xfer[i]);
- dev->async_status = OSMOSDR_CANCELING;
+ next_status = OSMOSDR_CANCELING;
}
}
- if (OSMOSDR_INACTIVE == dev->async_status)
+ if (OSMOSDR_INACTIVE == next_status)
break;
}
}
_osmosdr_free_async_buffers(dev);
+ dev->async_status = next_status;
+
return r;
}
@@ -945,10 +957,17 @@ int osmosdr_cancel_async(osmosdr_dev_t *dev)
if (!dev)
return -1;
+ /* if streaming, try to cancel gracefully */
if (OSMOSDR_RUNNING == dev->async_status) {
dev->async_status = OSMOSDR_CANCELING;
return 0;
}
+ /* if called while in pending state, change the state forcefully */
+ if (OSMOSDR_INACTIVE != dev->async_status) {
+ dev->async_status = OSMOSDR_INACTIVE;
+ return 0;
+ }
+
return -2;
}