pothosware / SoapySDR

Vendor and platform neutral SDR support library.
https://github.com/pothosware/SoapySDR/wiki
Boost Software License 1.0
1.13k stars 179 forks source link

If more than one SDR device is connected to a Host system then only the first detected SDR device is opened #248

Closed farhan296 closed 4 years ago

farhan296 commented 4 years ago

Hello,

I am using XTRX pro SDR with SOAPY SDR library. I have two of those connected to my PC. On probing and using SoapySDR::KwargsList SoapySDR::Device::enumerate function I am able to get the result of both the devices.

Now when I try to open the device using SoapySDR::Device* SoapySDR::Device::make(const Kwargs &inputArgs) , only the first device in the list returned from the enumeration is opened.

The problem is in the SoapySDR::Device* SoapySDR::Device::make(const Kwargs &inputArgs) function. Upon passing the second device in the argument of the function it first checks if it has already been placed in the list at line 135 of Factory.cpp . If it does not find it in the list it goes on to enumerate again at line 142 and then in line 143 it picks the first device from the enumeration result that has already been opened and present in the list. From there on it exits the function.

guruofquality commented 4 years ago

Can you confirm the same bug with SoapySDRUtil --find, and SoapySDRUtil --make="the key/value args" and share what arguments are passing to the make option.

The problem is in the SoapySDR::Device* SoapySDR::Device::make(const Kwargs &inputArgs) function. Upon passing the second device in the argument of the function it first checks if it has already been placed in the list at line 135 of Factory.cpp . If it does not find it in the list it goes on to enumerate again at line 142 and then in line 143 it picks the first device from the enumeration result that has already been opened and present in the list. From there on it exits the function.

Thats correct behavior, but the enumerate call should be returning only one device if you passed in arguments that specify a specific device (usually by serial). If not, it could be a bug in the XTRX enumerate code, you may want to let them know.

farhan296 commented 4 years ago

sudo SoapySDRUtil --find ######################################################

Soapy SDR -- the SDR abstraction library

######################################################

14:55:03.477718 DEBUG: xtrxllpciev0_discovery:264 [PCIE] pcie: Found pcie:///dev/xtrx0 14:55:03.477772 DEBUG: xtrxllpciev0_discovery:264 [PCIE] pcie: Found pcie:///dev/xtrx1 Found device 0 addr = pcie:///dev/xtrx0 dev = pcie:///dev/xtrx0 driver = xtrx label = XTRX: pcie:///dev/xtrx0 (10Gbit) media = PCIe module = SoapyXTRX name = XTRX serial = type = xtrx

Found device 1 addr = pcie:///dev/xtrx1 dev = pcie:///dev/xtrx1 driver = xtrx label = XTRX: pcie:///dev/xtrx1 (10Gbit) media = PCIe module = SoapyXTRX name = XTRX serial = type = xtrx In the above we can clearly see two devices are connected to the system now when I pass the Key Value pair of xtrx1 above in make it only opens xtrx0 because of the reason I mentioned above.

sudo SoapySDRUtil --make="addr=pcie:///dev/xtrx1,dev=pcie:///dev/xtrx1,driver=xtrx,label=XTRX: pcie:///dev/xtrx1 (10Gbit),media=PCIe,module=SoapyXTRX,name=XTRX,serial= ,type=xtrx" ######################################################

Soapy SDR -- the SDR abstraction library

######################################################

Make device addr=pcie:///dev/xtrx1,dev=pcie:///dev/xtrx1,driver=xtrx,label=XTRX: pcie:///dev/xtrx1 (10Gbit),media=PCIe,module=SoapyXTRX,name=XTRX,serial= ,type=xtrx 14:59:32.889379 DEBUG: xtrxllpciev0_discovery:264 [PCIE] pcie: Found pcie:///dev/xtrx0 14:59:32.889409 DEBUG: xtrxllpciev0_discovery:264 [PCIE] pcie: Found pcie:///dev/xtrx1 [INFO] Make connection: 'pcie:///dev/xtrx0' 14:59:32.891626 INFO: [CTRL] PCI:/dev/xtrx0: XTRX Rev4 (04000113) 14:59:32.891633 INFO: [BPCI] PCI:/dev/xtrx0: RX DMA STOP MIMO (BLK:0 TS:0); TX DMA STOP MIMO @0.0 14:59:32.891637 INFO: [PCIE] PCI:/dev/xtrx0: Device pcie:///dev/xtrx0 was opened CPU Features: SSE2+ SSE4.1+ AVX+ FMA+ 14:59:33.008522 INFO: [CTRL] PCI:/dev/xtrx0: RFIC_GPIO 0x000304 14:59:33.108673 INFO: [CTRL] PCI:/dev/xtrx0: FPGA V_GPIO set to 3280mV 14:59:33.108705 INFO: [CTRL] PCI:/dev/xtrx0: LMS PMIC DCDC out set to VA18=1880mV VA14=1480mV VA12=1340mV 14:59:33.112239 INFO: [CTRL] PCI:/dev/xtrx0: FPGA V_IO set to 1800mV 14:59:33.122385 INFO: [CTRL] PCI:/dev/xtrx0: RFIC_GPIO 0x000306 14:59:33.133446 INFO: [LSM7] PCI:/dev/xtrx0: LMS VER:7 REV:1 MASK:1 (3841) 14:59:33.133480 INFO: [CTRL] PCI:/dev/xtrx0: RFIC_GPIO 0x00031e 14:59:33.133601 INFO: [DBGP] Starting XTRX debug thread driver=xtrx hardware=/dev/xtrx0 14:59:33.134370 INFO: [CTRL] PCI:/dev/xtrx0: RFIC_GPIO 0x000300 14:59:33.135506 INFO: [PCIE] PCI:/dev/xtrx0: Device closing

