mirror of
https://github.com/smittix/intercept.git
synced 2026-06-08 14:11:54 -07:00
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:
@@ -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
|
||||
})
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user