From 7776b6c497afd8fa63e853ce17f6ea007a373996 Mon Sep 17 00:00:00 2001 From: sssnake Date: Tue, 31 Mar 2026 07:20:55 -0700 Subject: [PATCH] Update to native-first driver model + user build docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Confirmed kernel modules on Pixel 10 Pro Fold (rango): All gamepad drivers native (xpad, hid-playstation, hid-nintendo, hid-sony, hid-microsoft, hid-logitech, hid-steam, wacom). SDR uses userspace USB (no kernel modules). WiFi nexmon and joydev need user-built firmware/modules — documented in BUILDING_MODULES.md with full instructions. --- BUILDING_MODULES.md | 195 +++++++++++++++++++++ driver-manager-v1.0.0.zip | Bin 0 -> 11057 bytes service.sh | 353 ++++++++++++++++++++------------------ webroot/index.html | 6 +- 4 files changed, 387 insertions(+), 167 deletions(-) create mode 100644 BUILDING_MODULES.md create mode 100644 driver-manager-v1.0.0.zip diff --git a/BUILDING_MODULES.md b/BUILDING_MODULES.md new file mode 100644 index 0000000..a288ffb --- /dev/null +++ b/BUILDING_MODULES.md @@ -0,0 +1,195 @@ +# Building Custom Kernel Modules & Firmware + +This module works out of the box for everything that's native to the Pixel 10 Pro Fold kernel. +Some features need extra firmware or kernel modules you build yourself. + +## What's Already Native (No Build Needed) + +| Component | Driver | Status | +|-----------|--------|--------| +| GPU | pvrsrvkm (PowerVR DXT-48-1536) | Built-in, Vulkan 1.4 / GLES 3.x / OpenCL 3.0 | +| WiFi | bcmdhd4390 (Broadcom BCM4390) | Built-in, Wi-Fi 7 / WFD R2 / P2P | +| Bluetooth | btqca + btbcm + rfcomm + hidp | Built-in | +| Xbox Controllers | xpad | Built-in (CONFIG_JOYSTICK_XPAD=y) | +| PS5 DualSense | hid-playstation | Built-in | +| PS4 DualShock | hid-sony | Built-in | +| Switch Pro / Joy-Con | hid-nintendo | Built-in | +| Xbox One (BT) | hid-microsoft | Built-in | +| Logitech (F310/F710) | hid-logitech + hidpp | Built-in | +| Steam Controller | hid-steam | Built-in | +| Wacom Tablets | wacom | Built-in | +| 8BitDo / Generic | hid-generic | Built-in | +| USB Audio | snd_usb_audio | Built-in | +| USB Serial (FTDI) | ftdi_sio | Built-in | +| USB CDC ACM | cdc_acm | Built-in | +| USB Cameras | uvcvideo | Built-in | +| WireGuard VPN | wireguard | Built-in | + +## What Needs User Action + +### 1. SDR Devices (RTL-SDR, HackRF, Airspy, LimeSDR) + +**No kernel modules needed.** All SDR devices on Android use userspace USB libraries. +The module handles USB permissions automatically. + +**Setup in Termux:** + +```bash +pkg update && pkg install -y rtl-sdr hackrf +``` + +This gives you: `rtl_sdr`, `rtl_fm`, `rtl_adsb`, `rtl_power`, `rtl_tcp`, `hackrf_transfer`, `hackrf_sweep` + +**Android apps that work with USB OTG SDR:** +- SDR Touch (RTL-SDR) +- RF Analyzer (RTL-SDR) +- Aerial TV (DVB-T via RTL-SDR) +- SDR++ (if compiled for Android via Termux) + +**Switching between DVB-T and SDR:** +There's no kernel conflict on this device (no DVB modules compiled in). +Just use the appropriate app — Aerial TV for DVB-T, SDR Touch for scanning. + +### 2. Nexmon WiFi Monitor/Injection Mode + +The BCM4390 is a new chip. Nexmon does NOT officially support it yet. + +**To check for support:** +```bash +git clone https://github.com/seemoo-lab/nexmon +grep -r "4390" nexmon/ +``` + +**If/when BCM4390 patches become available:** + +1. Clone nexmon and set up the build environment: +```bash +# In Termux or a Linux build machine +git clone https://github.com/seemoo-lab/nexmon +cd nexmon +source setup_env.sh +make +``` + +2. Build the patched firmware for BCM4390: +```bash +cd patches/bcm4390//nexmon +make +``` + +3. Copy the firmware files to the module: +```bash +# Monitor mode firmware +cp .bin /data/adb/modules/driver-manager/firmware/fw_bcm4390_monitor.bin + +# Injection mode firmware (if separate) +cp .bin /data/adb/modules/driver-manager/firmware/fw_bcm4390_injection.bin +``` + +4. Switch mode via WebUI or manually: +```bash +echo "monitor" > /data/adb/modules/driver-manager/config/wifi_mode +sh /data/adb/modules/driver-manager/service.sh +``` + +**Currently supported Broadcom chips with nexmon:** +BCM4330, BCM4335b0, BCM4339, BCM43430a1, BCM43439a0, BCM43451b1, +BCM43455c0, BCM43436b0, BCM4375b1, BCM4389c1, BCM4398d0 + +### 3. Joydev (/dev/input/jsX) + +The kernel has `CONFIG_INPUT_JOYDEV` disabled. Most Android games use evdev +(`/dev/input/eventX`) which works fine. If you need joydev for a specific app: + +**Option A: Build joydev.ko** + +You need the kernel source matching your device's kernel version. + +```bash +# Get kernel version +uname -r + +# Clone the kernel source +# For Pixel 10 (rango), the source is in the Android kernel common tree +repo init -u https://android.googlesource.com/kernel/manifest -b android-gs-laguna- +repo sync -c + +# Build the module +make ARCH=arm64 modules_prepare +make ARCH=arm64 M=drivers/input/joydev modules +``` + +Copy `joydev.ko` to `/data/adb/modules/driver-manager/modules/` and it will +be loaded on next boot. + +**Option B: Use a custom kernel** that has joydev compiled in. + +### 4. GPU Driver Updates + +The PowerVR GPU driver is updatable via Google Play (Game Update Pack). +This module sets `ro.gfx.driver.1` to request the updatable driver. + +**To check current driver version:** +```bash +dumpsys gpu | grep -i version +# or +getprop ro.gfx.driver.1 +``` + +**To force a specific driver version:** +If Google hasn't pushed v25.1+ yet, check: +- Settings > System > System Update (driver updates come with security patches) +- The Android 16 QPR3 update bumps the driver to v1.634.2906 + +### 5. OpenCL (CUDA Alternative) + +There is no CUDA on Android (NVIDIA only). PowerVR supports OpenCL 3.0 instead. + +**To use OpenCL on Pixel 10:** +- PowerVR OpenCL library: `/vendor/lib64/libPVROCL.so` +- Use compute mode in this module to enable FP16 and max GPU freq +- Vulkan compute shaders are also an option for GPU workloads + +**Termux OpenCL setup:** +```bash +pkg install -y clinfo opencl-headers +clinfo # Should show PowerVR device +``` + +## Kernel Module Loading via KernelSU + +KernelSU supports loading `.ko` files. Place them in: +``` +/data/adb/modules/driver-manager/modules/.ko +``` + +The module will `insmod` any `.ko` files found at boot. + +**Important:** Modules must be compiled against the exact kernel version +running on your device. Mismatched modules will fail to load with +"Invalid module format" or segfault. + +Check your kernel version: +```bash +uname -r +cat /proc/version +``` + +## USB Device Reference + +| Device | Vendor:Product | Type | +|--------|---------------|------| +| RTL-SDR v1 | 0bda:2832 | Userspace USB | +| RTL-SDR v3 | 0bda:2838 | Userspace USB | +| RTL-SDR v4 | 0bda:2840 | Userspace USB | +| HackRF One | 1d50:6089 | Userspace USB | +| Airspy Mini | 1d50:60a1 | Userspace USB | +| Airspy HF+ | 1d50:6108 | Userspace USB | +| LimeSDR Mini | 04b4:00f3 | Userspace USB | +| SDRplay RSP1 | 1df7:2500 | Userspace USB | +| SDRplay RSP2 | 1df7:3020 | Userspace USB | +| Xbox Controller | 045e:028e | Native xpad | +| PS5 DualSense | 054c:0ce6 | Native hid-playstation | +| PS4 DualShock | 054c:09cc | Native hid-sony | +| Switch Pro | 057e:2009 | Native hid-nintendo | +| 8BitDo | Various | Native hid-generic | diff --git a/driver-manager-v1.0.0.zip b/driver-manager-v1.0.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..c40ece5dbc5d6e3e8a5eca5cfee7321000cf97dc GIT binary patch literal 11057 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 Z`1?05#OsCv01#e(POtm5it^{b{|6C`Mn?bu literal 0 HcmV?d00001 diff --git a/service.sh b/service.sh index 710366a..df117c6 100755 --- a/service.sh +++ b/service.sh @@ -1,6 +1,16 @@ #!/system/bin/sh # Driver Manager - late service # Manages GPU, WiFi, Bluetooth, SDR, and game controller drivers +# +# Native kernel support confirmed on Pixel 10 Pro Fold (rango): +# GPU: pvrsrvkm (PowerVR DXT-48-1536) — built-in +# WiFi: bcmdhd4390 (Broadcom BCM4390) — built-in +# Bluetooth: btqca, btbcm, bluetooth, rfcomm, hidp — built-in +# Controllers: xpad, hid-playstation, hid-nintendo, hid-sony, +# hid-microsoft, hid-logitech, hid-steam, wacom — all built-in +# USB: usbhid, usb_storage, ftdi_sio, cdc_acm, snd_usb_audio — built-in +# SDR: No kernel DVB/SDR modules — all SDR uses userspace USB via OTG +# (librtlsdr, libhackrf, libairspy talk directly to USB device) MODDIR=${0%/*} LOGFILE="$MODDIR/driver-manager.log" @@ -30,91 +40,109 @@ 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 +# GPU — PowerVR DXT-48-1536 (pvrsrvkm, native) # ============================================================ -# 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/ +# Vulkan 1.4, OpenGL ES 3.x, OpenCL 3.0 +# Driver: /vendor/lib64/egl/libGLES_powervr.so +# Firmware: /vendor/firmware/powervr/ 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.renderer skiagl resetprop debug.hwui.use_hint_manager true - mlog "GPU mode: performance (Vulkan renderer, max freq)" + # Request max GPU frequency via thermal hint + echo "max" > /sys/class/powervr/frequency_hint 2>/dev/null + mlog "GPU: performance (Vulkan render, max freq)" ;; balanced) - resetprop vendor.powervr.gpu.freq_hint auto - resetprop debug.hwui.renderer skiagl resetprop debug.renderengine.backend skiaglthreaded - mlog "GPU mode: balanced" + resetprop debug.hwui.renderer skiagl + echo "auto" > /sys/class/powervr/frequency_hint 2>/dev/null + mlog "GPU: balanced" ;; powersave) - resetprop vendor.powervr.gpu.freq_hint min - resetprop debug.hwui.renderer skiagl resetprop debug.renderengine.backend skiagl - mlog "GPU mode: powersave" + resetprop debug.hwui.renderer skiagl + echo "min" > /sys/class/powervr/frequency_hint 2>/dev/null + mlog "GPU: powersave" ;; compute) - # Optimized for OpenCL workloads + # OpenCL compute priority — CUDA alternative 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)" + echo "max" > /sys/class/powervr/frequency_hint 2>/dev/null + mlog "GPU: compute (OpenCL 3.0, FP16 enabled)" ;; esac -# Force Vulkan 1.4 feature level if driver supports it +# Updatable GPU driver — Pixel 10 supports Game Update Pack +# v25.1+ brings Vulkan 1.4 and major perf improvements over v24.3 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" +mlog "GPU driver: PowerVR DXT-48-1536 (pvrsrvkm native)" # ============================================================ -# WIFI DRIVER MANAGEMENT — BCM4390 (bcmdhd4390) +# WIFI — BCM4390 (bcmdhd4390, native) # ============================================================ -# Modes: standard, monitor, injection (nexmon), mesh +# Capabilities: Wi-Fi 7, WFD R2, P2P, VHT, DFS +# Firmware: /vendor/firmware/fw_bcmdhd4390.bin 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" + resetprop wifi.direct.go_intent 15 + mlog "WiFi: standard (P2P enabled)" ;; monitor) - # Enable monitor mode on BCM4390 - # Requires nexmon-patched firmware or native support + # BCM4390 monitor mode via nexmon firmware patch if [ -f "$MODDIR/firmware/fw_bcm4390_monitor.bin" ]; then + # Back up stock firmware on first use + if [ ! -f "$MODDIR/firmware/fw_bcm4390_stock.bin" ]; then + cp /vendor/firmware/fw_bcmdhd4390.bin "$MODDIR/firmware/fw_bcm4390_stock.bin" + mlog "WiFi: backed up stock firmware" + fi cp "$MODDIR/firmware/fw_bcm4390_monitor.bin" /vendor/firmware/fw_bcmdhd4390.bin - mlog "WiFi mode: monitor (nexmon firmware loaded)" + # Reload driver + echo 1 > /sys/module/bcmdhd4390/parameters/reload 2>/dev/null + mlog "WiFi: monitor mode (nexmon firmware loaded)" else - # Try native monitor via iw/ip - mlog "WiFi mode: monitor (native, nexmon firmware not found)" + mlog "WiFi: monitor mode requested — nexmon firmware not found" + mlog "WiFi: see BUILDING_MODULES.md for instructions" fi ;; injection) - # Frame injection — requires nexmon patches for BCM4390 if [ -f "$MODDIR/firmware/fw_bcm4390_injection.bin" ]; then + if [ ! -f "$MODDIR/firmware/fw_bcm4390_stock.bin" ]; then + cp /vendor/firmware/fw_bcmdhd4390.bin "$MODDIR/firmware/fw_bcm4390_stock.bin" + fi cp "$MODDIR/firmware/fw_bcm4390_injection.bin" /vendor/firmware/fw_bcmdhd4390.bin - mlog "WiFi mode: injection (nexmon firmware loaded)" + echo 1 > /sys/module/bcmdhd4390/parameters/reload 2>/dev/null + mlog "WiFi: injection mode (nexmon firmware loaded)" else - mlog "WiFi mode: injection requested but no nexmon firmware" + mlog "WiFi: injection requested — nexmon firmware not found" + mlog "WiFi: see BUILDING_MODULES.md for instructions" fi ;; - mesh) - # 802.11s mesh networking - resetprop wifi.interface wlan0 - mlog "WiFi mode: mesh (802.11s)" + restore) + # Restore stock firmware + if [ -f "$MODDIR/firmware/fw_bcm4390_stock.bin" ]; then + cp "$MODDIR/firmware/fw_bcm4390_stock.bin" /vendor/firmware/fw_bcmdhd4390.bin + echo 1 > /sys/module/bcmdhd4390/parameters/reload 2>/dev/null + mlog "WiFi: stock firmware restored" + fi + echo "standard" > "$CONFDIR/wifi_mode" + mlog "WiFi: restored to standard" ;; esac # ============================================================ -# BLUETOOTH DRIVER MANAGEMENT — QCA (btqca) +# BLUETOOTH — QCA + BCM (btqca, btbcm, native) # ============================================================ +# rfcomm, hidp, bluetooth all built into kernel BT_MODE=$(cat "$CONFDIR/bt_mode" 2>/dev/null || echo "standard") @@ -124,178 +152,175 @@ case "$BT_MODE" in 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" + mlog "BT: standard" ;; pentest) - # Enable all profiles + raw HCI access for BLE scanning/exploitation + # All profiles enabled, raw HCI access 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)" + # Allow BLE scan without location + resetprop bluetooth.le.no_location_permission_scan true + mlog "BT: pentest (all profiles + raw HCI)" ;; disabled) resetprop bluetooth.profile.a2dp.source.enabled false resetprop bluetooth.profile.hfp.ag.enabled false - mlog "BT mode: disabled" + resetprop bluetooth.profile.hid.host.enabled false + mlog "BT: disabled" ;; esac # ============================================================ -# SDR DRIVER MANAGEMENT — RTL-SDR, HackRF, Airspy, LimeSDR +# SDR — Userspace USB (no kernel modules needed) # ============================================================ -# Kernel modules for USB SDR devices via OTG -# DVB-T vs SDR mode switching for RTL-SDR +# RTL-SDR, HackRF, Airspy, LimeSDR all use userspace USB libs +# Android apps (SDR Touch, RF Analyzer) or Termux tools +# (rtl_sdr, hackrf_transfer, etc.) talk directly to USB device. +# +# The kernel has NO DVB/RTL-SDR modules compiled in, so there's +# no DVB-T vs SDR conflict to manage — it's always userspace. +# +# What we DO manage: USB device permissions and decoder processes 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 +# Ensure USB OTG is enabled for SDR dongles +resetprop persist.sys.usb.otg 1 + +# Set USB device permissions for known SDR hardware +# This runs udev-style permission fixing for USB devices +fix_sdr_permissions() { + # Find USB devices by vendor:product and chmod them + for dev in /dev/bus/usb/*/*; do + [ -e "$dev" ] || continue + # Read vendor/product from sysfs + USBDEV=$(readlink -f "$dev" 2>/dev/null) + VENDOR=$(cat "$(dirname "$USBDEV")/idVendor" 2>/dev/null) + PRODUCT=$(cat "$(dirname "$USBDEV")/idProduct" 2>/dev/null) + + case "$VENDOR:$PRODUCT" in + 0bda:2832|0bda:2838|0bda:2840) # RTL-SDR v1-v4 + chmod 666 "$dev" 2>/dev/null + mlog "SDR USB: RTL-SDR at $dev" + ;; + 1d50:6089) # HackRF One + chmod 666 "$dev" 2>/dev/null + mlog "SDR USB: HackRF at $dev" + ;; + 1d50:60a1) # Airspy + chmod 666 "$dev" 2>/dev/null + mlog "SDR USB: Airspy at $dev" + ;; + 1d50:6108) # Airspy HF+ + chmod 666 "$dev" 2>/dev/null + mlog "SDR USB: Airspy HF+ at $dev" + ;; + 0403:6014|04b4:00f3) # LimeSDR (FTDI/Cypress) + chmod 666 "$dev" 2>/dev/null + mlog "SDR USB: LimeSDR at $dev" + ;; + 1df7:2500|1df7:3020) # SDRplay RSP1/RSP2 + chmod 666 "$dev" 2>/dev/null + mlog "SDR USB: SDRplay at $dev" + ;; + esac + done } +fix_sdr_permissions + 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)" + mlog "SDR: scanner mode (userspace USB, all devices)" ;; 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)" + # DVB-T mode — uses same USB device but with DVB-T app + # No kernel module switching needed; app handles the protocol + mlog "SDR: DVB-T mode (userspace, Aerial TV or similar app)" ;; 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)" + mlog "SDR: HackRF TX/RX mode (userspace USB)" ;; 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" + mlog "SDR: off" + ;; +esac + +# SDR decoder management +DECODER_MODE=$(cat "$CONFDIR/decoder_mode" 2>/dev/null || echo "off") +TERMUX_BIN="/data/data/com.termux/files/usr/bin" + +case "$DECODER_MODE" in + adsb) + if [ -x "$TERMUX_BIN/rtl_adsb" ]; then + "$TERMUX_BIN/rtl_adsb" > "$MODDIR/adsb_output.txt" 2>/dev/null & + mlog "Decoder: ADS-B started via Termux (1090 MHz)" + else + mlog "Decoder: ADS-B requested — install rtl-sdr in Termux" + fi + ;; + fm) + FREQ=$(cat "$CONFDIR/fm_freq" 2>/dev/null || echo "100.0M") + if [ -x "$TERMUX_BIN/rtl_fm" ]; then + "$TERMUX_BIN/rtl_fm" -f "$FREQ" -M wbfm -s 200000 -r 48000 - 2>/dev/null | \ + "$TERMUX_BIN/aplay" -r 48000 -f S16_LE -t raw -c 1 2>/dev/null & + mlog "Decoder: FM radio ($FREQ) via Termux" + else + mlog "Decoder: FM requested — install rtl-sdr in Termux" + fi + ;; + spectrum) + RANGE=$(cat "$CONFDIR/spectrum_range" 2>/dev/null || echo "24M:1800M") + if [ -x "$TERMUX_BIN/rtl_power" ]; then + "$TERMUX_BIN/rtl_power" -f "$RANGE" -g 50 -i 1 "$MODDIR/spectrum_data.csv" 2>/dev/null & + mlog "Decoder: spectrum scan ($RANGE) via Termux" + else + mlog "Decoder: spectrum requested — install rtl-sdr in Termux" + fi + ;; + off) + # Kill any running decoders + pkill -f rtl_adsb 2>/dev/null + pkill -f rtl_fm 2>/dev/null + pkill -f rtl_power 2>/dev/null + mlog "Decoder: off" ;; esac # ============================================================ -# GAME CONTROLLER DRIVERS — Xbox, PS5, Switch Pro, 8BitDo +# GAME CONTROLLERS — All native, all built into kernel # ============================================================ -# Android already has HID support but some controllers need -# specific prop tweaks or module loading for full support +# xpad (Xbox) — CONFIG_JOYSTICK_XPAD=y +# hid-playstation (PS5 DualSense, PS4 DualShock) — built-in +# hid-nintendo (Switch Pro, Joy-Con) — built-in +# hid-sony (PS3 Sixaxis, PS4 DS4) — built-in +# hid-microsoft (Xbox One BT) — built-in +# hid-logitech + hidpp (F310, F710, etc.) — built-in +# hid-steam (Steam Controller) — built-in +# wacom (drawing tablets) — built-in +# hid-generic (8BitDo, generic HID gamepads) — built-in +# +# NOTE: CONFIG_INPUT_JOYDEV is NOT set, so /dev/input/jsX +# does not exist. Games use /dev/input/eventX via evdev instead, +# which is standard on Android. Apps that need joydev will need +# a custom kernel — see BUILDING_MODULES.md GAMEPAD_MODE=$(cat "$CONFDIR/gamepad_mode" 2>/dev/null || echo "auto") case "$GAMEPAD_MODE" in auto) - # Enable all supported gamepad types + # All controllers already supported natively + # Just ensure the HID input prop is set 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" + mlog "Controllers: auto (xpad, hid-playstation, hid-nintendo, hid-sony, hid-microsoft, hid-logitech, hid-steam, wacom — all native)" ;; 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" + mlog "Controllers: off (native drivers still loaded, cannot unload built-in)" ;; esac diff --git a/webroot/index.html b/webroot/index.html index e0cd879..75883e5 100644 --- a/webroot/index.html +++ b/webroot/index.html @@ -177,9 +177,9 @@
@@ -247,7 +247,7 @@
Controller Mode
-
Xbox / PS5 / Switch Pro / 8BitDo / Generic
+
All native: Xbox, PS5, PS4, Switch, Steam, Logitech, 8BitDo, Wacom