From d58460ebaf5c517ade6c19f36b0caa1724db4f58 Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Sun, 17 May 2026 11:22:55 +0200 Subject: [PATCH] fix(round): modprobe dwc2 in secubox-otg-gadget chain (rpiz UDC was implicit on eye-gadget) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous build had two gadget services enabled at boot: - secubox-eye-gadget.service: ExecStartPre=modprobe dwc2 + libcomposite - secubox-otg-gadget.service: ExecStartPre=modprobe libcomposite + usb_f_* (NO dwc2 — relied on eye-gadget loading it first) When PR #175 disabled secubox-eye-gadget at boot (to stop the UDC conflict), nobody loaded dwc2 anymore. systemd-modules-load reads /etc/modules but the order of dwc2 load vs the otg-gadget service start window was tight — and on the rpiz the journal showed no successful gadget enumeration after the PR #175 image deployed. Defensive fix in two places: 1. secubox-otg-gadget.service: prepend ExecStartPre=/sbin/modprobe dwc2. Drop the ConditionPathIsDirectory=/sys/class/udc gate so the service actually runs and can load dwc2 if it isn't loaded yet (the path is a sysfs dir that exists when its parent /sys/class is mounted — it was harmless, but removing it makes the chain self-bootstrapping). 2. secubox-otg-gadget.sh check_prerequisites(): also modprobe dwc2 (in case the service is invoked manually by an operator), then poll /sys/class/udc for up to 5s waiting for the BCM USB controller to bind asynchronously. Diagnostic message updated to point at the two places to check (dtoverlay + /etc/modules) if no UDC ever shows up. --- remote-ui/common/shell/secubox-otg-gadget.sh | 18 ++++++++++++++++-- remote-ui/round/secubox-otg-gadget.service | 10 +++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/remote-ui/common/shell/secubox-otg-gadget.sh b/remote-ui/common/shell/secubox-otg-gadget.sh index bea67365..63225d16 100755 --- a/remote-ui/common/shell/secubox-otg-gadget.sh +++ b/remote-ui/common/shell/secubox-otg-gadget.sh @@ -178,16 +178,30 @@ check_prerequisites() { fi fi - # Charger les modules nécessaires + # Charger les modules nécessaires. dwc2 must be loaded FIRST — it creates + # the UDC node that the gadget functions bind to. Historically dwc2 was + # loaded implicitly by secubox-eye-gadget.service's ExecStartPre; with + # that service disabled at boot (storage-only mode is opt-in), the + # gadget chain now owns its own dwc2 modprobe explicitly. + modprobe dwc2 2>/dev/null || true modprobe libcomposite 2>/dev/null || true modprobe usb_f_ecm 2>/dev/null || true modprobe usb_f_rndis 2>/dev/null || true modprobe usb_f_acm 2>/dev/null || true modprobe usb_f_mass_storage 2>/dev/null || true + # dwc2 binds asynchronously to the BCM USB controller — wait up to 5s + # for the UDC node to appear (typically <500ms on a Pi Zero W). + for _ in 1 2 3 4 5 6 7 8 9 10; do + if [[ -d /sys/class/udc ]] && [[ -n "$(ls /sys/class/udc 2>/dev/null)" ]]; then + break + fi + sleep 0.5 + done + # Vérifier la présence d'un UDC (USB Device Controller) if [[ ! -d /sys/class/udc ]] || [[ -z "$(ls /sys/class/udc 2>/dev/null)" ]]; then - err "Aucun UDC trouvé — ce script doit être exécuté sur un RPi Zero W" + err "Aucun UDC trouvé — vérifier dtoverlay=dwc2 dans /boot/config.txt et module dwc2 dans /etc/modules" return 1 fi diff --git a/remote-ui/round/secubox-otg-gadget.service b/remote-ui/round/secubox-otg-gadget.service index b740bb5b..e7da9bca 100644 --- a/remote-ui/round/secubox-otg-gadget.service +++ b/remote-ui/round/secubox-otg-gadget.service @@ -17,15 +17,19 @@ After=systemd-modules-load.service Before=network-pre.target Wants=network-pre.target -# Conditions : seulement sur un périphérique avec UDC (RPi Zero W) -ConditionPathIsDirectory=/sys/class/udc +# Conditions : configfs disponible (UDC est crééable dynamiquement via dwc2, +# voir ExecStartPre — pas de pré-condition stricte sur /sys/class/udc). ConditionPathExists=/sys/kernel/config [Service] Type=oneshot RemainAfterExit=yes -# Chargement des modules nécessaires +# Chargement des modules nécessaires. dwc2 est chargé en premier pour créer +# le UDC (sinon le gadget ne peut s'attacher). secubox-eye-gadget.service +# le chargeait historiquement avant; depuis qu'il est désactivé au boot +# (storage-only mode opt-in), on doit le charger ici. +ExecStartPre=/sbin/modprobe dwc2 ExecStartPre=/sbin/modprobe libcomposite ExecStartPre=/sbin/modprobe usb_f_ecm ExecStartPre=/sbin/modprobe usb_f_acm