Search code examples
software-defined-radiortl-sdr

rtl-sdr crashes with "Bus error" when running rtl_tcp or rtl_test


I have an SDR dongle connected on a Raspberry Pi 3 running Kali Linux Arm64. The SDR itself is this particular model

Trouble is, whenever I connect to the rtl_tcp server remotely, it exits:

rtl_tcp -a 192.168.200.132
Found 1 device(s):
  0:  Realtek, RTL2838UHIDIR, SN: 00000001

Using device 0: Generic RTL2832U OEM
Found Rafael Micro R820T tuner
[R82XX] PLL not locked!
Tuned to 100000000 Hz.
listening...
Use the device argument 'rtl_tcp=192.168.200.132:1234' in OsmoSDR (gr-osmosdr) source
to receive samples in GRC and control rtl_tcp parameters (frequency, gain, ...).
client accepted! 192.168.200.102 64098
Allocating 15 zero-copy buffers
Bus error

Testing with rtl_test -t is fine:

rtl_test -t
Found 1 device(s):
  0:  Realtek, RTL2838UHIDIR, SN: 00000001

Using device 0: Generic RTL2832U OEM
Found Rafael Micro R820T tuner
Supported gain values (29): 0.0 0.9 1.4 2.7 3.7 7.7 8.7 12.5 14.4 15.7 16.6 19.7 20.7 22.9 25.4 28.0 29.7 32.8 33.8 36.4 37.2 38.6 40.2 42.1 43.4 43.9 44.5 48.0 49.6
[R82XX] PLL not locked!
Sampling at 2048000 S/s.
No E4000 tuner found, aborting.

But testing with a sample rate results in the same undesired behavior.

rtl_test -s 2048000
Found 1 device(s):
  0:  Realtek, RTL2838UHIDIR, SN: 00000001

Using device 0: Generic RTL2832U OEM
Found Rafael Micro R820T tuner
Supported gain values (29): 0.0 0.9 1.4 2.7 3.7 7.7 8.7 12.5 14.4 15.7 16.6 19.7 20.7 22.9 25.4 28.0 29.7 32.8 33.8 36.4 37.2 38.6 40.2 42.1 43.4 43.9 44.5 48.0 49.6
[R82XX] PLL not locked!
Sampling at 2048000 S/s.

Info: This tool will continuously read from the device, and report if
samples get lost. If you observe no further output, everything is fine.

Reading samples in async mode...
Allocating 15 zero-copy buffers
Bus error

How do I keep this from happening, and get RTL-SDR to run properly?

Things I've tried

No change:

  1. I've used RTL-SDR in Kali's repos, as well as compiled from source using the git.osmocom.org/rtl-sdr.git repo — no change
  2. Increased the swap file size to 2 GB — no change

Some change:

Forcing synchronous mode in rtl_test did not produce the error.

rtl_test -s 2048000 -S
Found 1 device(s):
  0:  Realtek, RTL2838UHIDIR, SN: 00000001

Using device 0: Generic RTL2832U OEM
Found Rafael Micro R820T tuner
Supported gain values (29): 0.0 0.9 1.4 2.7 3.7 7.7 8.7 12.5 14.4 15.7 16.6 19.7 20.7 22.9 25.4 28.0 29.7 32.8 33.8 36.4 37.2 38.6 40.2 42.1 43.4 43.9 44.5 48.0 49.6
[R82XX] PLL not locked!
Sampling at 2048000 S/s.

Info: This tool will continuously read from the device, and report if
samples get lost. If you observe no further output, everything is fine.

Reading samples in sync mode...
(Samples are being lost but not reported.)

Introducting the b flag in rtl_tcp allows me to set the number of buffers, which doesn't seem to do much:

rtl_tcp -a 192.168.200.132 -b 1
Found 1 device(s):
  0:  Realtek, RTL2838UHIDIR, SN: 00000001

Using device 0: Generic RTL2832U OEM
Found Rafael Micro R820T tuner
[R82XX] PLL not locked!
Tuned to 100000000 Hz.
listening...
Use the device argument 'rtl_tcp=192.168.200.132:1234' in OsmoSDR (gr-osmosdr) source
to receive samples in GRC and control rtl_tcp parameters (frequency, gain, ...).
client accepted!
Allocating 1 zero-copy buffers
Bus error

Solution

  • I'm still not sure what the problem is, but based on the indication @jsr gave me, I went ahead and removed the zerocopy code and recompiled rtl-sdr and it worked.

    Here's a diff. This is likely a bug in the program and needs to be addressed.

    diff --git a/src/librtlsdr.c b/src/librtlsdr.c
    index 89ec903..61bcebc 100644
    --- a/src/librtlsdr.c
    +++ b/src/librtlsdr.c
    @@ -1748,50 +1748,6 @@ static int _rtlsdr_alloc_async_buffers(rtlsdr_dev_t *dev)
            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]) {
    -                       /* 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;
    -               }
    -       }
    -
    -       /* 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) {
    

    After recompiling, the program worked as expected:

    ~/sandbox/rtl-sdr# rtl_tcp -a 192.168.200.132 -f 89000 -b 100
    Found 1 device(s):
      0:  Realtek, RTL2838UHIDIR, SN: 00000001
    
    Using device 0: Generic RTL2832U OEM
    Found Rafael Micro R820T tuner
    [R82XX] PLL not locked!
    [R82XX] PLL not locked!
    Tuned to 89000 Hz.
    listening...
    Use the device argument 'rtl_tcp=192.168.200.132:1234' in OsmoSDR (gr-osmosdr) source
    to receive samples in GRC and control rtl_tcp parameters (frequency, gain, ...).
    client accepted!
    set gain mode 1
    set agc mode 0
    set direct sampling 0
    Disabled direct sampling mode
    [R82XX] PLL not locked!
    set offset tuning 0
    set bias tee 0
    set sample rate 1800000
    [R82XX] PLL not locked!
    ll+, now 1
    set freq 24000000
    set gain 495
    ll+, now 2
    set gain 495
    set gain 495
    set freq 106661000
    ll+, now 3
    ll+, now 4
    ll+, now 5
    ll+, now 6