#!/bin/sh
# pocketds-mtp-gadget up|bind|unbind|down
#
# configfs USB-gadget lifecycle for umtprd (FunctionFS mode), driven by
# umtp-responder.service. The gadget skeleton and the functionfs mount
# persist across service restarts — only the UDC is unbound on stop.
# Tearing the whole gadget down on every stop races the kernel's ffs
# teardown (the umount returns EBUSY until the daemon's endpoint fds
# finish closing) and the next start then inherits a stale ffs instance
# whose ep0 never accepts descriptors, hanging the daemon before READY.
# `bind` is a separate verb because the UDC may only be bound after
# umtprd has written the descriptors to ep0 — the service runs it from
# ExecStartPost, after umtprd's READY=1.

set -eu

G=/sys/kernel/config/usb_gadget/pocketds-mtp
FFS=/dev/ffs-mtp

up() {
    if [ ! -d "$G" ]; then
        mkdir -p "$G"
        echo 0x1d6b > "$G/idVendor"
        echo 0x0100 > "$G/idProduct"
        mkdir -p "$G/strings/0x409"
        cat /sys/devices/soc0/serial_number 2>/dev/null > "$G/strings/0x409/serialnumber" \
            || echo 0123456789 > "$G/strings/0x409/serialnumber"
        echo AYANEO > "$G/strings/0x409/manufacturer"
        echo "Pocket DS" > "$G/strings/0x409/product"
        mkdir -p "$G/configs/c.1/strings/0x409"
        echo MTP > "$G/configs/c.1/strings/0x409/configuration"
        echo 500 > "$G/configs/c.1/MaxPower"
        mkdir -p "$G/functions/ffs.mtp"
        ln -sf "$G/functions/ffs.mtp" "$G/configs/c.1/ffs.mtp"
    fi
    if ! mountpoint -q "$FFS"; then
        mkdir -p "$FFS"
        mount -t functionfs mtp "$FFS"
    fi
}

bind() {
    udc=$(ls /sys/class/udc | head -n 1)
    [ -n "$udc" ]
    echo "$udc" > "$G/UDC"
}

unbind() {
    [ -e "$G/UDC" ] || return 0
    echo "" > "$G/UDC" 2>/dev/null || :
}

down() {
    [ -d "$G" ] || return 0
    unbind
    i=0
    while mountpoint -q "$FFS" && ! umount "$FFS" 2>/dev/null; do
        i=$((i + 1))
        [ "$i" -ge 10 ] && { umount -l "$FFS" 2>/dev/null || :; break; }
        sleep 0.2
    done
    rm -f "$G/configs/c.1/ffs.mtp"
    rmdir "$G/configs/c.1/strings/0x409" "$G/configs/c.1" \
          "$G/functions/ffs.mtp" "$G/strings/0x409" "$G" 2>/dev/null || :
}

case "${1:-}" in
    up|bind|unbind|down) "$1" ;;
    *) echo "usage: $0 up|bind|unbind|down" >&2; exit 2 ;;
esac
