#!/bin/sh
set -eu

[ -f /etc/peacock/debug-rndis.conf ] && . /etc/peacock/debug-rndis.conf || true

USB_MODE="${USB_MODE:-rndis}"
RNDIS_ADDR="${RNDIS_ADDR:-172.16.42.1/24}"
RNDIS_DHCP_START="${RNDIS_DHCP_START:-172.16.42.20}"
RNDIS_DHCP_END="${RNDIS_DHCP_END:-172.16.42.120}"
USB_ID_VENDOR="${USB_ID_VENDOR:-04E8}"
USB_ID_PRODUCT_RNDIS="${USB_ID_PRODUCT_RNDIS:-6863}"
USB_GADGET_PATH="${USB_GADGET_PATH:-}"
USB_UDC_NAME="${USB_UDC_NAME:-}"

logf="/var/log/peacock-debug-rndis.log"
mkdir -p /var/log /run /tmp /dev/socket

try_modprobe() {
    command -v modprobe >/dev/null 2>&1 || return 0
    modprobe "$1" >/dev/null 2>&1 || true
}

# Best-effort: load gadget/network pieces when built as modules.
for m in libcomposite usb_f_rndis u_ether usb_f_ecm usb_f_acm configfs; do
    try_modprobe "$m"
done

find_usb_base() {
    for p in \
        "$USB_GADGET_PATH" \
        /sys/class/android_usb/android0 \
        /sys/devices/virtual/android_usb/android0 \
        /sys/devices/virtual/usb_composite/*; do
        if [ -n "${p:-}" ] && [ -d "$p" ] && [ -e "$p/enable" ] && [ -e "$p/functions" ]; then
            echo "$p"
            return 0
        fi
    done
    return 1
}

sys_write() {
    local p="$1" v="$2"
    [ -e "$p" ] || return 1
    echo "$v" > "$p" 2>/dev/null || return 1
    return 0
}

setup_usb_configfs_gadget() {
    local mode="$1"
    local gad="/sys/kernel/config/usb_gadget/peacock"
    local udc="${USB_UDC_NAME:-}"
    local first_udc=""

    mkdir -p /sys/kernel/config 2>/dev/null || true
    mountpoint -q /sys/kernel/config 2>/dev/null || mount -t configfs configfs /sys/kernel/config >/dev/null 2>&1 || true
    [ -d /sys/kernel/config/usb_gadget ] || return 1

    if [ -d /sys/class/udc ]; then
        first_udc="$(ls /sys/class/udc 2>/dev/null | head -n1 || true)"
    fi
    if [ -n "$udc" ] && [ ! -d "/sys/class/udc/$udc" ]; then
        echo "rndis: configured UDC '$udc' missing, falling back to auto-detect" >> "$logf"
        udc=""
    fi
    if [ -z "$udc" ]; then
        udc="$first_udc"
    fi
    [ -n "$udc" ] || return 1
    [ -d "/sys/class/udc/$udc" ] || return 1

    if [ -d "$gad" ]; then
        printf '%s' '' > "$gad/UDC" 2>/dev/null || true
    else
        mkdir -p "$gad" || return 1
    fi

    printf '%s' "0x${USB_ID_VENDOR}" > "$gad/idVendor" 2>/dev/null || true
    printf '%s' "0x${USB_ID_PRODUCT_RNDIS}" > "$gad/idProduct" 2>/dev/null || true

    mkdir -p "$gad/strings/0x409" "$gad/configs/c.1/strings/0x409" || return 1
    printf '%s' "PEACOCK-DAISY-DEBUG" > "$gad/strings/0x409/serialnumber" 2>/dev/null || true
    printf '%s' "Peacock" > "$gad/strings/0x409/manufacturer" 2>/dev/null || true
    printf '%s' "Peacock Debug" > "$gad/strings/0x409/product" 2>/dev/null || true
    printf '%s' "RNDIS" > "$gad/configs/c.1/strings/0x409/configuration" 2>/dev/null || true
    printf '%s' 120 > "$gad/configs/c.1/MaxPower" 2>/dev/null || true

    for l in "$gad/configs/c.1/"*; do
        [ -L "$l" ] && rm -f "$l" 2>/dev/null || true
    done

    mkdir -p "$gad/functions/rndis.usb0" || return 1
    printf '%s' "02:1A:11:00:00:01" > "$gad/functions/rndis.usb0/dev_addr" 2>/dev/null || true
    printf '%s' "02:1A:11:00:00:02" > "$gad/functions/rndis.usb0/host_addr" 2>/dev/null || true
    ln -snf "$gad/functions/rndis.usb0" "$gad/configs/c.1/rndis.usb0" 2>/dev/null || true

    printf '%s' "$udc" > "$gad/UDC" 2>/dev/null || return 1
    echo "$udc"
    return 0
}

usb_base="$(find_usb_base || true)"
if [ -z "$usb_base" ]; then
    for _ in 1 2 3 4 5; do
        [ -d /sys/class/udc ] && [ -n "$(ls /sys/class/udc 2>/dev/null | head -n1 || true)" ] && break
        sleep 1
    done
    configfs_udc="$(setup_usb_configfs_gadget "$USB_MODE" 2>/dev/null || true)"
    if [ -z "$configfs_udc" ]; then
        echo "rndis: no android_usb/configfs gadget found (udc=$(ls /sys/class/udc 2>/dev/null | tr '\n' ' ' || true))" >> "$logf"
        exit 0
    fi
    echo "rndis: configfs udc=$configfs_udc" >> "$logf"
    /sbin/mdev -s >/dev/null 2>&1 || true
    sleep 1
else
    sys_write "$usb_base/enable" 0 || true
    sys_write "$usb_base/idVendor" "$USB_ID_VENDOR" || true
    sys_write "$usb_base/idProduct" "$USB_ID_PRODUCT_RNDIS" || true
    sys_write "$usb_base/iManufacturer" "Peacock" || true
    sys_write "$usb_base/iProduct" "Peacock Debug" || true
    sys_write "$usb_base/iSerial" "PEACOCK-DAISY-DEBUG" || true

    case "$USB_MODE" in
        rndis)
            sys_write "$usb_base/f_rndis/wceis" "1" || true
            sys_write "$usb_base/functions" "rndis" || true
            ;;
        *)
            sys_write "$usb_base/functions" "$USB_MODE" || true
            ;;
    esac

    /sbin/mdev -s >/dev/null 2>&1 || true
    sys_write "$usb_base/enable" 1 || true
    sleep 1
fi

net_if=""
for _ in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do
    for p in usb0 USB0 rndis0 RNDIS0 eth0 ETH0; do
        if [ -d "/sys/class/net/$p" ] || [ -L "/sys/class/net/$p" ]; then
            net_if="$p"
            break
        fi
    done
    [ -n "$net_if" ] && break
    sleep 1
done

if [ -z "$net_if" ]; then
    echo "rndis: no net iface (have=$(ls /sys/class/net 2>/dev/null | tr '\n' ' ' || true))" >> "$logf"
    exit 0
fi

echo "$net_if" > /run/peacock-debug-rndis.if

ipbin="$(command -v ip || true)"
if [ -n "$ipbin" ]; then
    "$ipbin" link set "$net_if" up >/dev/null 2>&1 || true
    "$ipbin" addr flush dev "$net_if" >/dev/null 2>&1 || true
    "$ipbin" addr add "$RNDIS_ADDR" dev "$net_if" >/dev/null 2>&1 || true
else
    ifconfig "$net_if" "${RNDIS_ADDR%/*}" netmask 255.255.255.0 up >/dev/null 2>&1 || true
fi

echo "rndis: if=$net_if ip=$RNDIS_ADDR" >> "$logf"

udhcpd_bin=""
if command -v udhcpd >/dev/null 2>&1; then
    udhcpd_bin="$(command -v udhcpd)"
elif [ -x /usr/local/sbin/peacock-busybox ] && /usr/local/sbin/peacock-busybox --list 2>/dev/null | grep -qx udhcpd; then
    udhcpd_bin="/usr/local/sbin/peacock-busybox udhcpd"
elif [ -x /usr/local/sbin/busybox ] && /usr/local/sbin/busybox --list 2>/dev/null | grep -qx udhcpd; then
    udhcpd_bin="/usr/local/sbin/busybox udhcpd"
elif command -v busybox >/dev/null 2>&1 && busybox --list 2>/dev/null | grep -qx udhcpd; then
    udhcpd_bin="$(command -v busybox) udhcpd"
fi

if [ -n "$udhcpd_bin" ]; then
    cat > /run/peacock-debug-udhcpd.conf <<CFG
start $RNDIS_DHCP_START
end $RNDIS_DHCP_END
interface $net_if
option subnet 255.255.255.0
option router ${RNDIS_ADDR%/*}
option dns ${RNDIS_ADDR%/*}
option lease 3600
pidfile /run/peacock-debug-udhcpd.pid
lease_file /run/peacock-debug-udhcpd.leases
CFG

    if [ -f /run/peacock-debug-udhcpd.pid ]; then
        kill "$(cat /run/peacock-debug-udhcpd.pid 2>/dev/null || true)" >/dev/null 2>&1 || true
        rm -f /run/peacock-debug-udhcpd.pid
    fi

    # shellcheck disable=SC2086
    sh -c "$udhcpd_bin -f /run/peacock-debug-udhcpd.conf" >> "$logf" 2>&1 &
    sleep 1
    if [ -f /run/peacock-debug-udhcpd.pid ]; then
        echo "rndis: dhcp up" >> "$logf"
    else
        echo "rndis: dhcp failed" >> "$logf"
    fi
fi

exit 0
