mirror of
https://github.com/rtlsdrblog/rtl-sdr-blog.git
synced 2025-02-28 18:04:09 +01:00
lib: use USB zero-copy transfers if possible
Decreases CPU load especially for embedded machines. Requires Linux >= 4.6 and libusb >= 1.0.21. If this is not the case or the allocation fails, we will fall back to buffers allocated in userspace. Signed-off-by: Steve Markgraf <steve@steve-m.de>
This commit is contained in:
parent
326b0e3acc
commit
a854ae8b48
@ -103,6 +103,7 @@ struct rtlsdr_dev {
|
|||||||
void *cb_ctx;
|
void *cb_ctx;
|
||||||
enum rtlsdr_async_status async_status;
|
enum rtlsdr_async_status async_status;
|
||||||
int async_cancel;
|
int async_cancel;
|
||||||
|
int use_zerocopy;
|
||||||
/* rtl demod context */
|
/* rtl demod context */
|
||||||
uint32_t rate; /* Hz */
|
uint32_t rate; /* Hz */
|
||||||
uint32_t rtl_xtal; /* Hz */
|
uint32_t rtl_xtal; /* Hz */
|
||||||
@ -1741,12 +1742,49 @@ static int _rtlsdr_alloc_async_buffers(rtlsdr_dev_t *dev)
|
|||||||
dev->xfer[i] = libusb_alloc_transfer(0);
|
dev->xfer[i] = libusb_alloc_transfer(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dev->xfer_buf) {
|
if (dev->xfer_buf)
|
||||||
dev->xfer_buf = malloc(dev->xfer_buf_num *
|
return -2;
|
||||||
sizeof(unsigned char *));
|
|
||||||
|
|
||||||
for(i = 0; i < dev->xfer_buf_num; ++i)
|
dev->xfer_buf = malloc(dev->xfer_buf_num * sizeof(unsigned char *));
|
||||||
|
memset(dev->xfer_buf, 0, dev->xfer_buf_num * sizeof(unsigned char *));
|
||||||
|
|
||||||
|
#if defined (__linux__) && LIBUSB_API_VERSION >= 0x01000105
|
||||||
|
fprintf(stderr, "Allocating %d zero-copy buffers\n", dev->xfer_buf_num);
|
||||||
|
|
||||||
|
dev->use_zerocopy = 1;
|
||||||
|
for (i = 0; i < dev->xfer_buf_num; ++i) {
|
||||||
|
dev->xfer_buf[i] = libusb_dev_mem_alloc(dev->devh, dev->xfer_buf_len);
|
||||||
|
|
||||||
|
if (!dev->xfer_buf[i]) {
|
||||||
|
fprintf(stderr, "Failed to allocate zero-copy "
|
||||||
|
"buffer for transfer %d\nFalling "
|
||||||
|
"back to buffers in userspace\n", i);
|
||||||
|
|
||||||
|
dev->use_zerocopy = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* zero-copy buffer allocation failed (partially or completely)
|
||||||
|
* we need to free the buffers again if already allocated */
|
||||||
|
if (!dev->use_zerocopy) {
|
||||||
|
for (i = 0; i < dev->xfer_buf_num; ++i) {
|
||||||
|
if (dev->xfer_buf[i])
|
||||||
|
libusb_dev_mem_free(dev->devh,
|
||||||
|
dev->xfer_buf[i],
|
||||||
|
dev->xfer_buf_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* no zero-copy available, allocate buffers in userspace */
|
||||||
|
if (!dev->use_zerocopy) {
|
||||||
|
for (i = 0; i < dev->xfer_buf_num; ++i) {
|
||||||
dev->xfer_buf[i] = malloc(dev->xfer_buf_len);
|
dev->xfer_buf[i] = malloc(dev->xfer_buf_len);
|
||||||
|
|
||||||
|
if (!dev->xfer_buf[i])
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1772,9 +1810,18 @@ static int _rtlsdr_free_async_buffers(rtlsdr_dev_t *dev)
|
|||||||
|
|
||||||
if (dev->xfer_buf) {
|
if (dev->xfer_buf) {
|
||||||
for (i = 0; i < dev->xfer_buf_num; ++i) {
|
for (i = 0; i < dev->xfer_buf_num; ++i) {
|
||||||
if (dev->xfer_buf[i])
|
if (dev->xfer_buf[i]) {
|
||||||
|
if (dev->use_zerocopy) {
|
||||||
|
#if defined (__linux__) && LIBUSB_API_VERSION >= 0x01000105
|
||||||
|
libusb_dev_mem_free(dev->devh,
|
||||||
|
dev->xfer_buf[i],
|
||||||
|
dev->xfer_buf_len);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
free(dev->xfer_buf[i]);
|
free(dev->xfer_buf[i]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(dev->xfer_buf);
|
free(dev->xfer_buf);
|
||||||
dev->xfer_buf = NULL;
|
dev->xfer_buf = NULL;
|
||||||
@ -1828,7 +1875,12 @@ int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx,
|
|||||||
|
|
||||||
r = libusb_submit_transfer(dev->xfer[i]);
|
r = libusb_submit_transfer(dev->xfer[i]);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
fprintf(stderr, "Failed to submit transfer %i!\n", i);
|
fprintf(stderr, "Failed to submit transfer %i\n"
|
||||||
|
"Please increase your allowed "
|
||||||
|
"usbfs buffer size with the "
|
||||||
|
"following command:\n"
|
||||||
|
"echo 0 > /sys/module/usbcore"
|
||||||
|
"/parameters/usbfs_memory_mb\n", i);
|
||||||
dev->async_status = RTLSDR_CANCELING;
|
dev->async_status = RTLSDR_CANCELING;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user