farhan296 commented 4 years ago

Ideally one should enumerate first and based on the enumeration result, the key value pair must be passed to make function. The make function now always picks the first device identified in the list via results.front() in line 143. What happens in the case when there is more than one device on the system and the user wants to make the second device in the list? Clearly this is not possible in the current implementation.

guruofquality commented 4 years ago

Ideally one should enumerate first and based on the enumeration result, the key value pair must be passed to make function. The make function now always picks the first device identified in the list via results.front() in line 143

Correct

What happens in the case when there is more than one device on the system and the user wants to make the second device in the list? Clearly this is not possible in the current implementation.

In this case you want it to only yield one result if you pass the args in for a specific device, but you are seeing two. If you run 'sudo SoapySDRUtil --find="addr=pcie:///dev/xtrx1,dev=pcie:///dev/xtrx1,driver=xtrx,label=XTRX: pcie:///dev/xtrx1 (10Gbit),media=PCIe,module=SoapyXTRX,name=XTRX,serial= ,type=xtrx"' you get two devices right?

I regularly use SoapySDR with dozens of devices on the network. What I'm saying is that the implementation is not in this project. Its in Soapy XTRX. There is nothing I can do to address this issue this in this repository as far as I know.

For example somethings that seem like bugs to me:

I think fairwaves needs to know about this so they can fix it.

farhan296 commented 4 years ago

Correct I see two. The thing is that I would not even know before hand what the Device's key value pairs are until I enumerate right ? After enumeration I should pass on those parameters of that particular device (xtrx0 or xtrx1) to make function for it to make that specific device. In the current implementation it always makes xtrx0 even when I pass the key/value pairs for xtrx1. This is because at first the Devicetable is empty, when make is invoked it searches for the device table in line 135. If it does not find it goes ahead and calls the enumerate function which returns a list with xtrx0 and xtrx1 key/value pair. At line 143 discoveredArgs = results.front(); it can be seen that the first entry is returned only which is xtrx0 key/value pairs. xtrx1 is never referenced. This issue will arise when you connect two or more SDRs of the same vendor using the same underlying drivers. Take two LimeSDR for instance and connect them to the same host system.

Answer to your questions

  1. XTRX have a blank serial number because it is probably a PCIe device?
  2. I checked the xtrx enumeration driver it works as it should returns 2 devices xtrx0 and xtrx1. I am pretty sure the problem is with line 143 of Factory.cpp. I hacked around a bit and was able to make both devices individually on the same system.
guruofquality commented 4 years ago

Generally devices support a unique way to identify them that you can know prior such as serial number (almost universally) and when not that a unique address or index are always possible.

For XTRX, I would strongly prefer the serial be fixed if possible -- that way the driver would match how 90% of the other supported devices work in this reguard. As a close second I think "addr" or "dev" (specifically) would work -- as they are unique, and hopefully can be made persistent on reboot.

As far as factory implementation. I know it only picks the first enumeration result even if there are more. But the intention is to make sure that the enumeration implementation provided by the manufacturer's driver gets to sanitize the input arguments and ensure that only arguments from the manufacturer's enumerate is passed into the manufacturer's factory function.

There is intentionally not a way for factory in this project to use the args to select more than one of the enumeration result. Its the job of the manufacturer's enumeration function to do this. That gives the device manufacturer the flexibility on how to implement it.

This is documented here for driver maintainers: https://github.com/pothosware/SoapySDR/wiki/DriverGuide#filtering-devices

So in this case, the XTRX has a bug in how this enumeration is supposed to work. I opened an issue here: https://github.com/xtrx-sdr/libxtrx/issues/20