From 4c34968d287faba1d29e81244e30828cc80c2b88 Mon Sep 17 00:00:00 2001 From: Denny Sheirer Date: Sun, 9 Feb 2020 10:51:55 -0500 Subject: [PATCH] #654 Warn users when USB bus speeds are exceeded. (#655) Updates logging to track max usb speeds per bus and warns user when any USB bus combined tuner data rates exceeds 70% of the max bus rate. --- .../github/dsheirer/source/tuner/Tuner.java | 6 + .../dsheirer/source/tuner/TunerManager.java | 149 +++++++++++++++--- .../source/tuner/airspy/AirspyTuner.java | 39 +++-- .../dsheirer/source/tuner/fcd/FCDTuner.java | 36 +++-- .../source/tuner/hackrf/HackRFTuner.java | 37 +++-- .../tuner/recording/RecordingTuner.java | 6 + .../source/tuner/rtl/RTL2832Tuner.java | 37 +++-- .../dsheirer/source/tuner/test/TestTuner.java | 36 +++-- 8 files changed, 256 insertions(+), 90 deletions(-) diff --git a/src/main/java/io/github/dsheirer/source/tuner/Tuner.java b/src/main/java/io/github/dsheirer/source/tuner/Tuner.java index 56b44997..d2f5cc92 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/Tuner.java +++ b/src/main/java/io/github/dsheirer/source/tuner/Tuner.java @@ -109,6 +109,12 @@ public abstract class Tuner implements ISourceEventProcessor, ITunerErrorListene getChannelSourceManager().setErrorMessage(errorMessage); } + /** + * Maximum number of bytes per second (MBps) produced by this tuner. + * @return Bytes Per Second (Bps) + */ + public abstract int getMaximumUSBBitsPerSecond(); + /** * Optional error message that describes an error state. */ diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerManager.java b/src/main/java/io/github/dsheirer/source/tuner/TunerManager.java index 4a749520..4be42fa5 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/TunerManager.java +++ b/src/main/java/io/github/dsheirer/source/tuner/TunerManager.java @@ -1,21 +1,23 @@ /* - * ****************************************************************************** - * sdrtrunk - * Copyright (C) 2014-2018 Dennis Sheirer * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * * ****************************************************************************** + * * Copyright (C) 2014-2020 Dennis Sheirer + * * + * * This program is free software: you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation, either version 3 of the License, or + * * (at your option) any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program. If not, see + * * ***************************************************************************** * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * ***************************************************************************** */ package io.github.dsheirer.source.tuner; @@ -41,15 +43,22 @@ import org.usb4java.DeviceDescriptor; import org.usb4java.DeviceList; import org.usb4java.LibUsb; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; public class TunerManager { private final static Logger mLog = LoggerFactory.getLogger(TunerManager.class); + private static final int MAXIMUM_USB_2_DATA_RATE = 480000000; private MixerManager mMixerManager; private TunerModel mTunerModel; private UserPreferences mUserPreferences; + private Map> mUSBBusTunerMap = new TreeMap<>(); /** * Application-wide LibUSB timeout processor for transfer buffers. All classes that need to use USB transfer @@ -70,6 +79,7 @@ public class TunerManager mUserPreferences = userPreferences; initTuners(); + validateUSBBusTransferRates(); } /** @@ -141,10 +151,13 @@ public class TunerManager StringBuilder sb = new StringBuilder(); - sb.append("usb device ["); + int bus = LibUsb.getBusNumber(device); + sb.append("USB Bus [").append(bus).append("]"); + sb.append(" Device ["); sb.append(String.format("%04X", descriptor.idVendor())); sb.append(":"); sb.append(String.format("%04X", descriptor.idProduct())); + sb.append("]"); if(status.isLoaded()) { @@ -153,20 +166,21 @@ public class TunerManager try { mTunerModel.addTuner(tuner); - sb.append("] LOADED: "); + sb.append(" LOADED: "); sb.append(tuner.toString()); + sb.append(" Max Rate:").append(tuner.getMaximumUSBBitsPerSecond()).append(" bps"); + updateUSBBusTunerMap(bus, tuner); } catch(Exception e) { - sb.append("] NOT LOADED: "); + sb.append(" NOT LOADED: "); sb.append(status.getInfo()); sb.append(" Error:" + e.getMessage()); } } else { - sb.append("] NOT LOADED: "); - sb.append(status.getInfo()); + sb.append(" ").append(getDeviceClass(descriptor.bDeviceClass())); } mLog.info(sb.toString()); @@ -176,6 +190,103 @@ public class TunerManager LibUsb.freeDeviceList(deviceList, true); } + private static String getDeviceClass(byte deviceClass) + { + switch(deviceClass) + { + case 0: + return "Unknown Device - Class 0"; + case 2: + return "Communications Device"; + case 3: + return "HID Device"; + case 5: + return "Physical Device"; + case 6: + return "Still Imaging Device"; + case 7: + return "Printer Device"; + case 8: + return "Mass Storage Device"; + case 9: + return "Hub Device"; + case 0xA: + return "Communications Device"; + case 0xB: + return "Smart Card Device"; + case 0xD: + return "Content Security Device"; + case 0xE: + return "Video Device"; + case 0xF: + return "Personal Healthcare Device"; + case 0x10: + return "Audio/Video Device"; + case (byte)0xDC: + return "Diagnostic Device"; + case (byte)0xE0: + return "Wireless Controller Device"; + case (byte)0xEF: + return "Miscellaneous Device"; + default: + return "Unknown Device - Class " + deviceClass; + } + } + + private void updateUSBBusTunerMap(int bus, Tuner tuner) + { + if(mUSBBusTunerMap.containsKey(bus)) + { + mUSBBusTunerMap.get(bus).add(tuner); + } + else + { + List tuners = new ArrayList<>(); + tuners.add(tuner); + mUSBBusTunerMap.put(bus, tuners); + } + } + + private void validateUSBBusTransferRates() + { + mLog.info("-------------------------------------------------------------"); + mLog.info("USB Bus - Potential Maximum Data Rates"); + + boolean warning = false; + + List buses = new ArrayList(mUSBBusTunerMap.keySet()); + Collections.sort(buses); + for(Integer bus: buses) + { + int totalBPS = 0; + + for(Tuner tuner: mUSBBusTunerMap.get(bus)) + { + totalBPS += tuner.getMaximumUSBBitsPerSecond(); + } + + if(totalBPS > (MAXIMUM_USB_2_DATA_RATE * .7)) + { + warning = true; + } + + mLog.info("USB Bus [" + bus + "] Rate [" + totalBPS + "] bits per second" + (warning ? " *** WARNING ***" : "")); + } + + if(warning) + { + StringBuilder sb = new StringBuilder(); + sb.append( + "\n\t\t******************************************************************************************************\n" + + "\t\t* WARNING: the combined data rates of tuner(s) on USB bus(es) above can potentially saturate or exceed\n" + + "\t\t* the maximum USB 2.0 data rate of 480 Mbps. This can cause data loss and severely impact decoding\n" + + "\t\t* performance resulting in missed calls and stuttering audio. Recommend moving tuner(s) to other\n" + + "\t\t* USB ports/buses to better balance data rates across available USB buses.\n" + + "\t\t******************************************************************************************************"); + mLog.warn(sb.toString()); + } + } + private TunerInitStatus initTuner(Device device, DeviceDescriptor descriptor) { diff --git a/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTuner.java b/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTuner.java index dfb6975d..7a980910 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTuner.java +++ b/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTuner.java @@ -1,21 +1,23 @@ /* - * ****************************************************************************** - * sdrtrunk - * Copyright (C) 2014-2018 Dennis Sheirer * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * * ****************************************************************************** + * * Copyright (C) 2014-2020 Dennis Sheirer + * * + * * This program is free software: you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation, either version 3 of the License, or + * * (at your option) any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program. If not, see + * * ***************************************************************************** * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * ***************************************************************************** */ package io.github.dsheirer.source.tuner.airspy; @@ -73,4 +75,11 @@ public class AirspyTuner extends Tuner { return 13.0; } -} \ No newline at end of file + + @Override + public int getMaximumUSBBitsPerSecond() + { + //4-bytes per sample = 32 bits times 10 MSps = 320,000,000 bits per second + return 320000000; + } +} diff --git a/src/main/java/io/github/dsheirer/source/tuner/fcd/FCDTuner.java b/src/main/java/io/github/dsheirer/source/tuner/fcd/FCDTuner.java index 54bf824a..2172e215 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/fcd/FCDTuner.java +++ b/src/main/java/io/github/dsheirer/source/tuner/fcd/FCDTuner.java @@ -1,21 +1,23 @@ /* - * ****************************************************************************** - * sdrtrunk - * Copyright (C) 2014-2018 Dennis Sheirer * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * * ****************************************************************************** + * * Copyright (C) 2014-2020 Dennis Sheirer + * * + * * This program is free software: you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation, either version 3 of the License, or + * * (at your option) any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program. If not, see + * * ***************************************************************************** * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * ***************************************************************************** */ package io.github.dsheirer.source.tuner.fcd; @@ -64,4 +66,10 @@ public class FCDTuner extends Tuner { return 16.0; } + + @Override + public int getMaximumUSBBitsPerSecond() + { + return (int)getController().getCurrentSampleRate() * 32; + } } diff --git a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTuner.java b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTuner.java index c587bafb..224cbcbe 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTuner.java +++ b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTuner.java @@ -1,21 +1,23 @@ /* - * ****************************************************************************** - * sdrtrunk - * Copyright (C) 2014-2018 Dennis Sheirer * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * * ****************************************************************************** + * * Copyright (C) 2014-2020 Dennis Sheirer + * * + * * This program is free software: you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation, either version 3 of the License, or + * * (at your option) any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program. If not, see + * * ***************************************************************************** * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * ***************************************************************************** */ package io.github.dsheirer.source.tuner.hackrf; @@ -74,4 +76,11 @@ public class HackRFTuner extends Tuner return BoardID.HACKRF_ONE.getLabel(); } + + @Override + public int getMaximumUSBBitsPerSecond() + { + //16 bits per sample * 20 MSPS + return 320000000; + } } \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTuner.java b/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTuner.java index e521d701..55a2038a 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTuner.java +++ b/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTuner.java @@ -136,4 +136,10 @@ public class RecordingTuner extends Tuner } } } + + @Override + public int getMaximumUSBBitsPerSecond() + { + return 0; + } } diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832Tuner.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832Tuner.java index a1de2b63..11baee44 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832Tuner.java +++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832Tuner.java @@ -1,21 +1,23 @@ /* - * ****************************************************************************** - * sdrtrunk - * Copyright (C) 2014-2018 Dennis Sheirer * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * * ****************************************************************************** + * * Copyright (C) 2014-2020 Dennis Sheirer + * * + * * This program is free software: you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation, either version 3 of the License, or + * * (at your option) any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program. If not, see + * * ***************************************************************************** * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * ***************************************************************************** */ package io.github.dsheirer.source.tuner.rtl; @@ -72,4 +74,11 @@ public class RTL2832Tuner extends Tuner //actual noise floor. return 11.0; } + + @Override + public int getMaximumUSBBitsPerSecond() + { + //16 bits per sample * 2.4 MSPS + return 38400000; + } } \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/source/tuner/test/TestTuner.java b/src/main/java/io/github/dsheirer/source/tuner/test/TestTuner.java index 5b3d899b..93d215a3 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/test/TestTuner.java +++ b/src/main/java/io/github/dsheirer/source/tuner/test/TestTuner.java @@ -1,21 +1,23 @@ /* - * ****************************************************************************** - * sdrtrunk - * Copyright (C) 2014-2018 Dennis Sheirer * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * * ****************************************************************************** + * * Copyright (C) 2014-2020 Dennis Sheirer + * * + * * This program is free software: you can redistribute it and/or modify + * * it under the terms of the GNU General Public License as published by + * * the Free Software Foundation, either version 3 of the License, or + * * (at your option) any later version. + * * + * * This program is distributed in the hope that it will be useful, + * * but WITHOUT ANY WARRANTY; without even the implied warranty of + * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * * GNU General Public License for more details. + * * + * * You should have received a copy of the GNU General Public License + * * along with this program. If not, see + * * ***************************************************************************** * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * ***************************************************************************** */ package io.github.dsheirer.source.tuner.test; @@ -72,4 +74,10 @@ public class TestTuner extends Tuner { return 16.0; } + + @Override + public int getMaximumUSBBitsPerSecond() + { + return 0; + } }