Add DVB driver conflict detection and auto-fix feature

- Add /settings/rtlsdr/driver-status endpoint to check for loaded DVB modules
- Add /settings/rtlsdr/blacklist-drivers endpoint to unload modules and create blacklist
- Show warning banner on dashboard when DVB conflict detected
- Provide "Fix Now" button to automatically resolve the issue
- Warn users that their RTL-SDR devices may not work until drivers are blacklisted

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Smittix
2026-01-15 17:06:18 +00:00
parent 459bf2d8cd
commit 97d5ec6b33
2 changed files with 226 additions and 0 deletions
+124
View File
@@ -2,6 +2,10 @@
from __future__ import annotations
import os
import subprocess
import sys
from flask import Blueprint, jsonify, request, Response
from utils.database import (
@@ -164,3 +168,123 @@ def get_device_correlations() -> Response:
'status': 'error',
'message': str(e)
}), 500
# =============================================================================
# RTL-SDR DVB Driver Management
# =============================================================================
DVB_MODULES = ['dvb_usb_rtl28xxu', 'rtl2832_sdr', 'rtl2832', 'rtl2830', 'r820t']
BLACKLIST_FILE = '/etc/modprobe.d/blacklist-rtlsdr.conf'
@settings_bp.route('/rtlsdr/driver-status', methods=['GET'])
def check_dvb_driver_status() -> Response:
"""Check if DVB kernel drivers are loaded and blocking RTL-SDR devices."""
if sys.platform != 'linux':
return jsonify({
'status': 'success',
'platform': sys.platform,
'issue_detected': False,
'message': 'DVB driver conflict only affects Linux systems'
})
# Check which DVB modules are currently loaded
loaded_modules = []
try:
result = subprocess.run(['lsmod'], capture_output=True, text=True, timeout=5)
lsmod_output = result.stdout
for mod in DVB_MODULES:
if mod in lsmod_output:
loaded_modules.append(mod)
except Exception as e:
logger.warning(f"Could not check loaded modules: {e}")
# Check if blacklist file exists
blacklist_exists = os.path.exists(BLACKLIST_FILE)
# Check blacklist file contents
blacklist_contents = []
if blacklist_exists:
try:
with open(BLACKLIST_FILE, 'r') as f:
blacklist_contents = [line.strip() for line in f if line.strip() and not line.startswith('#')]
except Exception:
pass
issue_detected = len(loaded_modules) > 0
return jsonify({
'status': 'success',
'platform': 'linux',
'issue_detected': issue_detected,
'loaded_modules': loaded_modules,
'blacklist_file_exists': blacklist_exists,
'blacklist_contents': blacklist_contents,
'message': 'DVB drivers are claiming RTL-SDR devices' if issue_detected else 'No DVB driver conflict detected'
})
@settings_bp.route('/rtlsdr/blacklist-drivers', methods=['POST'])
def blacklist_dvb_drivers() -> Response:
"""Blacklist DVB kernel drivers to prevent them from claiming RTL-SDR devices."""
if sys.platform != 'linux':
return jsonify({
'status': 'error',
'message': 'This feature is only available on Linux'
}), 400
# Check if we have permission (need to be running as root or with sudo)
if os.geteuid() != 0:
return jsonify({
'status': 'error',
'message': 'Root privileges required. Run the app with sudo or manually run: sudo modprobe -r dvb_usb_rtl28xxu rtl2832_sdr rtl2832 r820t'
}), 403
errors = []
successes = []
# Create blacklist file if it doesn't exist
if not os.path.exists(BLACKLIST_FILE):
try:
blacklist_content = """# RTL-SDR blacklist - prevents DVB drivers from claiming RTL-SDR devices
# Created by INTERCEPT
blacklist dvb_usb_rtl28xxu
blacklist rtl2832
blacklist rtl2830
blacklist r820t
"""
with open(BLACKLIST_FILE, 'w') as f:
f.write(blacklist_content)
successes.append(f'Created {BLACKLIST_FILE}')
except Exception as e:
errors.append(f'Failed to create blacklist file: {e}')
# Unload the modules
for mod in DVB_MODULES:
try:
result = subprocess.run(
['modprobe', '-r', mod],
capture_output=True,
text=True,
timeout=10
)
if result.returncode == 0:
successes.append(f'Unloaded module: {mod}')
# returncode != 0 is OK - module might not be loaded
except Exception as e:
logger.warning(f"Could not unload {mod}: {e}")
if errors:
return jsonify({
'status': 'partial',
'message': 'Some operations failed. Please unplug and replug your RTL-SDR device.',
'successes': successes,
'errors': errors
})
return jsonify({
'status': 'success',
'message': 'DVB drivers blacklisted. Please unplug and replug your RTL-SDR device.',
'successes': successes
})
+102
View File
@@ -1920,6 +1920,7 @@ ACARS: ${r.statistics.acarsMessages} messages`;
setInterval(cleanupOldAircraft, 10000);
checkAdsbTools();
checkAircraftDatabase();
checkDvbDriverConflict();
// Auto-connect to gpsd if available
autoConnectGps();
@@ -1990,6 +1991,107 @@ ACARS: ${r.statistics.acarsMessages} messages`;
});
}
function checkDvbDriverConflict() {
fetch('/settings/rtlsdr/driver-status')
.then(r => r.json())
.then(data => {
if (data.issue_detected) {
showDvbDriverWarning(data.loaded_modules);
}
})
.catch(() => {});
}
function showDvbDriverWarning(loadedModules) {
// Don't show if already dismissed this session
if (sessionStorage.getItem('dvb_warning_dismissed')) return;
const warning = document.createElement('div');
warning.id = 'dvbDriverWarning';
warning.style.cssText = `
position: fixed;
top: 70px;
left: 50%;
transform: translateX(-50%);
background: rgba(239, 68, 68, 0.95);
color: white;
padding: 15px 20px;
border-radius: 8px;
font-size: 13px;
z-index: 10000;
box-shadow: 0 4px 20px rgba(0,0,0,0.5);
max-width: 500px;
text-align: center;
`;
warning.innerHTML = `
<div style="font-weight: bold; margin-bottom: 8px;">⚠️ DVB Driver Conflict Detected</div>
<div style="margin-bottom: 10px;">
Kernel DVB drivers are claiming your RTL-SDR devices, preventing them from working properly.
<br><small>Loaded modules: ${loadedModules.join(', ')}</small>
</div>
<div style="display: flex; gap: 10px; justify-content: center;">
<button onclick="fixDvbDrivers()" style="background: white; color: #dc2626; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer; font-weight: bold;">
Fix Now
</button>
<button onclick="dismissDvbWarning()" style="background: rgba(255,255,255,0.2); color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer;">
Dismiss
</button>
</div>
`;
document.body.appendChild(warning);
}
function fixDvbDrivers() {
const warning = document.getElementById('dvbDriverWarning');
if (warning) {
warning.innerHTML = '<div>Applying fix...</div>';
}
fetch('/settings/rtlsdr/blacklist-drivers', { method: 'POST' })
.then(r => r.json())
.then(data => {
if (data.status === 'success' || data.status === 'partial') {
if (warning) {
warning.style.background = 'rgba(34, 197, 94, 0.95)';
warning.innerHTML = `
<div style="font-weight: bold;">✓ DVB Drivers Disabled</div>
<div style="margin-top: 8px;">${data.message}</div>
<button onclick="this.parentElement.remove()" style="margin-top: 10px; background: white; color: #16a34a; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer;">
OK
</button>
`;
}
} else {
if (warning) {
warning.innerHTML = `
<div style="font-weight: bold;">Manual Fix Required</div>
<div style="margin-top: 8px;">${data.message}</div>
<button onclick="this.parentElement.remove()" style="margin-top: 10px; background: rgba(255,255,255,0.2); color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer;">
Close
</button>
`;
}
}
})
.catch(err => {
if (warning) {
warning.innerHTML = `
<div>Error: ${err.message}</div>
<button onclick="this.parentElement.remove()" style="margin-top: 10px; background: rgba(255,255,255,0.2); color: white; border: none; padding: 8px 16px; border-radius: 4px; cursor: pointer;">
Close
</button>
`;
}
});
}
function dismissDvbWarning() {
sessionStorage.setItem('dvb_warning_dismissed', 'true');
const warning = document.getElementById('dvbDriverWarning');
if (warning) warning.remove();
}
function checkAdsbTools() {
fetch('/adsb/tools')
.then(r => r.json())