Project

General

Profile

Actions

Bug #6005

open

rtl-test and rtl-sdr exit code=-5 when running on Windows 10 WSL and Ubuntu

Added by mluckham about 1 year ago. Updated 6 months ago.

Status:
New
Priority:
Normal
Assignee:
Target version:
-
Start date:
04/16/2023
Due date:
% Done:

0%

Spec Reference:

Description

While trying to get radiosonde_auto_rx 6.0 to work on Windows 10 WSL and Ubuntu, neither the RTL-SDR.COM dongle nor an older DVB-T+DAB+FM dongle were detected by auto_rx.py. Increasing the log level to debug showed that rtl_sdr was returning a non-zero error code.

Echoing the return code ($#) after running rtl_sdr or rtl_test on the command line, -5 is being returned instead of zero. Modifying auto_rx/autorx/utils.py to accept a return code of 5 allowed the SDR to be detected and operate normally.

Moving to the rtl-sdr code, in librtlsdr.c, the rtl_read_async() method returns -5 from the variable 'r' if a non-zero error was returned from r=libusb_cancel_transfer. The main also returns the non-zero value of 'r' which is the problem.

I reported these findings on: [https://github.com/projecthorus/radiosonde_auto_rx/issues/765 [https://github.com/projecthorus/radiosonde_auto_rx/issues/765]].

Moving on to Windows 10 WSL, the dorssel/usbipd-win project bridges Windows 10 USB devices to the Ubuntu environment. I submitted a request for assistance to the project and they advised how to capture debug information. Their response: [https://github.com/dorssel/usbipd-win/issues/572 [https://github.com/dorssel/usbipd-win/issues/572]]

Here is the code change that I made to librtlsdr.c to absorb the error code and return the normal exit code=0. There are two changes flagged with the comment '// Mike'. I don't know whether this change is generic enough - it just works in this situation.


int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx,
                          uint32_t buf_num, uint32_t buf_len)
{
        unsigned int i;
        int r = 0;
        struct timeval tv = { 1, 0 };
        struct timeval zerotv = { 0, 0 };
        enum rtlsdr_async_status next_status = RTLSDR_INACTIVE;

        if (!dev)
                return -1;

        if (RTLSDR_INACTIVE != dev->async_status)
                return -2;

        dev->async_status = RTLSDR_RUNNING;
        dev->async_cancel = 0;

        dev->cb = cb;
        dev->cb_ctx = ctx;

        if (buf_num > 0)
                dev->xfer_buf_num = buf_num;
        else
                dev->xfer_buf_num = DEFAULT_BUF_NUMBER;

        if (buf_len > 0 && buf_len % 512 == 0) /* len must be multiple of 512 */
                dev->xfer_buf_len = buf_len;
        else
                dev->xfer_buf_len = DEFAULT_BUF_LENGTH;

        _rtlsdr_alloc_async_buffers(dev);

        for(i = 0; i < dev->xfer_buf_num; ++i) {
                libusb_fill_bulk_transfer(dev->xfer[i],
                                          dev->devh,
                                          0x81,
                                          dev->xfer_buf[i],
                                          dev->xfer_buf_len,
                                          _libusb_callback,
                                          (void *)dev,
                                          BULK_TIMEOUT);

                r = libusb_submit_transfer(dev->xfer[i]);
                if (r < 0) {
                        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;
                        break;
                }
        }

        while (RTLSDR_INACTIVE != dev->async_status) {
                r = libusb_handle_events_timeout_completed(dev->ctx, &tv,
                                                           &dev->async_cancel);
                if (r < 0) {
                        fprintf(stderr, "libusb_handle_events_timeout_completed returned: %d\n", r);
                        if (r == LIBUSB_ERROR_INTERRUPTED) /* stray signal */
                                continue;
                        break;
                }

                if (RTLSDR_CANCELING == dev->async_status) {
                        next_status = RTLSDR_INACTIVE;

                        if (!dev->xfer)
                                break;

                        for(i = 0; i < dev->xfer_buf_num; ++i) {
                                if (!dev->xfer[i])
                                        continue;

                                if (LIBUSB_TRANSFER_CANCELLED !=
                                                dev->xfer[i]->status) {

                                        r = libusb_cancel_transfer(dev->xfer[i]);
                                        fprintf(stderr, "libusb_cancel_transfer : %d\n", r);
                                        /* handle events after canceling
                                         * to allow transfer status to
                                         * propagate */
#ifdef _WIN32
                                        Sleep(1);
#endif
                                        libusb_handle_events_timeout_completed(dev->ctx,
                                                                               &zerotv, NULL);

                                        // Mike: first call return r=0, after that r=-5, final call
                                        if (r < 0)
                                                continue;

                                        next_status = RTLSDR_CANCELING;
                                }
                        }

                        // Mike
                        if (r < 0) {
                                fprintf(stderr, "final r return value %d, reset to 0", r);
                                r = 0;
                        }

                        if (dev->dev_lost || RTLSDR_INACTIVE == next_status) {
                                /* handle any events that still need to
                                 * be handled before exiting after we
                                 * just cancelled all transfers */
                                libusb_handle_events_timeout_completed(dev->ctx,
                                                                       &zerotv, NULL);
                                break;
                        }
                }
        }

        _rtlsdr_free_async_buffers(dev);

        dev->async_status = next_status;

        return r;
}

int rtlsdr_cancel_async(rtlsdr_dev_t *dev)
{
        if (!dev)
                return -1;

        /* if streaming, try to cancel gracefully */
        if (RTLSDR_RUNNING == dev->async_status) {
                dev->async_status = RTLSDR_CANCELING;
                dev->async_cancel = 1;
                return 0;
        }

        /* if called while in pending state, change the state forcefully */
#if 0
        if (RTLSDR_INACTIVE != dev->async_status) {
                dev->async_status = RTLSDR_INACTIVE;
                return 0;
        }
#endif
        return -2;
}

uint32_t rtlsdr_get_tuner_clock(void *dev)
{
        uint32_t tuner_freq;

        if (!dev)
                return 0;

        /* read corrected clock value */
        if (rtlsdr_get_xtal_freq((rtlsdr_dev_t *)dev, NULL, &tuner_freq))
                return 0;

        return tuner_freq;
}

int rtlsdr_i2c_write_fn(void *dev, uint8_t addr, uint8_t *buf, int len)
{
        if (dev)
                return rtlsdr_i2c_write(((rtlsdr_dev_t *)dev), addr, buf, len);

        return -1;
}

int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len)
{
        if (dev)
                return rtlsdr_i2c_read(((rtlsdr_dev_t *)dev), addr, buf, len);

        return -1;
}

int rtlsdr_set_bias_tee_gpio(rtlsdr_dev_t *dev, int gpio, int on)
{
        if (!dev)
                return -1;

        rtlsdr_set_gpio_output(dev, gpio);
        rtlsdr_set_gpio_bit(dev, gpio, on);

        return 0;
}

int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on)
{
        return rtlsdr_set_bias_tee_gpio(dev, 0, on);
}

Actions #1

Updated by laforge 6 months ago

  • Assignee set to steve-m
Actions

Also available in: Atom PDF

Add picture from clipboard (Maximum size: 48.8 MB)