#!/bin/bash # Composite USB gadget for the robot, via configfs: NCM Ethernet (usb0) + ACM serial (ttyGS0). # Installed as /usr/local/sbin/robot-usb-gadget and run by robot-usb-gadget.service. # robot-usb-gadget start | stop set -euo pipefail G=/sys/kernel/config/usb_gadget/hermes HOST_MAC=02:68:65:72:6d:01 # the host's end of the link (locally administered, spells "herm") DEV_MAC=02:68:65:72:6d:02 # the robot's end (usb0) stop() { [ -d "$G" ] || return 0 cd "$G" echo "" > UDC 2>/dev/null || true rm -f configs/c.1/ncm.usb0 configs/c.1/acm.usb0 rmdir configs/c.1/strings/0x409 configs/c.1 functions/ncm.usb0 functions/acm.usb0 strings/0x409 2>/dev/null || true cd / rmdir "$G" 2>/dev/null || true } start() { modprobe libcomposite mountpoint -q /sys/kernel/config || mount -t configfs none /sys/kernel/config stop udc= for _ in $(seq 40); do # dwc2 can take a moment to register after boot udc=$(ls /sys/class/udc 2>/dev/null | head -n1 || true) [ -n "$udc" ] && break sleep 0.5 done [ -n "$udc" ] || { echo "robot-usb-gadget: no UDC (is dtoverlay=dwc2,dr_mode=peripheral set?)" >&2; exit 1; } mkdir -p "$G" cd "$G" echo 0x1d6b > idVendor # Linux Foundation echo 0x0104 > idProduct # multifunction composite gadget echo 0x0100 > bcdDevice echo 0x0200 > bcdUSB echo 0xEF > bDeviceClass # composite with interface association descriptors echo 0x02 > bDeviceSubClass echo 0x01 > bDeviceProtocol mkdir -p strings/0x409 echo "$(awk '/^Serial/ {print $3}' /proc/cpuinfo)" > strings/0x409/serialnumber echo "Hermes" > strings/0x409/manufacturer echo "Hermes robot" > strings/0x409/product mkdir -p configs/c.1/strings/0x409 echo "NCM + ACM" > configs/c.1/strings/0x409/configuration echo 250 > configs/c.1/MaxPower mkdir -p functions/ncm.usb0 echo "$HOST_MAC" > functions/ncm.usb0/host_addr echo "$DEV_MAC" > functions/ncm.usb0/dev_addr mkdir -p functions/acm.usb0 ln -s functions/ncm.usb0 configs/c.1/ ln -s functions/acm.usb0 configs/c.1/ echo "$udc" > UDC } case "${1:-}" in start) start ;; stop) stop ;; *) echo "usage: $0 start|stop" >&2; exit 2 ;; esac