e0bc4785e9
Flashes the diskOS custom UI onto the FiiO Snowsky Disc over Ingenic mask-ROM USB, building the image from your own stock firmware. Runs from source via install.sh.
89 lines
3.0 KiB
Bash
Executable File
89 lines
3.0 KiB
Bash
Executable File
#!/bin/sh
|
|
# diskOS dev/recovery: USB CDC-ACM serial console on the device USB-C port.
|
|
# Host enumerates 0525:a4a7 -> /dev/ttyACM0 -> root shell (raw, no login).
|
|
#
|
|
# Robust against the failure that killed the previous attempt: the stock
|
|
# serial_config.sh binds the UDC exactly once and never retries, so a UDC that
|
|
# registers (or a host that plugs in) a moment later was missed. This runs a
|
|
# persistent supervisor: (re)bind whenever a UDC is present, keep a shell alive
|
|
# on ttyGS0. All steps best-effort + logged to a persistent (rw) partition.
|
|
|
|
LOG=/usr/data/fiio/usbserial.log
|
|
G=/sys/kernel/config/usb_gadget/serial_demo
|
|
|
|
log() { echo "$(date 2>/dev/null) $*" >> "$LOG" 2>/dev/null; }
|
|
|
|
build_gadget() {
|
|
[ -d /sys/kernel/config/usb_gadget ] || mount -t configfs none /sys/kernel/config 2>/dev/null
|
|
[ -d "$G" ] && return 0
|
|
mkdir -p "$G" || return 1
|
|
echo 0x0525 > "$G/idVendor"
|
|
echo 0xa4a7 > "$G/idProduct"
|
|
echo 0x0200 > "$G/bcdUSB"
|
|
echo 0x2400 > "$G/bcdDevice"
|
|
echo 0x02 > "$G/bDeviceClass"
|
|
echo 0x00 > "$G/bDeviceSubClass"
|
|
echo 0x00 > "$G/bDeviceProtocol"
|
|
mkdir -p "$G/strings/0x409"
|
|
echo "INGENIC" > "$G/strings/0x409/manufacturer"
|
|
echo "diskOS Serial" > "$G/strings/0x409/product"
|
|
echo "diskos-serial" > "$G/strings/0x409/serialnumber"
|
|
mkdir -p "$G/configs/c.1/strings/0x409"
|
|
echo 120 > "$G/configs/c.1/MaxPower"
|
|
echo 0x80 > "$G/configs/c.1/bmAttributes"
|
|
echo "serial" > "$G/configs/c.1/strings/0x409/configuration"
|
|
mkdir -p "$G/functions/acm.0"
|
|
ln -sf "$G/functions/acm.0" "$G/configs/c.1/" 2>/dev/null
|
|
log "gadget built"
|
|
}
|
|
|
|
# Best-effort nudge into peripheral mode. dr_mode=otg already auto-switches to
|
|
# device when plugged into a host (CC/pin), so this is only a safety net. Only
|
|
# the unambiguous "device" token is written -- never anything that could select
|
|
# host mode and break enumeration.
|
|
force_device_mode() {
|
|
for f in /sys/devices/platform/*otg*/dwc2_mode \
|
|
/sys/devices/platform/*otg*/dwc2_force_dr_mode \
|
|
/sys/devices/platform/*/13500000.otg/dwc2_mode; do
|
|
[ -e "$f" ] || continue
|
|
echo device > "$f" 2>/dev/null && log "wrote device-mode to $f"
|
|
done
|
|
}
|
|
|
|
bound() { [ -n "$(cat "$G/UDC" 2>/dev/null)" ]; }
|
|
|
|
bind_when_ready() {
|
|
udc=$(ls /sys/class/udc/ 2>/dev/null | head -n1)
|
|
[ -n "$udc" ] || return 1
|
|
echo "$udc" > "$G/UDC" 2>/dev/null && { log "bound UDC=$udc"; return 0; }
|
|
return 1
|
|
}
|
|
|
|
# Delegate the ttyGS0 shell to diskos-debug (the SINGLE owner - fuser-guarded + self-respawning).
|
|
# Two independent shell respawners on one tty is the classic "answers once then goes silent" wedge,
|
|
# so this script no longer binds its own shell; it only builds the gadget and asks diskos-debug to
|
|
# attach the one shell. Idempotent: serial-on is a no-op if a shell already owns ttyGS0.
|
|
DEBUG=/usr/project/diskos-debug.sh
|
|
ensure_shell() {
|
|
[ -c /dev/ttyGS0 ] || return 0
|
|
[ -x "$DEBUG" ] && "$DEBUG" serial-on >/dev/null 2>&1
|
|
}
|
|
|
|
main() {
|
|
: > "$LOG" 2>/dev/null
|
|
log "S99usbserial start"
|
|
build_gadget
|
|
force_device_mode
|
|
while true; do
|
|
bound || bind_when_ready
|
|
ensure_shell
|
|
sleep 2
|
|
done
|
|
}
|
|
|
|
case "$1" in
|
|
start) main & ;;
|
|
*) exit 1 ;;
|
|
esac
|
|
exit 0
|