pothosware/SoapyPlutoSDR

Driver discovery method sometimes is incompatible with SoapyRTLSDR

dmitryelj opened this issue · 12 comments

Hi all,

While testing the last PothosSDR package (PothosSDR-2019.03.24-vc14-x64.exe) I've found that sometimes RTL SDR V3 is not initializing correctly.

After a small investigation it was found that the problem is causing by having PlutoSDRSupport.dll in the drivers folder.
More details here: pothosware/SoapyRTLSDR#38

Maybe 2 threads are trying to access USB bus at the same time during the devices enumeration.
Please check.

Many of the usb devices wrap around libusb, rtl, hackrf, etc. I think they play nicely together. Someone may have to look under the hood for iio_create_scan_context and iio_scan_context_get_info_list, and see if its doing anything "interesting" or "suspicious".

iio_create_scan_context calls down to usb_context_scan -- couldn't spot anything suspicous so far.
I use both RTL-SDR an Pluto and I don't remember encountering this scan problem.
Can you perhaps describe the smallest setup where this occurs? Distro, Versions and compile flags would be great.

Thanks for the answer.

I am using distro from "PothosSDR-2019.03.24-vc14-x64.exe", system Windows 10, receiver RTL SDR V3, I don't have PlutoSDR at all. In the older version "PothosSDR-2018.09.09-vc14-x64.exe" all was ok.

For code to reproduce the bug and screenshot please check the link pothosware/SoapyRTLSDR#38

I solved the problem by removing "PlutoSDRSupport.dll" from the PothosSDR folder, but its just a workaround.

FWIW libusb should be ok with this in principal: https://github.com/libusb/libusb/blob/v1.0.22/libusb/core.c#L294

I can see that rtl sdr checks the vid/pid before opening it with libusb_open:
https://git.osmocom.org/rtl-sdr/tree/src/librtlsdr.c#n1369

Now where does IIO check the vid/pid before opening the device?
https://github.com/analogdevicesinc/libiio/blob/master/usb.c#L1152

It looks like libusb_open() is called on every device before inspecting it further. I think it should be checking vid/pid just like rtlsdr with libusb_get_device_descriptor() before opening. So if I had to guess, by not filtering out the devices, libiio is opening the rtl device simultaneously with the librtl in multiple threads -- and that may be causing the problem. And even if its not the libusb_open itself, it might be one of the calls that queries the info.

So we need to file a bug with https://github.com/analogdevicesinc/libiio is my guess...
Ideally we would patch something into IIO to filter based on the VID/PID and see if that helps first.

Would that work? I have a bunch of iio sensors on my laptop, so I don't know that we can restrict libiio to opening only certain usb vid/pid

Would that work? I have a bunch of iio sensors on my laptop, so I don't know that we can restrict libiio to opening only certain usb vid/pid

I dont know about all devices. I assume there is only a finite number of IIO libusb devices. But maybe the driver should support all of them that anyone could make with any ID numbers?

If you look closely its just grabbing some string and checking if its IIO: https://github.com/analogdevicesinc/libiio/blob/master/usb.c#L436 Unfortunately it needs to be opened for that.

I dont know if being opened is even the problem. I think someone needs to try out this VID/PID theory and see what happens. If that fixes it and libiio really does need to open all devices supported by libusb then I think it needs a separate iio_scan_context() that supports passing a VID/PID because ultimately pluto sdr specifically does have a finite number of products IDs that are supported.

The PlutoSDRSupport.dll also appears to be causing difficulties for UHD devices, as per this thread:

https://groups.google.com/g/pothos-users/c/VqWCDfvIMk0/m/TETVSs3DEgAJ

I have tried to report to IIO maintainers about the issue: analogdevicesinc/libiio#586

rgetz commented

I assume there is only a finite number of IIO libusb devices.

no - it's nearly infinite, and grows every kernel release.

Anything that is in https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/iio can be exposed over USB, by whatever hardware manufacture wants to make a widget that has USB OTG.

@rgetz thanks!

I guess this is up to date vid/pid list in the relevant udev rules: https://raw.githubusercontent.com/analogdevicesinc/plutosdr-fw/master/scripts/53-adi-plutosdr-usb.rules

That makes more sense now. libIIO can be any VID/PID of course, but PlutoSDR isnt, its just a small subset of course

So most of these libusb hardware drivers know about the subset of VID/PIDs they support, and they are careful to only open devices that match. RTL driver actually has quite an extensive list: https://github.com/librtlsdr/librtlsdr/blob/master/src/librtlsdr.c#L330

So I think to do this right, SoapyPlutoSDR would have a list of every know VID/PID just like rtl and similar drivers, and it would pass the VID/PID as some kind of scan context info into libIIO to build up a list of discovered devices.

So here SoapyPlutoSDR holds the list of unique VID/PIDs it wants to support, and the only change to libIIO is to scan all of the devices that match the new VID/PID criteria which are passed in via iio_create_scan_context? I need to look more at the API, but I assume the scanning can take some kind of arbitrary arguments, so this filtering based on vendor/product ID would not be the default, it would only be engaged when passed in.

I will try to get back to the other thread in a moment.

rgetz commented

Most people don't install that udev rule - they use this one that comes with libiio:

https://github.com/analogdevicesinc/libiio/blob/master/libiio.rules.cmakein

right now - libiio doesn't support PID/VID filtering - that would need to be extended - the existing API takes a usb uri usb:3.2.1 which is returned back by a scan context...

Let me poke into this a bit more to understand what the actual issue is in libusb.

Just for reference if it helps, heres some other SDR community devices drivers that use libusb, and where they do the filtering

Hackrf: https://github.com/mossmann/hackrf/blob/master/host/libhackrf/src/hackrf.c#L428
RTLSDR: https://github.com/librtlsdr/librtlsdr/blob/master/src/librtlsdr.c#L1647
LimeSDR: https://github.com/myriadrf/LimeSuite/blob/master/src/ConnectionFX3/ConnectionFX3Entry.cpp#L100
USRP: https://github.com/EttusResearch/uhd/blob/master/host/lib/transport/libusb1_base.cpp#L467

so libusb_get_device_list and libusb_get_device_descriptor is absolutely always safe to call and you can access any of the fields in libusb_device_descriptor http://libusb.sourceforge.net/api-1.0/structlibusb__device__descriptor.html

But to read out serial numbers and things like that with libusb_get_string_descriptor_ascii you have to do a libusb_open which is an exclusive access to the device handle.

So most of these drivers will check the idVendor and idProduct fields before making calls like libusb_get_string_descriptor_ascii or possibly going deeper and accessing control packets -- Because who knows what the device may do if its not the one you expect.