#!/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"
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"

# =================================================================
# BOOT TIMING — Wait for Play Integrity before applying mods
# =================================================================
# If boot timing is enabled, we hand off to boot_timing.sh which:
#   1. Spoofs boot props (green/locked/enforcing)
#   2. Waits for first Play Integrity attestation to finish
#   3. THEN applies all our modifications
#   4. Starts a watcher that hides mods during future PI checks
#
# If disabled, mods apply immediately (faster but less stealthy)

BOOT_TIMING=$(cat "$CONFDIR/boot_timing" 2>/dev/null || echo "0")

if [ "$BOOT_TIMING" = "1" ]; then
    mlog "Boot timing enabled — deferring mods until after PI attestation"
    # Spoof boot props NOW (safe, just props)
    sh "$MODDIR/scripts/boot_timing.sh" run &
    TIMING_PID=$!
    echo "$TIMING_PID" > "$MODDIR/run/boot_timing.pid"
    mlog "Boot timing daemon started (PID $TIMING_PID)"
    # The rest of this script still runs to set up configs,
    # but the actual driver spoofs are deferred to boot_timing.sh
fi

# ============================================================
# GPU — PowerVR DXT-48-1536 (pvrsrvkm, native)
# ============================================================
# 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)
        resetprop debug.renderengine.backend skiavk
        resetprop debug.hwui.renderer skiagl
        resetprop debug.hwui.use_hint_manager true
        # 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 debug.renderengine.backend skiaglthreaded
        resetprop debug.hwui.renderer skiagl
        echo "auto" > /sys/class/powervr/frequency_hint 2>/dev/null
        mlog "GPU: balanced"
        ;;
    powersave)
        resetprop debug.renderengine.backend skiagl
        resetprop debug.hwui.renderer skiagl
        echo "min" > /sys/class/powervr/frequency_hint 2>/dev/null
        mlog "GPU: powersave"
        ;;
    compute)
        # OpenCL compute priority — CUDA alternative
        resetprop vendor.powervr.opencl.allowfp16 1
        resetprop vendor.powervr.opencl.profiling 1
        echo "max" > /sys/class/powervr/frequency_hint 2>/dev/null
        mlog "GPU: compute (OpenCL 3.0, FP16 enabled)"
        ;;
esac

# 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 driver: PowerVR DXT-48-1536 (pvrsrvkm native)"

# ============================================================
# WIFI — BCM4390 (bcmdhd4390, native)
# ============================================================
# 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)
        resetprop wifi.direct.interface p2p-dev-wlan0
        resetprop wifi.direct.go_intent 15
        mlog "WiFi: standard (P2P enabled)"
        ;;
    monitor)
        # 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
            # Reload driver
            echo 1 > /sys/module/bcmdhd4390/parameters/reload 2>/dev/null
            mlog "WiFi: monitor mode (nexmon firmware loaded)"
        else
            mlog "WiFi: monitor mode requested — nexmon firmware not found"
            mlog "WiFi: see BUILDING_MODULES.md for instructions"
        fi
        ;;
    injection)
        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
            echo 1 > /sys/module/bcmdhd4390/parameters/reload 2>/dev/null
            mlog "WiFi: injection mode (nexmon firmware loaded)"
        else
            mlog "WiFi: injection requested — nexmon firmware not found"
            mlog "WiFi: see BUILDING_MODULES.md for instructions"
        fi
        ;;
    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 — QCA + BCM (btqca, btbcm, native)
# ============================================================
# rfcomm, hidp, bluetooth all built into kernel

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: standard"
        ;;
    pentest)
        # 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
        resetprop bluetooth.le.disable_apcf_extended_features 0
        # 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
        resetprop bluetooth.profile.hid.host.enabled false
        mlog "BT: disabled"
        ;;
esac

# ============================================================
# SDR — Userspace USB (no kernel modules needed)
# ============================================================
# 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")

# 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)
        mlog "SDR: scanner mode (userspace USB, all devices)"
        ;;
    dvbt)
        # 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)
        mlog "SDR: HackRF TX/RX mode (userspace USB)"
        ;;
    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 CONTROLLERS — All native, all built into kernel
# ============================================================
# 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)
        # All controllers already supported natively
        # Just ensure the HID input prop is set
        resetprop input.gamepad.enabled true
        mlog "Controllers: auto (xpad, hid-playstation, hid-nintendo, hid-sony, hid-microsoft, hid-logitech, hid-steam, wacom — all native)"
        ;;
    off)
        mlog "Controllers: off (native drivers still loaded, cannot unload built-in)"
        ;;
esac

# ============================================================
# DRIVER SPOOFING — Stock files visible, custom code loaded
# ============================================================
# Per-process mount namespace isolation: verification tools see
# stock drivers (hash/sig intact), but the actual loader process
# (surfaceflinger, wpa_supplicant, etc.) gets our custom binary.
# dm-verity stays intact. Verified boot passes.

SPOOF_ENABLED=$(cat "$CONFDIR/spoof_enabled" 2>/dev/null || echo "0")

if [ "$SPOOF_ENABLED" = "1" ] && [ "$BOOT_TIMING" != "1" ]; then
    # Apply immediately if boot timing is NOT handling it
    # (boot_timing.sh applies spoofs after PI passes)
    sleep 5
    sh "$MODDIR/scripts/driver_spoof.sh" apply
    mlog "Driver spoofing applied (immediate mode)"
fi

mlog "Driver Manager service complete"
