Initial release: Driver Manager KernelSU module v1.0.0
Manage GPU, WiFi, Bluetooth, SDR, and game controller drivers. Supports PowerVR mode switching, BCM4390/Nexmon WiFi modes, RTL-SDR/HackRF/Airspy with DVB-T/SDR mode toggle, Xbox/PS5/ Switch Pro controllers, and QCA Bluetooth pentest mode. WebUI control panel for KernelSU manager.
This commit is contained in:
18
build.sh
Executable file
18
build.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
ZIP="driver-manager-v1.0.0.zip"
|
||||
rm -f "$ZIP"
|
||||
|
||||
zip -r9 "$ZIP" \
|
||||
module.prop \
|
||||
customize.sh \
|
||||
post-fs-data.sh \
|
||||
service.sh \
|
||||
system.prop \
|
||||
system/ \
|
||||
webroot/ \
|
||||
-x "*.git*" "build.sh" "tools/*" "README*"
|
||||
|
||||
echo "Built: $ZIP ($(du -h "$ZIP" | cut -f1))"
|
||||
85
customize.sh
Normal file
85
customize.sh
Normal file
@@ -0,0 +1,85 @@
|
||||
#!/system/bin/sh
|
||||
# Driver Manager - Installation Script
|
||||
|
||||
SKIPUNZIP=0
|
||||
|
||||
ui_print "================================================"
|
||||
ui_print " Driver Manager v1.0.0"
|
||||
ui_print "================================================"
|
||||
ui_print ""
|
||||
|
||||
DEVICE=$(getprop ro.product.device)
|
||||
MODEL=$(getprop ro.product.model)
|
||||
SOC=$(getprop ro.soc.model)
|
||||
PLATFORM=$(getprop ro.board.platform)
|
||||
GPU=$(getprop ro.hardware.egl)
|
||||
API=$(getprop ro.build.version.sdk)
|
||||
|
||||
ui_print "- Device: $MODEL ($DEVICE)"
|
||||
ui_print "- SoC: $SOC ($PLATFORM)"
|
||||
ui_print "- GPU: $GPU"
|
||||
ui_print "- API: $API"
|
||||
ui_print ""
|
||||
|
||||
# Detect WiFi chip
|
||||
WIFI_MOD=$(ls /sys/module/ 2>/dev/null | grep -iE "^bcmdhd" | head -1)
|
||||
ui_print "- WiFi module: ${WIFI_MOD:-unknown}"
|
||||
|
||||
# Detect Bluetooth
|
||||
BT_MOD=$(ls /sys/module/ 2>/dev/null | grep -iE "^(btqca|btusb|btbcm|hci)" | head -1)
|
||||
ui_print "- BT module: ${BT_MOD:-unknown}"
|
||||
|
||||
ui_print ""
|
||||
|
||||
# Create default config
|
||||
mkdir -p "$MODPATH/config"
|
||||
echo "performance" > "$MODPATH/config/gpu_mode"
|
||||
echo "standard" > "$MODPATH/config/wifi_mode"
|
||||
echo "standard" > "$MODPATH/config/bt_mode"
|
||||
echo "sdr" > "$MODPATH/config/sdr_mode"
|
||||
echo "auto" > "$MODPATH/config/gamepad_mode"
|
||||
echo "off" > "$MODPATH/config/decoder_mode"
|
||||
echo "100.0M" > "$MODPATH/config/fm_freq"
|
||||
echo "24M:1800M" > "$MODPATH/config/spectrum_range"
|
||||
|
||||
# Create modules directory for .ko files
|
||||
mkdir -p "$MODPATH/modules"
|
||||
mkdir -p "$MODPATH/firmware"
|
||||
|
||||
ui_print "- Default config written"
|
||||
ui_print "- Kernel module dir: modules/"
|
||||
ui_print "- Firmware dir: firmware/"
|
||||
ui_print ""
|
||||
|
||||
# Check for kernel module support
|
||||
if [ -d "/proc/modules" ]; then
|
||||
ui_print "- Kernel module loading: supported"
|
||||
else
|
||||
ui_print "! Kernel module loading: not detected"
|
||||
ui_print "! SDR and controller .ko files may not load"
|
||||
fi
|
||||
|
||||
# Check USB OTG
|
||||
if [ -d "/sys/class/udc" ]; then
|
||||
ui_print "- USB OTG: supported"
|
||||
else
|
||||
ui_print "! USB OTG: not detected"
|
||||
fi
|
||||
|
||||
ui_print ""
|
||||
ui_print "- Setting permissions..."
|
||||
|
||||
set_perm_recursive $MODPATH 0 0 0755 0644
|
||||
set_perm $MODPATH/post-fs-data.sh 0 0 0755
|
||||
set_perm $MODPATH/service.sh 0 0 0755
|
||||
set_perm_recursive $MODPATH/config 0 0 0755 0644
|
||||
set_perm_recursive $MODPATH/modules 0 0 0755 0644
|
||||
set_perm_recursive $MODPATH/firmware 0 0 0755 0644
|
||||
set_perm_recursive $MODPATH/system/etc 0 0 0755 0644
|
||||
|
||||
ui_print ""
|
||||
ui_print "- Installation complete!"
|
||||
ui_print "- Use WebUI in KernelSU to switch driver modes"
|
||||
ui_print "- Place .ko modules in modules/ dir"
|
||||
ui_print "- Place firmware in firmware/ dir"
|
||||
ui_print ""
|
||||
6
module.prop
Normal file
6
module.prop
Normal file
@@ -0,0 +1,6 @@
|
||||
id=driver-manager
|
||||
name=Driver Manager
|
||||
version=v1.0.0
|
||||
versionCode=1
|
||||
author=sssnake
|
||||
description=Manage GPU, WiFi, Bluetooth, SDR, and game controller drivers. Supports PowerVR, BCM4390/Nexmon, RTL-SDR, HackRF, Airspy, and more.
|
||||
17
post-fs-data.sh
Executable file
17
post-fs-data.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/system/bin/sh
|
||||
# Driver Manager - post-fs-data
|
||||
# Early boot: set core driver properties before services start
|
||||
|
||||
MODDIR=${0%/*}
|
||||
|
||||
# GPU — PowerVR latest driver hints
|
||||
resetprop ro.hardware.egl powervr
|
||||
resetprop ro.hardware.vulkan powervr
|
||||
resetprop graphics.gpu.profiler.support true
|
||||
|
||||
# OpenCL compute
|
||||
resetprop vendor.powervr.opencl.allowfp16 1
|
||||
resetprop vendor.powervr.opencl.profiling 1
|
||||
|
||||
# USB OTG — required for SDR dongles, HackRF, game controllers
|
||||
resetprop persist.sys.usb.otg 1
|
||||
302
service.sh
Executable file
302
service.sh
Executable file
@@ -0,0 +1,302 @@
|
||||
#!/system/bin/sh
|
||||
# Driver Manager - late service
|
||||
# Manages GPU, WiFi, Bluetooth, SDR, and game controller drivers
|
||||
|
||||
MODDIR=${0%/*}
|
||||
LOGFILE="$MODDIR/driver-manager.log"
|
||||
CONFDIR="$MODDIR/config"
|
||||
|
||||
mkdir -p "$CONFDIR"
|
||||
|
||||
mlog() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOGFILE"
|
||||
log -t DriverManager "$1"
|
||||
}
|
||||
|
||||
echo "" > "$LOGFILE"
|
||||
mlog "Waiting for boot..."
|
||||
|
||||
while [ "$(getprop sys.boot_completed)" != "1" ]; do
|
||||
sleep 1
|
||||
done
|
||||
sleep 3
|
||||
|
||||
DEVICE=$(getprop ro.product.device)
|
||||
SOC=$(getprop ro.soc.model)
|
||||
PLATFORM=$(getprop ro.board.platform)
|
||||
API=$(getprop ro.build.version.sdk)
|
||||
GPU=$(getprop ro.hardware.egl)
|
||||
|
||||
mlog "Boot complete. Device=$DEVICE SoC=$SOC Platform=$PLATFORM API=$API GPU=$GPU"
|
||||
|
||||
# ============================================================
|
||||
# GPU DRIVER MANAGEMENT — PowerVR DXT-48-1536
|
||||
# ============================================================
|
||||
# Tensor G5 shipped with outdated v24.3 drivers
|
||||
# v25.1+ adds Vulkan 1.4, better thermal efficiency
|
||||
# Driver files live in /vendor/lib64/egl/ and /vendor/firmware/
|
||||
|
||||
GPU_MODE=$(cat "$CONFDIR/gpu_mode" 2>/dev/null || echo "performance")
|
||||
|
||||
case "$GPU_MODE" in
|
||||
performance)
|
||||
# Max GPU clock, prefer quality
|
||||
resetprop vendor.powervr.gpu.freq_hint max
|
||||
resetprop debug.hwui.renderer skiagl
|
||||
resetprop debug.renderengine.backend skiavk
|
||||
resetprop debug.hwui.use_hint_manager true
|
||||
mlog "GPU mode: performance (Vulkan renderer, max freq)"
|
||||
;;
|
||||
balanced)
|
||||
resetprop vendor.powervr.gpu.freq_hint auto
|
||||
resetprop debug.hwui.renderer skiagl
|
||||
resetprop debug.renderengine.backend skiaglthreaded
|
||||
mlog "GPU mode: balanced"
|
||||
;;
|
||||
powersave)
|
||||
resetprop vendor.powervr.gpu.freq_hint min
|
||||
resetprop debug.hwui.renderer skiagl
|
||||
resetprop debug.renderengine.backend skiagl
|
||||
mlog "GPU mode: powersave"
|
||||
;;
|
||||
compute)
|
||||
# Optimized for OpenCL workloads
|
||||
resetprop vendor.powervr.opencl.allowfp16 1
|
||||
resetprop vendor.powervr.opencl.profiling 1
|
||||
resetprop vendor.powervr.gpu.freq_hint max
|
||||
mlog "GPU mode: compute (OpenCL optimized)"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Force Vulkan 1.4 feature level if driver supports it
|
||||
resetprop ro.gfx.driver.1 com.google.pixel.powervr.gfxdriver
|
||||
mlog "GPU: PowerVR DXT-48-1536, Vulkan 1.4, OpenGL ES 3.x, OpenCL 3.0"
|
||||
|
||||
# ============================================================
|
||||
# WIFI DRIVER MANAGEMENT — BCM4390 (bcmdhd4390)
|
||||
# ============================================================
|
||||
# Modes: standard, monitor, injection (nexmon), mesh
|
||||
|
||||
WIFI_MODE=$(cat "$CONFDIR/wifi_mode" 2>/dev/null || echo "standard")
|
||||
|
||||
case "$WIFI_MODE" in
|
||||
standard)
|
||||
# Normal operation
|
||||
resetprop wifi.direct.interface p2p-dev-wlan0
|
||||
mlog "WiFi mode: standard"
|
||||
;;
|
||||
monitor)
|
||||
# Enable monitor mode on BCM4390
|
||||
# Requires nexmon-patched firmware or native support
|
||||
if [ -f "$MODDIR/firmware/fw_bcm4390_monitor.bin" ]; then
|
||||
cp "$MODDIR/firmware/fw_bcm4390_monitor.bin" /vendor/firmware/fw_bcmdhd4390.bin
|
||||
mlog "WiFi mode: monitor (nexmon firmware loaded)"
|
||||
else
|
||||
# Try native monitor via iw/ip
|
||||
mlog "WiFi mode: monitor (native, nexmon firmware not found)"
|
||||
fi
|
||||
;;
|
||||
injection)
|
||||
# Frame injection — requires nexmon patches for BCM4390
|
||||
if [ -f "$MODDIR/firmware/fw_bcm4390_injection.bin" ]; then
|
||||
cp "$MODDIR/firmware/fw_bcm4390_injection.bin" /vendor/firmware/fw_bcmdhd4390.bin
|
||||
mlog "WiFi mode: injection (nexmon firmware loaded)"
|
||||
else
|
||||
mlog "WiFi mode: injection requested but no nexmon firmware"
|
||||
fi
|
||||
;;
|
||||
mesh)
|
||||
# 802.11s mesh networking
|
||||
resetprop wifi.interface wlan0
|
||||
mlog "WiFi mode: mesh (802.11s)"
|
||||
;;
|
||||
esac
|
||||
|
||||
# ============================================================
|
||||
# BLUETOOTH DRIVER MANAGEMENT — QCA (btqca)
|
||||
# ============================================================
|
||||
|
||||
BT_MODE=$(cat "$CONFDIR/bt_mode" 2>/dev/null || echo "standard")
|
||||
|
||||
case "$BT_MODE" in
|
||||
standard)
|
||||
resetprop bluetooth.profile.a2dp.source.enabled true
|
||||
resetprop bluetooth.profile.hfp.ag.enabled true
|
||||
resetprop bluetooth.profile.hid.host.enabled true
|
||||
resetprop bluetooth.profile.pan.nap.enabled true
|
||||
mlog "BT mode: standard"
|
||||
;;
|
||||
pentest)
|
||||
# Enable all profiles + raw HCI access for BLE scanning/exploitation
|
||||
resetprop bluetooth.profile.a2dp.source.enabled true
|
||||
resetprop bluetooth.profile.hfp.ag.enabled true
|
||||
resetprop bluetooth.profile.hid.host.enabled true
|
||||
resetprop bluetooth.profile.hid.device.enabled true
|
||||
resetprop bluetooth.profile.pan.nap.enabled true
|
||||
resetprop bluetooth.profile.opp.enabled true
|
||||
# Enable BLE scanning without location requirement
|
||||
resetprop bluetooth.le.disable_apcf_extended_features 0
|
||||
mlog "BT mode: pentest (all profiles, raw HCI)"
|
||||
;;
|
||||
disabled)
|
||||
resetprop bluetooth.profile.a2dp.source.enabled false
|
||||
resetprop bluetooth.profile.hfp.ag.enabled false
|
||||
mlog "BT mode: disabled"
|
||||
;;
|
||||
esac
|
||||
|
||||
# ============================================================
|
||||
# SDR DRIVER MANAGEMENT — RTL-SDR, HackRF, Airspy, LimeSDR
|
||||
# ============================================================
|
||||
# Kernel modules for USB SDR devices via OTG
|
||||
# DVB-T vs SDR mode switching for RTL-SDR
|
||||
|
||||
SDR_MODE=$(cat "$CONFDIR/sdr_mode" 2>/dev/null || echo "sdr")
|
||||
|
||||
# Load USB SDR kernel modules if available
|
||||
load_sdr_module() {
|
||||
MOD_NAME=$1
|
||||
MOD_PATH="$MODDIR/modules/$MOD_NAME.ko"
|
||||
if [ -f "$MOD_PATH" ]; then
|
||||
insmod "$MOD_PATH" 2>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
mlog "SDR: loaded $MOD_NAME"
|
||||
else
|
||||
mlog "SDR: failed to load $MOD_NAME (kernel mismatch?)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
case "$SDR_MODE" in
|
||||
sdr)
|
||||
# SDR scanner mode — blacklist DVB-T drivers, use userspace RTL-SDR
|
||||
# Remove DVB-T kernel module if loaded (conflicts with librtlsdr)
|
||||
rmmod dvb_usb_rtl28xxu 2>/dev/null
|
||||
rmmod dvb_usb_rtl2832u 2>/dev/null
|
||||
rmmod rtl2832 2>/dev/null
|
||||
rmmod rtl2832_sdr 2>/dev/null
|
||||
rmmod dvb_usb_v2 2>/dev/null
|
||||
|
||||
# Load HackRF module
|
||||
load_sdr_module "hackrf"
|
||||
|
||||
# Load Airspy module
|
||||
load_sdr_module "airspy"
|
||||
|
||||
# Set USB permissions for SDR devices
|
||||
# RTL-SDR: vendor 0x0bda, products 0x2832 0x2838
|
||||
# HackRF: vendor 0x1d50, product 0x6089
|
||||
# Airspy: vendor 0x1d50, product 0x60a1
|
||||
# LimeSDR: vendor 0x0403 (FTDI) or 0x04b4 (Cypress)
|
||||
|
||||
mlog "SDR mode: scanner (DVB-T blacklisted, userspace SDR)"
|
||||
;;
|
||||
dvbt)
|
||||
# DVB-T digital TV mode — load DVB kernel drivers
|
||||
load_sdr_module "dvb_usb_rtl28xxu"
|
||||
load_sdr_module "rtl2832"
|
||||
load_sdr_module "rtl2832_sdr"
|
||||
|
||||
# Remove conflicting SDR modules
|
||||
rmmod hackrf 2>/dev/null
|
||||
rmmod airspy 2>/dev/null
|
||||
|
||||
mlog "SDR mode: DVB-T (digital TV receiver)"
|
||||
;;
|
||||
hackrf)
|
||||
# HackRF-only mode — TX/RX capable
|
||||
rmmod dvb_usb_rtl28xxu 2>/dev/null
|
||||
load_sdr_module "hackrf"
|
||||
mlog "SDR mode: HackRF (TX/RX enabled)"
|
||||
;;
|
||||
off)
|
||||
# Unload all SDR modules
|
||||
rmmod hackrf 2>/dev/null
|
||||
rmmod airspy 2>/dev/null
|
||||
rmmod dvb_usb_rtl28xxu 2>/dev/null
|
||||
rmmod rtl2832 2>/dev/null
|
||||
mlog "SDR mode: off"
|
||||
;;
|
||||
esac
|
||||
|
||||
# ============================================================
|
||||
# GAME CONTROLLER DRIVERS — Xbox, PS5, Switch Pro, 8BitDo
|
||||
# ============================================================
|
||||
# Android already has HID support but some controllers need
|
||||
# specific prop tweaks or module loading for full support
|
||||
|
||||
GAMEPAD_MODE=$(cat "$CONFDIR/gamepad_mode" 2>/dev/null || echo "auto")
|
||||
|
||||
case "$GAMEPAD_MODE" in
|
||||
auto)
|
||||
# Enable all supported gamepad types
|
||||
resetprop input.gamepad.enabled true
|
||||
|
||||
# Xbox controller — xpad or xone kernel module
|
||||
load_sdr_module "xpad"
|
||||
|
||||
# PS5 DualSense — hid-playstation
|
||||
load_sdr_module "hid-playstation"
|
||||
|
||||
# Nintendo Switch Pro — hid-nintendo
|
||||
load_sdr_module "hid-nintendo"
|
||||
|
||||
# 8BitDo and generic HID gamepads — standard HID stack
|
||||
# Ensure hid-generic is loaded
|
||||
load_sdr_module "hid-generic"
|
||||
|
||||
mlog "Gamepad mode: auto (all controllers enabled)"
|
||||
;;
|
||||
xbox)
|
||||
load_sdr_module "xpad"
|
||||
mlog "Gamepad mode: Xbox"
|
||||
;;
|
||||
playstation)
|
||||
load_sdr_module "hid-playstation"
|
||||
mlog "Gamepad mode: PlayStation DualSense"
|
||||
;;
|
||||
nintendo)
|
||||
load_sdr_module "hid-nintendo"
|
||||
mlog "Gamepad mode: Nintendo Switch Pro"
|
||||
;;
|
||||
off)
|
||||
mlog "Gamepad mode: off"
|
||||
;;
|
||||
esac
|
||||
|
||||
# ============================================================
|
||||
# SDR DECODERS — Auto-start background decoders if configured
|
||||
# ============================================================
|
||||
|
||||
DECODER_MODE=$(cat "$CONFDIR/decoder_mode" 2>/dev/null || echo "off")
|
||||
|
||||
case "$DECODER_MODE" in
|
||||
adsb)
|
||||
# ADS-B aircraft tracking on 1090 MHz
|
||||
if command -v rtl_adsb >/dev/null 2>&1; then
|
||||
rtl_adsb &
|
||||
mlog "Decoder: ADS-B started (1090 MHz)"
|
||||
fi
|
||||
;;
|
||||
fm)
|
||||
FREQ=$(cat "$CONFDIR/fm_freq" 2>/dev/null || echo "100.0M")
|
||||
if command -v rtl_fm >/dev/null 2>&1; then
|
||||
rtl_fm -f "$FREQ" -M wbfm -s 200000 -r 48000 - | \
|
||||
aplay -r 48000 -f S16_LE -t raw -c 1 &
|
||||
mlog "Decoder: FM radio started ($FREQ)"
|
||||
fi
|
||||
;;
|
||||
spectrum)
|
||||
# Power spectrum scan
|
||||
if command -v rtl_power >/dev/null 2>&1; then
|
||||
RANGE=$(cat "$CONFDIR/spectrum_range" 2>/dev/null || echo "24M:1800M")
|
||||
rtl_power -f "$RANGE" -g 50 -i 1 "$MODDIR/spectrum_data.csv" &
|
||||
mlog "Decoder: spectrum scan started ($RANGE)"
|
||||
fi
|
||||
;;
|
||||
off)
|
||||
mlog "Decoder: off"
|
||||
;;
|
||||
esac
|
||||
|
||||
mlog "Driver Manager service complete"
|
||||
25
system.prop
Normal file
25
system.prop
Normal file
@@ -0,0 +1,25 @@
|
||||
# GPU — PowerVR DXT-48-1536 (Tensor G5)
|
||||
# Force latest Vulkan 1.4 driver path
|
||||
ro.hardware.egl=powervr
|
||||
ro.hardware.vulkan=powervr
|
||||
graphics.gpu.profiler.support=true
|
||||
|
||||
# OpenCL compute (CUDA alternative for non-NVIDIA)
|
||||
vendor.powervr.opencl.allowfp16=1
|
||||
vendor.powervr.opencl.profiling=1
|
||||
|
||||
# WiFi — BCM4390 (Broadcom)
|
||||
wifi.direct.interface=p2p-dev-wlan0
|
||||
wifi.direct.go_intent=15
|
||||
|
||||
# Bluetooth — QCA
|
||||
bluetooth.profile.a2dp.source.enabled=true
|
||||
bluetooth.profile.hfp.ag.enabled=true
|
||||
bluetooth.profile.hid.host.enabled=true
|
||||
bluetooth.profile.pan.nap.enabled=true
|
||||
|
||||
# USB OTG for SDR dongles and controllers
|
||||
persist.sys.usb.otg=1
|
||||
|
||||
# Game controller support
|
||||
input.gamepad.enabled=true
|
||||
12
system/etc/permissions/driver-manager.xml
Normal file
12
system/etc/permissions/driver-manager.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<permissions>
|
||||
<feature name="android.hardware.usb.host" />
|
||||
<feature name="android.hardware.usb.accessory" />
|
||||
<feature name="android.hardware.bluetooth" />
|
||||
<feature name="android.hardware.bluetooth_le" />
|
||||
<feature name="android.hardware.wifi.direct" />
|
||||
<feature name="android.hardware.gamepad" />
|
||||
<feature name="android.hardware.vulkan.level" />
|
||||
<feature name="android.hardware.vulkan.version" />
|
||||
<feature name="android.hardware.opengles.aep" />
|
||||
</permissions>
|
||||
9
system/etc/sysconfig/driver-manager.xml
Normal file
9
system/etc/sysconfig/driver-manager.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<config>
|
||||
<feature name="android.hardware.usb.host" />
|
||||
<feature name="android.hardware.usb.accessory" />
|
||||
<feature name="android.hardware.bluetooth" />
|
||||
<feature name="android.hardware.bluetooth_le" />
|
||||
<feature name="android.hardware.wifi.direct" />
|
||||
<feature name="android.hardware.gamepad" />
|
||||
</config>
|
||||
400
webroot/index.html
Normal file
400
webroot/index.html
Normal file
@@ -0,0 +1,400 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Driver Manager</title>
|
||||
<style>
|
||||
:root {
|
||||
--bg: #0d1117;
|
||||
--surface: #161b22;
|
||||
--surface2: #21262d;
|
||||
--border: #30363d;
|
||||
--primary: #58a6ff;
|
||||
--primary-dim: #388bfd;
|
||||
--green: #3fb950;
|
||||
--orange: #d29922;
|
||||
--red: #f85149;
|
||||
--text: #c9d1d9;
|
||||
--text-dim: #8b949e;
|
||||
--radius: 10px;
|
||||
}
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
background: var(--bg);
|
||||
color: var(--text);
|
||||
padding: 16px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
.header { text-align: center; padding: 20px 0 12px; }
|
||||
.header h1 { font-size: 20px; color: var(--primary); }
|
||||
.header .sub { font-size: 12px; color: var(--text-dim); margin-top: 4px; }
|
||||
|
||||
.card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
padding: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.card-title {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.8px;
|
||||
color: var(--primary);
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.card-title .dot {
|
||||
width: 8px; height: 8px;
|
||||
border-radius: 50%;
|
||||
background: var(--green);
|
||||
}
|
||||
.card-title .dot.off { background: var(--red); }
|
||||
.card-title .dot.warn { background: var(--orange); }
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
.row:last-child { border-bottom: none; }
|
||||
.row-label { font-size: 14px; font-weight: 500; }
|
||||
.row-desc { font-size: 11px; color: var(--text-dim); margin-top: 2px; }
|
||||
.row-value { font-size: 13px; color: var(--green); font-family: monospace; }
|
||||
|
||||
select.sel {
|
||||
background: var(--surface2);
|
||||
color: var(--text);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
padding: 6px 10px;
|
||||
font-size: 13px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 6px;
|
||||
}
|
||||
.info-item {
|
||||
background: var(--surface2);
|
||||
border-radius: 6px;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
.info-item .lbl { font-size: 10px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.3px; }
|
||||
.info-item .val { font-size: 13px; font-weight: 500; margin-top: 2px; font-family: monospace; }
|
||||
|
||||
.log-box {
|
||||
background: var(--surface2);
|
||||
border-radius: 6px;
|
||||
padding: 10px;
|
||||
font-family: "Cascadia Code", "Fira Code", monospace;
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
max-height: 180px;
|
||||
overflow-y: auto;
|
||||
color: var(--text-dim);
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.btn-row { display: flex; gap: 6px; margin-top: 8px; }
|
||||
.btn {
|
||||
flex: 1;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
background: var(--surface2);
|
||||
color: var(--text);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
.btn:active { opacity: 0.7; }
|
||||
.btn-primary { background: var(--primary-dim); color: #fff; border-color: var(--primary); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h1>Driver Manager</h1>
|
||||
<div class="sub">GPU / WiFi / Bluetooth / SDR / Controllers</div>
|
||||
</div>
|
||||
|
||||
<!-- Hardware Info -->
|
||||
<div class="card">
|
||||
<div class="card-title"><span class="dot"></span> Hardware</div>
|
||||
<div class="info-grid">
|
||||
<div class="info-item"><div class="lbl">Device</div><div class="val" id="hwDevice">—</div></div>
|
||||
<div class="info-item"><div class="lbl">SoC</div><div class="val" id="hwSoc">—</div></div>
|
||||
<div class="info-item"><div class="lbl">GPU</div><div class="val" id="hwGpu">—</div></div>
|
||||
<div class="info-item"><div class="lbl">WiFi</div><div class="val" id="hwWifi">—</div></div>
|
||||
<div class="info-item"><div class="lbl">Bluetooth</div><div class="val" id="hwBt">—</div></div>
|
||||
<div class="info-item"><div class="lbl">USB Devices</div><div class="val" id="hwUsb">—</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- GPU -->
|
||||
<div class="card">
|
||||
<div class="card-title"><span class="dot" id="gpuDot"></span> GPU — PowerVR</div>
|
||||
<div class="row">
|
||||
<div>
|
||||
<div class="row-label">Driver Mode</div>
|
||||
<div class="row-desc">Vulkan 1.4 / OpenGL ES 3.x / OpenCL 3.0</div>
|
||||
</div>
|
||||
<select class="sel" id="gpuMode" onchange="setMode('gpu_mode', this.value)">
|
||||
<option value="performance">Performance</option>
|
||||
<option value="balanced">Balanced</option>
|
||||
<option value="powersave">Power Save</option>
|
||||
<option value="compute">Compute (OpenCL)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div><div class="row-label">Vulkan Version</div></div>
|
||||
<div class="row-value" id="gpuVulkan">—</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div><div class="row-label">GL Renderer</div></div>
|
||||
<div class="row-value" id="gpuRenderer">—</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- WiFi -->
|
||||
<div class="card">
|
||||
<div class="card-title"><span class="dot" id="wifiDot"></span> WiFi — BCM4390</div>
|
||||
<div class="row">
|
||||
<div>
|
||||
<div class="row-label">Driver Mode</div>
|
||||
<div class="row-desc">Nexmon: monitor + injection support</div>
|
||||
</div>
|
||||
<select class="sel" id="wifiMode" onchange="setMode('wifi_mode', this.value)">
|
||||
<option value="standard">Standard</option>
|
||||
<option value="monitor">Monitor</option>
|
||||
<option value="injection">Injection (Nexmon)</option>
|
||||
<option value="mesh">Mesh (802.11s)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div><div class="row-label">Interface</div></div>
|
||||
<div class="row-value" id="wifiIface">—</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div><div class="row-label">Nexmon Firmware</div></div>
|
||||
<div class="row-value" id="wifiNexmon">—</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bluetooth -->
|
||||
<div class="card">
|
||||
<div class="card-title"><span class="dot" id="btDot"></span> Bluetooth — QCA</div>
|
||||
<div class="row">
|
||||
<div>
|
||||
<div class="row-label">Driver Mode</div>
|
||||
<div class="row-desc">Standard / pentest (raw HCI, all profiles)</div>
|
||||
</div>
|
||||
<select class="sel" id="btMode" onchange="setMode('bt_mode', this.value)">
|
||||
<option value="standard">Standard</option>
|
||||
<option value="pentest">Pentest</option>
|
||||
<option value="disabled">Disabled</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SDR -->
|
||||
<div class="card">
|
||||
<div class="card-title"><span class="dot" id="sdrDot"></span> SDR Drivers</div>
|
||||
<div class="row">
|
||||
<div>
|
||||
<div class="row-label">Radio Mode</div>
|
||||
<div class="row-desc">RTL-SDR v1-4 / HackRF / Airspy / LimeSDR</div>
|
||||
</div>
|
||||
<select class="sel" id="sdrMode" onchange="setMode('sdr_mode', this.value)">
|
||||
<option value="sdr">SDR Scanner</option>
|
||||
<option value="dvbt">DVB-T (Digital TV)</option>
|
||||
<option value="hackrf">HackRF (TX/RX)</option>
|
||||
<option value="off">Off</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div>
|
||||
<div class="row-label">Decoder</div>
|
||||
<div class="row-desc">Background signal decoder</div>
|
||||
</div>
|
||||
<select class="sel" id="decoderMode" onchange="setMode('decoder_mode', this.value)">
|
||||
<option value="off">Off</option>
|
||||
<option value="adsb">ADS-B (1090 MHz)</option>
|
||||
<option value="fm">FM Radio</option>
|
||||
<option value="spectrum">Spectrum Scan</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div><div class="row-label">USB SDR Devices</div></div>
|
||||
<div class="row-value" id="sdrDevices">—</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Game Controllers -->
|
||||
<div class="card">
|
||||
<div class="card-title"><span class="dot" id="padDot"></span> Game Controllers</div>
|
||||
<div class="row">
|
||||
<div>
|
||||
<div class="row-label">Controller Mode</div>
|
||||
<div class="row-desc">Xbox / PS5 / Switch Pro / 8BitDo / Generic</div>
|
||||
</div>
|
||||
<select class="sel" id="gamepadMode" onchange="setMode('gamepad_mode', this.value)">
|
||||
<option value="auto">Auto (All)</option>
|
||||
<option value="xbox">Xbox Only</option>
|
||||
<option value="playstation">PlayStation Only</option>
|
||||
<option value="nintendo">Nintendo Only</option>
|
||||
<option value="off">Off</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div><div class="row-label">Connected Controllers</div></div>
|
||||
<div class="row-value" id="padDevices">—</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Log -->
|
||||
<div class="card">
|
||||
<div class="card-title">Log</div>
|
||||
<div class="log-box" id="logArea">Initializing...</div>
|
||||
<div class="btn-row">
|
||||
<button class="btn" onclick="refreshAll()">Refresh</button>
|
||||
<button class="btn" onclick="showLog()">Module Log</button>
|
||||
<button class="btn btn-primary" onclick="applyAll()">Apply & Restart</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const MODDIR = '/data/adb/modules/driver-manager';
|
||||
|
||||
function exec(cmd) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const cb = 'cb_' + Date.now() + '_' + Math.random().toString(36).slice(2);
|
||||
window[cb] = (errno, stdout, stderr) => {
|
||||
delete window[cb];
|
||||
resolve({ errno, stdout: stdout || '', stderr: stderr || '' });
|
||||
};
|
||||
try { ksu.exec(cmd, '{}', cb); }
|
||||
catch (e) { delete window[cb]; reject(e); }
|
||||
});
|
||||
}
|
||||
|
||||
function log(msg) {
|
||||
const a = document.getElementById('logArea');
|
||||
const ts = new Date().toLocaleTimeString('en-US', { hour12: false });
|
||||
a.textContent += '\n[' + ts + '] ' + msg;
|
||||
a.scrollTop = a.scrollHeight;
|
||||
}
|
||||
|
||||
async function gp(name) {
|
||||
try { return (await exec('getprop ' + name)).stdout.trim(); }
|
||||
catch (e) { return ''; }
|
||||
}
|
||||
|
||||
async function setMode(file, value) {
|
||||
log('Setting ' + file + ' = ' + value);
|
||||
await exec('echo "' + value + '" > ' + MODDIR + '/config/' + file);
|
||||
log('OK. Changes apply on next boot or click Apply & Restart.');
|
||||
}
|
||||
|
||||
async function applyAll() {
|
||||
log('Restarting driver service...');
|
||||
await exec('sh ' + MODDIR + '/service.sh &');
|
||||
log('Service restarted. Some changes need reboot.');
|
||||
setTimeout(refreshAll, 2000);
|
||||
}
|
||||
|
||||
async function loadHardware() {
|
||||
document.getElementById('hwDevice').textContent = await gp('ro.product.model');
|
||||
document.getElementById('hwSoc').textContent = await gp('ro.soc.model');
|
||||
document.getElementById('hwGpu').textContent = await gp('ro.hardware.egl');
|
||||
|
||||
const wifi = (await exec('ls /sys/module/ | grep -iE "^(bcmdhd|qca|wcn|ath|mt76)" | head -1')).stdout.trim();
|
||||
document.getElementById('hwWifi').textContent = wifi || 'unknown';
|
||||
|
||||
const bt = (await exec('ls /sys/module/ | grep -iE "^(btqca|btusb|btbcm)" | head -1')).stdout.trim();
|
||||
document.getElementById('hwBt').textContent = bt || 'unknown';
|
||||
|
||||
const usb = (await exec('lsusb 2>/dev/null | wc -l || echo 0')).stdout.trim();
|
||||
document.getElementById('hwUsb').textContent = usb + ' devices';
|
||||
}
|
||||
|
||||
async function loadModes() {
|
||||
const modes = ['gpu_mode', 'wifi_mode', 'bt_mode', 'sdr_mode', 'gamepad_mode', 'decoder_mode'];
|
||||
const ids = ['gpuMode', 'wifiMode', 'btMode', 'sdrMode', 'gamepadMode', 'decoderMode'];
|
||||
for (let i = 0; i < modes.length; i++) {
|
||||
const val = (await exec('cat ' + MODDIR + '/config/' + modes[i] + ' 2>/dev/null')).stdout.trim();
|
||||
if (val) document.getElementById(ids[i]).value = val;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadGpuInfo() {
|
||||
const renderer = await gp('debug.hwui.renderer');
|
||||
document.getElementById('gpuRenderer').textContent = renderer || 'default';
|
||||
|
||||
const vulkan = await gp('ro.hardware.vulkan');
|
||||
document.getElementById('gpuVulkan').textContent = vulkan ? vulkan + ' (1.4)' : 'unknown';
|
||||
}
|
||||
|
||||
async function loadWifiInfo() {
|
||||
const iface = (await exec('ip link show wlan0 2>/dev/null | head -1')).stdout.trim();
|
||||
document.getElementById('wifiIface').textContent = iface ? 'wlan0 (up)' : 'wlan0';
|
||||
|
||||
const nexmon = (await exec('ls ' + MODDIR + '/firmware/fw_bcm4390_*.bin 2>/dev/null | wc -l')).stdout.trim();
|
||||
document.getElementById('wifiNexmon').textContent = nexmon > 0 ? nexmon + ' firmware(s)' : 'not installed';
|
||||
}
|
||||
|
||||
async function loadSdrInfo() {
|
||||
// Detect connected USB SDR devices by vendor:product ID
|
||||
const usb = (await exec(
|
||||
'cat /sys/bus/usb/devices/*/idVendor 2>/dev/null | while read v; do ' +
|
||||
'dir=$(grep -rl "$v" /sys/bus/usb/devices/*/idVendor 2>/dev/null | head -1 | xargs dirname); ' +
|
||||
'p=$(cat "$dir/idProduct" 2>/dev/null); ' +
|
||||
'case "$v:$p" in ' +
|
||||
'"0bda:2832"|"0bda:2838") echo "RTL-SDR";; ' +
|
||||
'"1d50:6089") echo "HackRF";; ' +
|
||||
'"1d50:60a1") echo "Airspy";; ' +
|
||||
'"0403:6014"|"04b4:00f3") echo "LimeSDR";; ' +
|
||||
'esac; done 2>/dev/null | sort -u | tr "\\n" ", "'
|
||||
)).stdout.trim();
|
||||
document.getElementById('sdrDevices').textContent = usb || 'none detected';
|
||||
}
|
||||
|
||||
async function loadControllerInfo() {
|
||||
const pads = (await exec('cat /proc/bus/input/devices 2>/dev/null | grep -iE "(xbox|playstation|dualsense|pro controller|8bitdo|gamepad)" | wc -l')).stdout.trim();
|
||||
document.getElementById('padDevices').textContent = (pads && pads !== '0') ? pads + ' connected' : 'none';
|
||||
}
|
||||
|
||||
async function showLog() {
|
||||
const r = await exec('cat ' + MODDIR + '/driver-manager.log 2>/dev/null || echo "No log"');
|
||||
document.getElementById('logArea').textContent = '=== Module Log ===\n' + r.stdout;
|
||||
}
|
||||
|
||||
async function refreshAll() {
|
||||
log('Refreshing...');
|
||||
await loadHardware();
|
||||
await loadModes();
|
||||
await loadGpuInfo();
|
||||
await loadWifiInfo();
|
||||
await loadSdrInfo();
|
||||
await loadControllerInfo();
|
||||
log('Done');
|
||||
}
|
||||
|
||||
(async () => {
|
||||
try { await refreshAll(); log('Ready'); }
|
||||
catch (e) { log('Init error: ' + e.message); }
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user