Bug #6005
openrtl-test and rtl-sdr exit code=-5 when running on Windows 10 WSL and Ubuntu
0%
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);
}