95 lines
2.4 KiB
Bash
Executable File
95 lines
2.4 KiB
Bash
Executable File
#!/bin/bash
|
|
# detect-usb-role.sh — Detect whether USB-C should be gadget or host.
|
|
# Writes result to /run/usb-role for consumption by pd-synth-auto.service.
|
|
#
|
|
# Detection methods (tried in order):
|
|
# 1. extcon — USB cable detection (most reliable on Qualcomm)
|
|
# 2. dwc3 debug — USB controller mode
|
|
# 3. UDC state — if a UDC is bound as configured, we're in gadget mode
|
|
# 4. lsusb — if USB devices appear (after host controller init), we're host
|
|
#
|
|
# Exit code: 0 if role detected, 1 if unknown
|
|
|
|
set -euo pipefail
|
|
|
|
ROLE_FILE="/run/usb-role"
|
|
unset ROLE
|
|
|
|
die() { echo "[USB-ROLE] $*" >&2; exit 1; }
|
|
|
|
# --- Method 1: extcon ---
|
|
check_extcon() {
|
|
for path in /sys/class/extcon/*/state; do
|
|
[ -f "$path" ] || continue
|
|
local state
|
|
state=$(cat "$path" 2>/dev/null || true)
|
|
if echo "$state" | grep -q "USB=1"; then
|
|
echo "gadget"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# --- Method 2: dwc3 debugfs ---
|
|
check_dwc3() {
|
|
local mode_file
|
|
for mode_file in /sys/kernel/debug/usb/dwc3*/mode; do
|
|
[ -f "$mode_file" ] || continue
|
|
local mode
|
|
mode=$(cat "$mode_file" 2>/dev/null || true)
|
|
case "$mode" in
|
|
*peripheral*) echo "gadget"; return 0 ;;
|
|
*host*) echo "host"; return 0 ;;
|
|
esac
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# --- Method 3: UDC state ---
|
|
check_udc() {
|
|
for path in /sys/class/udc/*/state; do
|
|
[ -f "$path" ] || continue
|
|
local state
|
|
state=$(cat "$path" 2>/dev/null || true)
|
|
case "$state" in
|
|
configured) echo "gadget"; return 0 ;;
|
|
esac
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# --- Method 4: USB host devices ---
|
|
check_lsusb() {
|
|
if command -v lsusb &>/dev/null; then
|
|
local count
|
|
count=$(lsusb 2>/dev/null | grep -v "Linux Foundation" | wc -l)
|
|
# If we see non-root-hub devices, likely we're the host
|
|
if [ "$count" -gt 1 ]; then
|
|
echo "host"
|
|
return 0
|
|
fi
|
|
fi
|
|
return 1
|
|
}
|
|
|
|
# Try methods in order
|
|
ROLE=$(check_extcon || check_dwc3 || check_udc || echo "")
|
|
|
|
# If still unknown, check lsusb after brief delay (host controller needs time)
|
|
if [ -z "$ROLE" ]; then
|
|
sleep 2
|
|
ROLE=$(check_lsusb || echo "")
|
|
fi
|
|
|
|
# Write result
|
|
if [ -n "$ROLE" ]; then
|
|
echo "$ROLE" > "$ROLE_FILE"
|
|
echo "[USB-ROLE] Detected: $ROLE"
|
|
exit 0
|
|
else
|
|
echo "[USB-ROLE] Unknown — defaulting to gadget"
|
|
echo "gadget" > "$ROLE_FILE"
|
|
exit 0
|
|
fi
|