From a09144bc88c35a74b425216a434bbf25a613ecc3 Mon Sep 17 00:00:00 2001 From: Dimitri Stolnikov Date: Wed, 8 Aug 2012 21:20:59 +0200 Subject: implement a more robust cancelation mechanism of async reader --- software/libosmosdr/src/libosmosdr.c | 35 +++++++++++++++++++++++++++-------- 1 file 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; } -- cgit v1.2.3