USB reset fails when using a LimeSDR Mini on FreeBSD
Jan Behrens
jbe-mlist at magnetkern.de
Sun Jun 28 09:28:12 UTC 2020
On Sat, 27 Jun 2020 17:36:04 +0200
Jan Behrens <jbe-mlist at magnetkern.de> wrote:
> On Sat, 27 Jun 2020 16:12:45 +0200
> Tomasz CEDRO <tomek at cedro.info> wrote:
>
> > I guess the FreeBSD's LibUSB implementation should be one-to-one
> > compatible with the GNU LibUSB.
Unless GNU LibUSB behaves wrong, in which case there'd be a good reason
for FreeBSD's LibUSB to behave differently. But not sure if that's the
case.
> > I would try to test and compare it
> > with Linux and MacOS implementation and see the difference:
> >
> > 1. If the problem exists on FreeBSD, Linux, MacOS. If so/no then if
> > there are different error messages / codes. If there are more verbose
> > codes / messages on systems other than BSD then FreeBSD's
> > implementation may need an update. However, the difference here seems
> > to be the USB stack itself.
As I currently have no Linux installed on my machines, I tested with a
friend how the SoapySDR module for the LimeSDR Mini (SoapyLMS7 from
Lime Suite 20.01.0) behaves on Linux in regard to the
libusb_reset_device() call. This is our result:
We modified LimeSuite-20.01.0/src/ConnectionFTDI/ConnectionFT601.cpp
in the following way:
At the begin of the file:
#include <unistd.h>
#include <sys/types.h>
And then below:
fprintf(stderr, "DEBUG: Executing libusb_reset_device() [UID=%i, effective UID=%i]\n", getuid(), geteuid());
if (libusb_reset_device(dev_handle)!=0)
return ReportError(-1, "USB reset failed", libusb_strerror(libusb_error(r)));
fprintf(stderr, "DEBUG: libusb_reset_device() executed successfully.\n");
This resulted in the following output:
$ SoapySDRUtil --make
######################################################
## Soapy SDR -- the SDR abstraction library ##
######################################################
Make device
linux; GNU C++ version 7.3.0; Boost_106501; UHD_003.010.003.000-0-unknown
[INFO] Make connection: 'LimeSDR Mini [USB 2.0] 1D3AC7FE409032'
DEBUG: Executing libusb_reset_device() [UID=1000, effective UID=1000]
DEBUG: libusb_reset_device() executed successfully.
[INFO] Reference clock 40.00 MHz
[INFO] Device name: LimeSDR-Mini
[INFO] Reference: 40 MHz
[INFO] LMS7002M register cache: Disabled
driver=FT601
hardware=LimeSDR-Mini
boardSerialNumber=0x1d3ac7fe409032
firmwareVersion=6
gatewareVersion=1.30
hardwareVersion=1
protocolVersion=1
Thus libusb_reset_device() returns without an error on GNU/Linux,
despite being executed as user (UID and EUID = 1000).
This proves that on Linux there is no problem in executing the call as
non-root. The problem appears on FreeBSD only.
> >
> > 2. If that function blocks normal operations on FreeBSD while without
> > it everything works fine, then it may be wrapped around ifdef and
> > simply removed for FreeBSD.
Whether the libusb_reset_device() call is needed or not isn't clear to
me. It *appears* to work without the call, but I'm not sure if there
are side effects or corner cases.
The context of the call is as follows:
[...] libusb_open(devs[i], &dev_handle) [...];
if(libusb_kernel_driver_active(dev_handle, 1) == 1) //find out if kernel driver is attached
{
lime::debug("Kernel Driver Active");
if(libusb_detach_kernel_driver(dev_handle, 1) == 0) //detach it
lime::debug("Kernel Driver Detached!");
}
int r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device
if (r < 0)
return ReportError(-1, "Cannot claim interface - %s", libusb_strerror(libusb_error(r)));
if ((r = libusb_claim_interface(dev_handle, 1))<0) //claim interface 1 of device
return ReportError(-1, "Cannot claim interface - %s", libusb_strerror(libusb_error(r)));
lime::debug("Claimed Interface");
if (libusb_reset_device(dev_handle)!=0)
return ReportError(-1, "USB reset failed", libusb_strerror(libusb_error(r)));
FT_FlushPipe(ctrlRdEp); //clear ctrl ep rx buffer
FT_SetStreamPipe(ctrlRdEp,64);
FT_SetStreamPipe(ctrlWrEp,64);
isConnected = true;
return 0;
See:
https://github.com/myriadrf/LimeSuite/blob/1c1c202f9a6ae4bb34068b6f3f576f7f8e74c7f1/src/ConnectionFTDI/ConnectionFT601.cpp#L160
> >
> > 3. Make sure this is not a bug in the LimeSDR firmware that makes this
> > non-standard behaviour.
As shown above, no problem on Linux.
It might still be wrong to call libusb_reset_device(), but for that we'd
need to understand why it's called and if it's generally a bad practice
to call it as driver that runs as non-root (and if there are
alternatives or if it's just not necessary to do the call).
> >
> > 4. According to `man usbconfig` reset will perform "Reset the device.
> > This forces the USB stack to reenumerate the bus.". If LimeSDR uses
> > some dynamic USB interfaces configuration and re-organizes itself at
> > runtime then I would observe how the FreeBSD USB stack reacts to that
> > changes. Such reset may not be even necessary by hand (or from libusb)
> > if the OS re-enumerates the bus for you. Maybe on other OS it is
> > important to call that libusb reset to make sure the bus is
> > re-enumerated.
> >
> > @HPS is the author of the USB stack so he could provide some hints..
> > but without actually seeing the device it can be hard to achieve :-)
For that, it would be helpful to understand when libusb_reset_device()
needs to or should be called, and if it's (supposed to be) the same on
FreeBSD, Linux, and macOS.
> > [...]
> >
> > Are you sure this is the problem? When run as root does the program
> > works fine? If so, there may be a systctl setting for the stack that
> > may allow user to reset / power-on-off the port (@HPS?)? You may want
> > to take a look at `sysctl -a | grep usb` to search for such sysctl
> > option. Maybe also `man usbconfig` and `man usb`.
Regards,
Jan
More information about the freebsd-usb
mailing list