diff --git a/src/librtlsdr.c b/src/librtlsdr.c index 433ed5b..89ec903 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -1755,11 +1755,26 @@ static int _rtlsdr_alloc_async_buffers(rtlsdr_dev_t *dev) 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]) { + if (dev->xfer_buf[i]) { + /* Check if Kernel usbfs mmap() bug is present: if the + * mapping is correct, the buffers point to memory that + * was memset to 0 by the Kernel, otherwise, they point + * to random memory. We check if the buffers are zeroed + * and otherwise fall back to buffers in userspace. + */ + if (dev->xfer_buf[i][0] || memcmp(dev->xfer_buf[i], + dev->xfer_buf[i] + 1, + dev->xfer_buf_len - 1)) { + fprintf(stderr, "Detected Kernel usbfs mmap() " + "bug, falling back to buffers " + "in userspace\n"); + dev->use_zerocopy = 0; + break; + } + } else { fprintf(stderr, "Failed to allocate zero-copy " "buffer for transfer %d\nFalling " "back to buffers in userspace\n", i); - dev->use_zerocopy = 0; break; }