diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java b/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java index c4cfa2da..d297e1f4 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java +++ b/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java @@ -69,25 +69,25 @@ public class TunerFactory /** * Create a USB tuner * @param tunerClass to instantiate - * @param port usb + * @param portAddress usb * @param bus usb * @param tunerErrorListener to listen for errors from the tuner * @param channelizerType for the tuner * @return instantiated tuner * @throws SourceException if the tuner class is unrecognized */ - public static Tuner getUsbTuner(TunerClass tunerClass, int port, int bus, ITunerErrorListener tunerErrorListener, + public static Tuner getUsbTuner(TunerClass tunerClass, String portAddress, int bus, ITunerErrorListener tunerErrorListener, ChannelizerType channelizerType) throws SourceException { switch(tunerClass) { case AIRSPY: - return new AirspyTuner(new AirspyTunerController(bus, port, tunerErrorListener), tunerErrorListener, channelizerType); + return new AirspyTuner(new AirspyTunerController(bus, portAddress, tunerErrorListener), tunerErrorListener, channelizerType); case FUNCUBE_DONGLE_PRO: TargetDataLine tdl1 = MixerManager.getTunerTargetDataLine(MixerTunerType.FUNCUBE_DONGLE_PRO); if(tdl1 != null) { - FCD1TunerController controller = new FCD1TunerController(tdl1, bus, port, tunerErrorListener); + FCD1TunerController controller = new FCD1TunerController(tdl1, bus, portAddress, tunerErrorListener); return new FCDTuner(controller, tunerErrorListener); } throw new SourceException("Unable to find matching tuner sound card mixer"); @@ -95,14 +95,14 @@ public class TunerFactory TargetDataLine tdl2 = MixerManager.getTunerTargetDataLine(MixerTunerType.FUNCUBE_DONGLE_PRO_PLUS); if(tdl2 != null) { - FCD2TunerController controller = new FCD2TunerController(tdl2, bus, port, tunerErrorListener); + FCD2TunerController controller = new FCD2TunerController(tdl2, bus, portAddress, tunerErrorListener); return new FCDTuner(controller, tunerErrorListener); } throw new SourceException("Unable to find matching tuner sound card mixer"); case HACKRF: - return new HackRFTuner(new HackRFTunerController(bus, port, tunerErrorListener), tunerErrorListener, channelizerType); + return new HackRFTuner(new HackRFTunerController(bus, portAddress, tunerErrorListener), tunerErrorListener, channelizerType); case RTL2832: - return new RTL2832Tuner(new RTL2832TunerController(bus, port, tunerErrorListener), tunerErrorListener, channelizerType); + return new RTL2832Tuner(new RTL2832TunerController(bus, portAddress, tunerErrorListener), tunerErrorListener, channelizerType); default: throw new SourceException("Unrecognized tuner class [" + tunerClass + "]"); } diff --git a/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerController.java index c7859894..9d125e34 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerController.java @@ -77,12 +77,12 @@ public class AirspyTunerController extends USBTunerController /** * Constructs an instance * @param bus usb - * @param port usb + * @param portAddress usb * @param tunerErrorListener to receive error notifications from this controller */ - public AirspyTunerController(int bus, int port, ITunerErrorListener tunerErrorListener) + public AirspyTunerController(int bus, String portAddress, ITunerErrorListener tunerErrorListener) { - super(bus, port, FREQUENCY_MIN, FREQUENCY_MAX, 0, USABLE_BANDWIDTH_PERCENT, tunerErrorListener); + super(bus, portAddress, FREQUENCY_MIN, FREQUENCY_MAX, 0, USABLE_BANDWIDTH_PERCENT, tunerErrorListener); } @Override diff --git a/src/main/java/io/github/dsheirer/source/tuner/fcd/FCDTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/fcd/FCDTunerController.java index 83ae087d..4fd13258 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/fcd/FCDTunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/fcd/FCDTunerController.java @@ -28,6 +28,7 @@ import io.github.dsheirer.source.tuner.MixerTunerType; import io.github.dsheirer.source.tuner.TunerClass; import io.github.dsheirer.source.tuner.TunerController; import io.github.dsheirer.source.tuner.TunerType; +import io.github.dsheirer.source.tuner.manager.TunerManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.usb4java.Context; @@ -56,7 +57,7 @@ public abstract class FCDTunerController extends TunerController private final static byte FCD_ENDPOINT_OUT = (byte) 0x2; private int mBus; - private int mPort; + private String mPortAddress; private Context mDeviceContext = new Context(); private Device mDevice; private DeviceDescriptor mDeviceDescriptor = new DeviceDescriptor(); @@ -73,17 +74,17 @@ public abstract class FCDTunerController extends TunerController * @param tunerType of FCD * @param mixerTDL for the sound card mixer interface * @param bus usb - * @param port usb + * @param portAddress usb * @param minTunableFrequency of the tuner * @param maxTunableFrequency of the tuner * @param tunerErrorListener to receive errors from this tuner */ - public FCDTunerController(MixerTunerType tunerType, TargetDataLine mixerTDL, int bus, int port, + public FCDTunerController(MixerTunerType tunerType, TargetDataLine mixerTDL, int bus, String portAddress, int minTunableFrequency, int maxTunableFrequency, ITunerErrorListener tunerErrorListener) { super(tunerErrorListener); mBus = bus; - mPort = port; + mPortAddress = portAddress; setMinimumFrequency(minTunableFrequency); setMaximumFrequency(maxTunableFrequency); setMiddleUnusableHalfBandwidth(DC_SPIKE_AVOID_HALF_BANDWIDTH); @@ -177,6 +178,8 @@ public abstract class FCDTunerController extends TunerController */ private Device findDevice() throws SourceException { + Device foundDevice = null; + DeviceList deviceList = new DeviceList(); int count = LibUsb.getDeviceList(mDeviceContext, deviceList); @@ -187,15 +190,37 @@ public abstract class FCDTunerController extends TunerController int bus = LibUsb.getBusNumber(device); int port = LibUsb.getPortNumber(device); - if(mBus == bus && mPort == port) + if(port > 0) { - return device; + String portAddress = TunerManager.getPortAddress(device); + + if(mBus == bus && mPortAddress != null && mPortAddress.equals(portAddress)) + { + foundDevice = device; + } + else + { + LibUsb.unrefDevice(device); + } + } + else + { + LibUsb.unrefDevice(device); } } } + else + { + throw new SourceException("LibUsb couldn't discover USB device [" + mBus + ":" + mPortAddress + + "] from device list" + (count < 0 ? " - error: " + LibUsb.errorName(count) : "")); + } - throw new SourceException("LibUsb couldn't discover USB device [" + mBus + ":" + mPort + - "] from device list" + (count < 0 ? " - error: " + LibUsb.errorName(count) : "")); + if(foundDevice == null) + { + throw new SourceException("LibUsb couldn't find the matching USB device"); + } + + return foundDevice; } /** @@ -249,7 +274,7 @@ public abstract class FCDTunerController extends TunerController if(status != LibUsb.SUCCESS) { - mLog.error("Unable to detach kernel driver for USB tuner device - bus:" + mBus + " port:" + mPort); + mLog.error("Unable to detach kernel driver for USB tuner device - bus:" + mBus + " port:" + mPortAddress); mDeviceHandle = null; mDeviceDescriptor = null; throw new SourceException("Can't detach kernel driver"); diff --git a/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerController.java b/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerController.java index 95cab56f..49bde78e 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerController.java @@ -56,12 +56,12 @@ public class FCD1TunerController extends FCDTunerController * Constructs an instance * @param mixerTDL for the audio/data interface * @param bus usb - * @param port usb + * @param portAddress usb * @param tunerErrorListener to receive tuner errors */ - public FCD1TunerController(TargetDataLine mixerTDL, int bus, int port, ITunerErrorListener tunerErrorListener) + public FCD1TunerController(TargetDataLine mixerTDL, int bus, String portAddress, ITunerErrorListener tunerErrorListener) { - super(MixerTunerType.FUNCUBE_DONGLE_PRO, mixerTDL, bus, port, MINIMUM_TUNABLE_FREQUENCY, + super(MixerTunerType.FUNCUBE_DONGLE_PRO, mixerTDL, bus, portAddress, MINIMUM_TUNABLE_FREQUENCY, MAXIMUM_TUNABLE_FREQUENCY, tunerErrorListener); } diff --git a/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerController.java b/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerController.java index 1a61ca29..2a705fc9 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerController.java @@ -48,12 +48,12 @@ public class FCD2TunerController extends FCDTunerController * Constructs an instance * @param mixerTDL for the sample stream * @param bus usb - * @param port usb + * @param portAddress usb * @param tunerErrorListener to receive errors from this tuner */ - public FCD2TunerController(TargetDataLine mixerTDL, int bus, int port, ITunerErrorListener tunerErrorListener) + public FCD2TunerController(TargetDataLine mixerTDL, int bus, String portAddress, ITunerErrorListener tunerErrorListener) { - super(MixerTunerType.FUNCUBE_DONGLE_PRO_PLUS, mixerTDL, bus, port, MINIMUM_TUNABLE_FREQUENCY, + super(MixerTunerType.FUNCUBE_DONGLE_PRO_PLUS, mixerTDL, bus, portAddress, MINIMUM_TUNABLE_FREQUENCY, MAXIMUM_TUNABLE_FREQUENCY, tunerErrorListener); } diff --git a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerController.java index 1e3d78b0..eaedae4f 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerController.java @@ -60,11 +60,11 @@ public class HackRFTunerController extends USBTunerController /** * Constructs an instance * @param bus usb - * @param port usb + * @param portAddress usb */ - public HackRFTunerController(int bus, int port, ITunerErrorListener tunerErrorListener) + public HackRFTunerController(int bus, String portAddress, ITunerErrorListener tunerErrorListener) { - super(bus, port, MINIMUM_TUNABLE_FREQUENCY, MAXIMUM_TUNABLE_FREQUENCY, DC_HALF_BANDWIDTH, USABLE_BANDWIDTH, + super(bus, portAddress, MINIMUM_TUNABLE_FREQUENCY, MAXIMUM_TUNABLE_FREQUENCY, DC_HALF_BANDWIDTH, USABLE_BANDWIDTH, tunerErrorListener); } diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/DiscoveredUSBTuner.java b/src/main/java/io/github/dsheirer/source/tuner/manager/DiscoveredUSBTuner.java index be3eafed..bf249830 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/manager/DiscoveredUSBTuner.java +++ b/src/main/java/io/github/dsheirer/source/tuner/manager/DiscoveredUSBTuner.java @@ -35,32 +35,32 @@ public class DiscoveredUSBTuner extends DiscoveredTuner private Logger mLog = LoggerFactory.getLogger(DiscoveredUSBTuner.class); private TunerClass mTunerClass; private int mBus; - private int mPort; + private String mPortAddress; private ChannelizerType mChannelizerType; /** * Constructs an instance * @param bus (USB) number - * @param port (USB) number + * @param portAddress (USB) * @param channelizerType to use with the tuner */ - public DiscoveredUSBTuner(TunerClass tunerClass, int bus, int port, ChannelizerType channelizerType) + public DiscoveredUSBTuner(TunerClass tunerClass, int bus, String portAddress, ChannelizerType channelizerType) { mTunerClass = tunerClass; mBus = bus; - mPort = port; + mPortAddress = portAddress; mChannelizerType = channelizerType; } /** * Indicates if this USB tuner is plugged into the specified bus and port. * @param bus number - * @param port number + * @param port address * @return true if there is a match */ - public boolean isAt(int bus, int port) + public boolean isAt(int bus, String port) { - return mBus == bus && mPort == port; + return mBus == bus && port != null && port.equalsIgnoreCase(mPortAddress); } /** @@ -82,9 +82,9 @@ public class DiscoveredUSBTuner extends DiscoveredTuner /** * USB port number */ - public int getPort() + public String getPortAddress() { - return mPort; + return mPortAddress; } @Override @@ -93,7 +93,7 @@ public class DiscoveredUSBTuner extends DiscoveredTuner StringBuilder sb = new StringBuilder(); sb.append(getTunerClass()); sb.append(" USB Bus:").append(getBus()); - sb.append(" Port:").append(getPort()); + sb.append(" Port:").append(getPortAddress()); return sb.toString(); } @@ -104,7 +104,7 @@ public class DiscoveredUSBTuner extends DiscoveredTuner { try { - mTuner = TunerFactory.getUsbTuner(getTunerClass(), getPort(), getBus(), this, mChannelizerType); + mTuner = TunerFactory.getUsbTuner(getTunerClass(), getPortAddress(), getBus(), this, mChannelizerType); mTuner.start(); } catch(SourceException se) diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/TunerManager.java b/src/main/java/io/github/dsheirer/source/tuner/manager/TunerManager.java index e17641f7..bb056b4c 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/manager/TunerManager.java +++ b/src/main/java/io/github/dsheirer/source/tuner/manager/TunerManager.java @@ -47,6 +47,7 @@ import org.usb4java.HotplugCallback; import org.usb4java.HotplugCallbackHandle; import org.usb4java.LibUsb; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -166,25 +167,33 @@ public class TunerManager implements IDiscoveredTunerStatusListener int bus = LibUsb.getBusNumber(device); int port = LibUsb.getPortNumber(device); - DeviceDescriptor deviceDescriptor = new DeviceDescriptor(); - int status = LibUsb.getDeviceDescriptor(device, deviceDescriptor); - - if(status == LibUsb.SUCCESS) + if(port > 0) { - TunerClass tunerClass = TunerClass.lookup(deviceDescriptor.idVendor(), deviceDescriptor.idProduct()); + DeviceDescriptor deviceDescriptor = new DeviceDescriptor(); + int status = LibUsb.getDeviceDescriptor(device, deviceDescriptor); - if(tunerClass.isSupportedUsbTuner()) + if(status == LibUsb.SUCCESS) { - mLog.info("Discovered tuner at USB Bus [" + bus + "] Port [" + port + "] Tuner Class [" + tunerClass + "]"); - ChannelizerType channelizerType = mUserPreferences.getTunerPreference().getChannelizerType(); - DiscoveredUSBTuner discoveredUSBTuner = new DiscoveredUSBTuner(tunerClass, bus, port, channelizerType); - discoveredUSBTuners.add(discoveredUSBTuner); + TunerClass tunerClass = TunerClass.lookup(deviceDescriptor.idVendor(), + deviceDescriptor.idProduct()); + + String portAddress = getPortAddress(device); + + if(tunerClass.isSupportedUsbTuner()) + { + mLog.info("Discovered tuner at USB Bus [" + bus + "] Port [" + portAddress + + "] Tuner Class [" + tunerClass + "]"); + ChannelizerType channelizerType = mUserPreferences.getTunerPreference().getChannelizerType(); + DiscoveredUSBTuner discoveredUSBTuner = new DiscoveredUSBTuner(tunerClass, bus, + portAddress, channelizerType); + discoveredUSBTuners.add(discoveredUSBTuner); + } + } + else + { + mLog.error("LibUsb - unable to get device descriptor for device on bus [" + bus + + "] port [" + port + "] - status [" + status + "] - " + LibUsb.errorName(status)); } - } - else - { - mLog.error("LibUsb - unable to get device descriptor for device on bus [" + bus + - "] port [" + port + "] - status [" + status + "] - " + LibUsb.errorName(status)); } //Unref the device - it will be rediscovered under the device context when it is started @@ -212,7 +221,7 @@ public class TunerManager implements IDiscoveredTunerStatusListener */ private void addUsbTuner(DiscoveredUSBTuner discoveredUSBTuner) { - if(!mDiscoveredTunerModel.hasUsbTuner(discoveredUSBTuner.getBus(), discoveredUSBTuner.getPort())) + if(!mDiscoveredTunerModel.hasUsbTuner(discoveredUSBTuner.getBus(), discoveredUSBTuner.getPortAddress())) { discoveredUSBTuner.addTunerStatusListener(this); @@ -251,11 +260,11 @@ public class TunerManager implements IDiscoveredTunerStatusListener /** * Stops and removes the USB tuner if it is currently discovered. * @param bus usb for the tuner - * @param port usb for the tuner + * @param portAddress usb for the tuner */ - private DiscoveredTuner removeUsbTuner(int bus, int port) + private DiscoveredTuner removeUsbTuner(int bus, String portAddress) { - return mDiscoveredTunerModel.removeUsbTuner(bus, port); + return mDiscoveredTunerModel.removeUsbTuner(bus, portAddress); } /** @@ -464,6 +473,33 @@ public class TunerManager implements IDiscoveredTunerStatusListener return source; } + /** + * Creates a dotted-notation string representing the port numbers for the device from the root hub through any + * intermediate hubs. + * @param device to inspect + * @return formatted address + */ + public static String getPortAddress(Device device) + { + ByteBuffer portNumberArray = ByteBuffer.allocateDirect(7); //7 ports maximum. + int portCount = LibUsb.getPortNumbers(device, portNumberArray); + portNumberArray.rewind(); + + StringBuilder sb = new StringBuilder(); + + for(int x = 0; x < portCount; x++) + { + if(x > 0) + { + sb.append("."); + } + + sb.append(portNumberArray.get()); + } + + return sb.toString(); + } + /** * USB hotplug event listener to register, unregister and detect when USB devices are added or removed. * @@ -489,47 +525,53 @@ public class TunerManager implements IDiscoveredTunerStatusListener int bus = LibUsb.getBusNumber(device); int port = LibUsb.getPortNumber(device); - switch(event) + if(port > 0) { - case LibUsb.HOTPLUG_EVENT_DEVICE_ARRIVED: - DeviceDescriptor deviceDescriptor = new DeviceDescriptor(); - int status = LibUsb.getDeviceDescriptor(device, deviceDescriptor); + String portAddress = getPortAddress(device); - if(status == LibUsb.SUCCESS) - { - TunerClass tunerClass = TunerClass.lookup(deviceDescriptor.idVendor(), deviceDescriptor.idProduct()); + switch(event) + { + case LibUsb.HOTPLUG_EVENT_DEVICE_ARRIVED: + DeviceDescriptor deviceDescriptor = new DeviceDescriptor(); + int status = LibUsb.getDeviceDescriptor(device, deviceDescriptor); - if(tunerClass.isSupportedUsbTuner()) + if(status == LibUsb.SUCCESS) { - mLog.info("Tuner plug-in detected at USB Bus [" + bus + "] Port [" + port + - "] Tuner Class [" + tunerClass + "]"); - ChannelizerType channelizerType = mUserPreferences.getTunerPreference().getChannelizerType(); - DiscoveredUSBTuner discoveredUSBTuner = new DiscoveredUSBTuner(tunerClass, bus, port, channelizerType); + TunerClass tunerClass = TunerClass.lookup(deviceDescriptor.idVendor(), deviceDescriptor.idProduct()); - if(tunerClass.isFuncubeTuner()) + if(tunerClass.isSupportedUsbTuner()) { - //Funcube tuners take a few moments to init the sound card interface. Delay adding - //the tuner so that it can be started correctly. - ThreadPool.SCHEDULED.schedule(() -> + mLog.info("Tuner plug-in detected at USB Bus [" + bus + "] Port [" + port + + "] Tuner Class [" + tunerClass + "]"); + ChannelizerType channelizerType = mUserPreferences.getTunerPreference().getChannelizerType(); + DiscoveredUSBTuner discoveredUSBTuner = new DiscoveredUSBTuner(tunerClass, bus, + portAddress, channelizerType); + + if(tunerClass.isFuncubeTuner()) + { + //Funcube tuners take a few moments to init the sound card interface. Delay adding + //the tuner so that it can be started correctly. + ThreadPool.SCHEDULED.schedule(() -> + { + addUsbTuner(discoveredUSBTuner); + }, 2, TimeUnit.SECONDS); + } + else { addUsbTuner(discoveredUSBTuner); - }, 2, TimeUnit.SECONDS); - } - else - { - addUsbTuner(discoveredUSBTuner); + } } } - } - break; - case LibUsb.HOTPLUG_EVENT_DEVICE_LEFT: - DiscoveredTuner removed = removeUsbTuner(bus, port); + break; + case LibUsb.HOTPLUG_EVENT_DEVICE_LEFT: + DiscoveredTuner removed = removeUsbTuner(bus, portAddress); - if(removed != null) - { - mLog.info("Tuner Unplugged: " + removed.getId()); - } - break; + if(removed != null) + { + mLog.info("Tuner Unplugged: " + removed.getId()); + } + break; + } } return HOTPLUG_CONTINUE_EVENT_SUPPORT; diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832TunerController.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832TunerController.java index 46b57569..65de47e5 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832TunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832TunerController.java @@ -73,9 +73,9 @@ public class RTL2832TunerController extends USBTunerController * to determine the tuner type, and construct the corresponding child * tuner controller class for that tuner type. */ - public RTL2832TunerController(int bus, int port, ITunerErrorListener tunerErrorListener) + public RTL2832TunerController(int bus, String portAddress, ITunerErrorListener tunerErrorListener) { - super(bus, port, tunerErrorListener); + super(bus, portAddress, tunerErrorListener); } /** diff --git a/src/main/java/io/github/dsheirer/source/tuner/ui/DiscoveredTunerModel.java b/src/main/java/io/github/dsheirer/source/tuner/ui/DiscoveredTunerModel.java index 7b942532..2ab1fa6f 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/ui/DiscoveredTunerModel.java +++ b/src/main/java/io/github/dsheirer/source/tuner/ui/DiscoveredTunerModel.java @@ -218,10 +218,10 @@ public class DiscoveredTunerModel extends AbstractTableModel implements Listener /** * Indicates if this model currently has the discovered tuner that is plugged into the specified bus and port. * @param bus number - * @param port number + * @param portAddress number * @return true if it already has the discovered device */ - public boolean hasUsbTuner(int bus, int port) + public boolean hasUsbTuner(int bus, String portAddress) { boolean hasDevice; mLock.lock(); @@ -229,7 +229,7 @@ public class DiscoveredTunerModel extends AbstractTableModel implements Listener try { hasDevice = mDiscoveredTuners.stream() - .filter(tuner -> tuner instanceof DiscoveredUSBTuner usbTuner && usbTuner.isAt(bus, port)) + .filter(tuner -> tuner instanceof DiscoveredUSBTuner usbTuner && usbTuner.isAt(bus, portAddress)) .findFirst() .isPresent(); } @@ -244,9 +244,9 @@ public class DiscoveredTunerModel extends AbstractTableModel implements Listener /** * Removes the USB tuner at bus and port number * @param bus usb - * @param port usb + * @param portAddress usb */ - public DiscoveredTuner removeUsbTuner(int bus, int port) + public DiscoveredTuner removeUsbTuner(int bus, String portAddress) { DiscoveredTuner removed = null; @@ -256,7 +256,7 @@ public class DiscoveredTunerModel extends AbstractTableModel implements Listener { DiscoveredTuner discoveredTuner = mDiscoveredTuners.stream() .filter(tuner -> tuner instanceof DiscoveredUSBTuner usbTuner && - usbTuner.isAt(bus, port)).findFirst().get(); + usbTuner.isAt(bus, portAddress)).findFirst().get(); if(discoveredTuner != null) { diff --git a/src/main/java/io/github/dsheirer/source/tuner/usb/USBTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/usb/USBTunerController.java index 6d8f53eb..76d57580 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/usb/USBTunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/usb/USBTunerController.java @@ -25,6 +25,7 @@ import io.github.dsheirer.source.SourceException; import io.github.dsheirer.source.tuner.ITunerErrorListener; import io.github.dsheirer.source.tuner.TunerController; import io.github.dsheirer.source.tuner.TunerType; +import io.github.dsheirer.source.tuner.manager.TunerManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.usb4java.Context; @@ -57,7 +58,7 @@ public abstract class USBTunerController extends TunerController private static final long USB_BULK_TRANSFER_TIMEOUT_MS = 2000l; private int mBus; - private int mPort; + private String mPortAddress; private Context mDeviceContext = new Context(); private Device mDevice; private DeviceHandle mDeviceHandle; @@ -73,30 +74,30 @@ public abstract class USBTunerController extends TunerController * or removed from this tuner controller. * * @param bus number USB - * @param port number USB + * @param portAddress address USB * @param tunerErrorListener to receive errors from this tuner controller */ - public USBTunerController(int bus, int port, ITunerErrorListener tunerErrorListener) + public USBTunerController(int bus, String portAddress, ITunerErrorListener tunerErrorListener) { super(tunerErrorListener); mBus = bus; - mPort = port; + mPortAddress = portAddress; } /** * Constructs an instance * @param bus usb - * @param port usb + * @param portAddress usb * @param minimum tunable frequency in Hertz * @param maximum tunable frequency in Hertz * @param halfBandwidth that is unusable for DC spike avoidance * @param usablePercent bandwith in Hertz * @param tunerErrorListener to receive errors from this tuner controller */ - public USBTunerController(int bus, int port, long minimum, long maximum, int halfBandwidth, double usablePercent, + public USBTunerController(int bus, String portAddress, long minimum, long maximum, int halfBandwidth, double usablePercent, ITunerErrorListener tunerErrorListener) { - this(bus, port, tunerErrorListener); + this(bus, portAddress, tunerErrorListener); setMinimumFrequency(minimum); setMaximumFrequency(maximum); setMiddleUnusableHalfBandwidth(halfBandwidth); @@ -159,7 +160,7 @@ public abstract class USBTunerController extends TunerController if(mDevice == null) { - throw new SourceException("Couldn't find USB device at bus [" + mBus + "] port [" + mPort + "]"); + throw new SourceException("Couldn't find USB device at bus [" + mBus + "] port [" + mPortAddress + "]"); } mDeviceDescriptor = new DeviceDescriptor(); @@ -204,7 +205,7 @@ public abstract class USBTunerController extends TunerController if(status != LibUsb.SUCCESS) { - mLog.error("Unable to detach kernel driver for USB tuner device - bus:" + mBus + " port:" + mPort); + mLog.error("Unable to detach kernel driver for USB tuner device - bus:" + mBus + " port:" + mPortAddress); mDeviceHandle = null; mDeviceDescriptor = null; throw new SourceException("Can't detach kernel driver"); @@ -351,9 +352,18 @@ public abstract class USBTunerController extends TunerController int bus = LibUsb.getBusNumber(device); int port = LibUsb.getPortNumber(device); - if(mBus == bus && mPort == port) + if(port > 0) { - foundDevice = device; + String portAddress = TunerManager.getPortAddress(device); + + if(mBus == bus && mPortAddress != null && mPortAddress.equals(portAddress)) + { + foundDevice = device; + } + else + { + LibUsb.unrefDevice(device); + } } else { @@ -370,7 +380,7 @@ public abstract class USBTunerController extends TunerController return foundDevice; } - throw new SourceException("LibUsb couldn't discover USB device [" + mBus + ":" + mPort + + throw new SourceException("LibUsb couldn't discover USB device [" + mBus + ":" + mPortAddress + "] from device list" + (count < 0 ? " - error: " + LibUsb.errorName(count) : "")); } @@ -653,7 +663,7 @@ public abstract class USBTunerController extends TunerController { mProcessing = true; mThread = new Thread(this); - mThread.setName("sdrtrunk USB tuner - bus [" + mBus + "] port [" + mPort + "]"); + mThread.setName("sdrtrunk USB tuner - bus [" + mBus + "] port [" + mPortAddress + "]"); mThread.setPriority(Thread.MAX_PRIORITY); mThread.start(); }