2025-06-01 21:28:09 -05:00
|
|
|
|
#!/usr/bin/env bash
|
2025-06-15 11:15:52 -05:00
|
|
|
|
# navka-core.sh - background stealth daemon to present gadget as usb hub of genuine devices
|
|
|
|
|
|
# Proven Pi-5 configfs gadget: HID keyboard+mouse
|
|
|
|
|
|
# Still need Web Cam Support + stereo UAC2
|
2025-06-06 20:45:09 -05:00
|
|
|
|
|
|
|
|
|
|
# navka-core – one-shot gadget bring-up for Pi-5 / Arch-ARM
|
2025-06-01 21:28:09 -05:00
|
|
|
|
set -euo pipefail
|
2025-06-06 20:25:26 -05:00
|
|
|
|
|
2025-06-06 20:45:09 -05:00
|
|
|
|
# 1) Ensure the dwc2 peripheral overlay is active exactly once
|
|
|
|
|
|
CFG=/boot/config.txt
|
|
|
|
|
|
grep -q 'dtoverlay=dwc2,dr_mode=peripheral' "$CFG" || echo 'dtoverlay=dwc2,dr_mode=peripheral' >> "$CFG"
|
2025-06-06 20:25:26 -05:00
|
|
|
|
|
2025-06-06 20:45:09 -05:00
|
|
|
|
# 2) Load kernel modules (idempotent)
|
2025-06-06 20:55:01 -05:00
|
|
|
|
modprobe dwc2 || { echo "dwc2 not in kernel; abort" >&2; exit 1; }
|
2025-06-06 00:41:32 -05:00
|
|
|
|
modprobe libcomposite || { echo "libcomposite not in kernel; abort" >&2; exit 1; }
|
2025-06-06 20:45:09 -05:00
|
|
|
|
|
|
|
|
|
|
# 3) Mount configfs once
|
2025-06-06 20:25:26 -05:00
|
|
|
|
mountpoint -q /sys/kernel/config || mount -t configfs none /sys/kernel/config
|
2025-06-01 21:28:09 -05:00
|
|
|
|
G=/sys/kernel/config/usb_gadget/navka
|
|
|
|
|
|
|
2025-06-06 20:45:09 -05:00
|
|
|
|
# 4) Tear down any previous half-built gadget
|
2025-06-02 20:18:19 -05:00
|
|
|
|
if [[ -d $G ]]; then
|
2025-06-06 22:10:59 -05:00
|
|
|
|
echo '' >"$G/UDC" 2>/dev/null || true
|
|
|
|
|
|
sleep 0.2
|
2025-06-06 20:55:01 -05:00
|
|
|
|
find "$G/configs" -type l -delete 2>/dev/null || true
|
2025-06-15 17:39:39 -05:00
|
|
|
|
rm -rf "$G" 2>/dev/null || true
|
2025-06-02 20:18:19 -05:00
|
|
|
|
fi
|
2025-06-01 21:28:09 -05:00
|
|
|
|
|
2025-06-06 20:45:09 -05:00
|
|
|
|
# 5) Create gadget (boot-keyboard + UAC2 mic/spkr, 500 mA max)
|
2025-06-01 21:28:09 -05:00
|
|
|
|
mkdir -p "$G"
|
|
|
|
|
|
echo 0x1d6b >"$G/idVendor" # Linux Foundation
|
|
|
|
|
|
echo 0x0104 >"$G/idProduct" # Multifunction Composite Gadget
|
|
|
|
|
|
echo 0x0200 >"$G/bcdUSB"
|
|
|
|
|
|
|
|
|
|
|
|
mkdir -p "$G/strings/0x409"
|
2025-06-06 20:25:26 -05:00
|
|
|
|
echo "$(cat /proc/sys/kernel/random/uuid)" >"$G/strings/0x409/serialnumber"
|
|
|
|
|
|
echo "Navka" >"$G/strings/0x409/manufacturer"
|
|
|
|
|
|
echo "Navka Composite" >"$G/strings/0x409/product"
|
2025-06-01 21:28:09 -05:00
|
|
|
|
|
2025-06-15 20:19:27 -05:00
|
|
|
|
# ----------------------- HID keyboard (usb0) -----------------------
|
2025-06-01 21:28:09 -05:00
|
|
|
|
mkdir -p "$G/functions/hid.usb0"
|
|
|
|
|
|
echo 1 >"$G/functions/hid.usb0/protocol"
|
|
|
|
|
|
echo 1 >"$G/functions/hid.usb0/subclass"
|
|
|
|
|
|
echo 8 >"$G/functions/hid.usb0/report_length"
|
2025-06-15 20:19:27 -05:00
|
|
|
|
printf '\x05\x01\x09\x06\xa1\x01\x05\x07\x19\xe0\x29\xe7\x15\x00\x25\x01'\
|
|
|
|
|
|
'\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x01\x95\x05\x75\x01\x05'\
|
|
|
|
|
|
'\x08\x19\x01\x29\x05\x91\x02\x95\x01\x75\x03\x91\x01\x95\x06\x75\x08'\
|
|
|
|
|
|
'\x15\x00\x25\x65\x05\x07\x19\x00\x29\x65\x81\x00\xc0' \
|
|
|
|
|
|
>"$G/functions/hid.usb0/report_desc"
|
2025-06-01 21:28:09 -05:00
|
|
|
|
|
2025-06-15 20:19:27 -05:00
|
|
|
|
# ----------------------- HID mouse (usb1) --------------------------
|
2025-06-11 22:01:16 -05:00
|
|
|
|
mkdir -p "$G/functions/hid.usb1"
|
2025-06-18 00:03:17 -05:00
|
|
|
|
echo 0 > "$G/functions/hid.usb1/protocol" # Boot mouse
|
|
|
|
|
|
echo 0 > "$G/functions/hid.usb1/subclass"
|
2025-06-11 22:01:16 -05:00
|
|
|
|
echo 4 > "$G/functions/hid.usb1/report_length"
|
2025-06-17 23:44:33 -05:00
|
|
|
|
|
|
|
|
|
|
# 3 buttons, X, Y, Wheel → total 4 bytes
|
2025-06-18 23:46:32 -05:00
|
|
|
|
# printf '\x05\x01' # Usage Page (Generic Desktop)
|
|
|
|
|
|
# printf '\x09\x02' # Usage (Mouse)
|
|
|
|
|
|
# printf '\xA1\x01' # Collection (Application)
|
|
|
|
|
|
# printf '\x09\x01' # Usage (Pointer)
|
|
|
|
|
|
# printf '\xA1\x00' # Collection (Physical)
|
|
|
|
|
|
# printf '\x05\x09' # Usage Page (Button)
|
|
|
|
|
|
# printf '\x19\x01' # Usage Min (1)
|
|
|
|
|
|
# printf '\x29\x03' # Usage Max (3)
|
|
|
|
|
|
# printf '\x15\x00' # Logical Min (0)
|
|
|
|
|
|
# printf '\x25\x01' # Logical Max (1)
|
|
|
|
|
|
# printf '\x95\x03' # Report Count (3)
|
|
|
|
|
|
# printf '\x75\x01' # Report Size (1)
|
|
|
|
|
|
# printf '\x81\x02' # Input (Data,Var,Abs) – 3 button bits
|
|
|
|
|
|
# printf '\x95\x01' # Report Count (1)
|
|
|
|
|
|
# printf '\x75\x05' # Report Size (5)
|
|
|
|
|
|
# printf '\x81\x03' # Input (Cnst,Var,Abs) – 5 pad bits
|
|
|
|
|
|
# printf '\x05\x01' # Usage Page (Generic Desktop)
|
|
|
|
|
|
# printf '\x09\x30' # Usage (X)
|
|
|
|
|
|
# printf '\x09\x31' # Usage (Y)
|
|
|
|
|
|
# printf '\x15\x81' # Logical Min (-127)
|
|
|
|
|
|
# printf '\x25\x7F' # Logical Max (127)
|
|
|
|
|
|
# printf '\x75\x08' # Report Size (8)
|
|
|
|
|
|
# printf '\x95\x02' # Report Count (2)
|
|
|
|
|
|
# printf '\x81\x06' # Input (Data,Var,Rel) – X, Y
|
|
|
|
|
|
# printf '\x09\x38' # Usage (Wheel)
|
|
|
|
|
|
# printf '\x15\x81' # Logical Min (-127)
|
|
|
|
|
|
# printf '\x25\x7F' # Logical Max (127)
|
|
|
|
|
|
# printf '\x75\x08' # Report Size (8)
|
|
|
|
|
|
# printf '\x95\x01' # Report Count (1)
|
|
|
|
|
|
# printf '\x81\x06' # Input (Data,Var,Rel) – Wheel
|
|
|
|
|
|
# printf '\xC0\xC0' # End collections
|
|
|
|
|
|
# >"$G/functions/hid.usb1/report_desc"
|
|
|
|
|
|
printf '\x05\x01\x09\x02\xa1\x01\x09\x01\xa1\x00'\
|
|
|
|
|
|
'\x05\x09\x19\x01\x29\x03\x15\x00\x25\x01\x95\x03\x75\x01\x81\x02'\
|
|
|
|
|
|
'\x95\x01\x75\x05\x81\x03'\
|
|
|
|
|
|
'\x05\x01\x09\x30\x09\x31\x09\x38\x15\x81\x25\x7f\x75\x08\x95\x03\x81\x06'\
|
|
|
|
|
|
'\xc0\xc0' >"$G/functions/hid.usb1/report_desc"
|
2025-06-11 22:01:16 -05:00
|
|
|
|
|
2025-06-06 20:55:01 -05:00
|
|
|
|
# # -- UAC2 Audio
|
|
|
|
|
|
# mkdir -p $G/functions/uac2.usb0
|
|
|
|
|
|
# echo 48000 > $G/functions/uac2.usb0/c_srate
|
|
|
|
|
|
# echo 2 > $G/functions/uac2.usb0/c_ssize
|
|
|
|
|
|
# echo 2 > $G/functions/uac2.usb0/p_chmask
|
2025-06-06 20:25:26 -05:00
|
|
|
|
|
2025-06-15 20:19:27 -05:00
|
|
|
|
# ----------------------- configuration -----------------------------
|
2025-06-06 23:03:17 -05:00
|
|
|
|
mkdir -p "$G/configs/c.1/strings/0x409"
|
|
|
|
|
|
echo 500 > "$G/configs/c.1/MaxPower"
|
|
|
|
|
|
echo "Config 1" > "$G/configs/c.1/strings/0x409/configuration"
|
2025-06-06 20:55:01 -05:00
|
|
|
|
|
2025-06-15 20:19:27 -05:00
|
|
|
|
# 6) Finally bind to first available UDC
|
2025-06-06 20:45:09 -05:00
|
|
|
|
ln -s $G/functions/hid.usb0 $G/configs/c.1/
|
2025-06-15 20:19:27 -05:00
|
|
|
|
ln -s $G/functions/hid.usb1 $G/configs/c.1/
|
2025-06-06 20:55:01 -05:00
|
|
|
|
# ln -s $G/functions/uac2.usb0 $G/configs/c.1/
|
2025-06-01 21:28:09 -05:00
|
|
|
|
|
2025-06-15 20:19:27 -05:00
|
|
|
|
# 7) Finally bind to first available UDC
|
2025-06-06 20:45:09 -05:00
|
|
|
|
echo $(ls /sys/class/udc | head -n1) > $G/UDC
|
2025-06-15 20:19:27 -05:00
|
|
|
|
echo "[navka-core] gadget ready (keyboard on hidg0, mouse on hidg1)"
|