onboard audio: JMISC HPH wiring, UCM fix, update scripts for git deploy
This commit is contained in:
Executable
+132
@@ -0,0 +1,132 @@
|
||||
#!/bin/bash
|
||||
# configure-usb-audio.sh
|
||||
# Configure the Arduino Uno Q as a composite USB gadget:
|
||||
# UAC1 (USB Audio Class) + gmidi (USB MIDI)
|
||||
#
|
||||
# The host sees one device with both an audio sink and a MIDI port,
|
||||
# allowing MIDI input over the same USB connection as audio output.
|
||||
#
|
||||
# Based on Linux USB gadget configfs setup.
|
||||
# The Uno Q's USB peripheral controller is exposed via configfs.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
GADGET_DIR="/sys/kernel/config/usb_gadget"
|
||||
GADGET_NAME="g1"
|
||||
UDC_DIR="/sys/class/udc"
|
||||
|
||||
# Gadget config
|
||||
VID="0x2341" # Arduino VID
|
||||
PID="0x006A" # Custom PID (Uno Q audio + MIDI)
|
||||
SERIAL="$(cat /sys/firmware/devicetree/base/serial-number 2>/dev/null | tr -d '\0' || cat /proc/cpuinfo 2>/dev/null | grep Serial | head -1 | awk '{print $3}' || echo 'UnoQ')"
|
||||
MANUFACTURER="Arduino"
|
||||
PRODUCT="Uno Q Audio Synth"
|
||||
|
||||
# USB audio params
|
||||
CHANNELS=2 # stereo out
|
||||
SAMPLE_RATE=48000
|
||||
SAMPLE_SIZE=2 # bytes (2 = 16-bit; kernel UAC1 gadget expects bytes, not bits)
|
||||
|
||||
# Find UDC (USB Device Controller)
|
||||
find_udc() {
|
||||
for controller in "$UDC_DIR"/*; do
|
||||
if [ -d "$controller" ]; then
|
||||
basename "$controller"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
echo "ERROR: No UDC found" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
create_gadget() {
|
||||
local udc="$1"
|
||||
|
||||
# Remove existing gadget if present
|
||||
if [ -d "$GADGET_DIR/$GADGET_NAME" ]; then
|
||||
echo "" > "$GADGET_DIR/$GADGET_NAME/UDC" 2>/dev/null || true
|
||||
for _ in $(seq 1 50); do
|
||||
if [ ! -f "$GADGET_DIR/$GADGET_NAME/UDC" ] || [ -z "$(cat "$GADGET_DIR/$GADGET_NAME/UDC" 2>/dev/null)" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
for config in "$GADGET_DIR/$GADGET_NAME/configs"/*/; do
|
||||
config=$(basename "$config")
|
||||
for func in "$GADGET_DIR/$GADGET_NAME/configs/$config/"*.*/; do
|
||||
func=$(basename "$func")
|
||||
[ -L "$GADGET_DIR/$GADGET_NAME/configs/$config/$func" ] && rm -f "$GADGET_DIR/$GADGET_NAME/configs/$config/$func"
|
||||
done
|
||||
rmdir "$GADGET_DIR/$GADGET_NAME/configs/$config" 2>/dev/null || true
|
||||
done
|
||||
for func in "$GADGET_DIR/$GADGET_NAME/functions"/*/; do
|
||||
func=$(basename "$func")
|
||||
rmdir "$GADGET_DIR/$GADGET_NAME/functions/$func" 2>/dev/null || true
|
||||
done
|
||||
rmdir "$GADGET_DIR/$GADGET_NAME" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
mkdir -p "$GADGET_DIR/$GADGET_NAME"
|
||||
echo "$VID" > "$GADGET_DIR/$GADGET_NAME/idVendor"
|
||||
echo "$PID" > "$GADGET_DIR/$GADGET_NAME/idProduct"
|
||||
echo "0x0100" > "$GADGET_DIR/$GADGET_NAME/bcdDevice"
|
||||
echo "0x0200" > "$GADGET_DIR/$GADGET_NAME/bcdUSB"
|
||||
|
||||
mkdir -p "$GADGET_DIR/$GADGET_NAME/strings/0x409"
|
||||
echo "$SERIAL" > "$GADGET_DIR/$GADGET_NAME/strings/0x409/serialnumber"
|
||||
echo "$MANUFACTURER" > "$GADGET_DIR/$GADGET_NAME/strings/0x409/manufacturer"
|
||||
echo "$PRODUCT" > "$GADGET_DIR/$GADGET_NAME/strings/0x409/product"
|
||||
|
||||
# Create UAC1 function (audio output, wide host compatibility)
|
||||
mkdir -p "$GADGET_DIR/$GADGET_NAME/functions/uac1.gs0"
|
||||
echo "$CHANNELS" > "$GADGET_DIR/$GADGET_NAME/functions/uac1.gs0/p_chmask"
|
||||
echo "$SAMPLE_RATE" > "$GADGET_DIR/$GADGET_NAME/functions/uac1.gs0/p_srate"
|
||||
echo "$SAMPLE_SIZE" > "$GADGET_DIR/$GADGET_NAME/functions/uac1.gs0/p_ssize"
|
||||
echo "$CHANNELS" > "$GADGET_DIR/$GADGET_NAME/functions/uac1.gs0/c_chmask"
|
||||
echo "$SAMPLE_RATE" > "$GADGET_DIR/$GADGET_NAME/functions/uac1.gs0/c_srate"
|
||||
echo "$SAMPLE_SIZE" > "$GADGET_DIR/$GADGET_NAME/functions/uac1.gs0/c_ssize"
|
||||
|
||||
# Create MIDI function (MIDI input from host)
|
||||
mkdir -p "$GADGET_DIR/$GADGET_NAME/functions/midi.gs0"
|
||||
echo 1 > "$GADGET_DIR/$GADGET_NAME/functions/midi.gs0/in_ports"
|
||||
echo 1 > "$GADGET_DIR/$GADGET_NAME/functions/midi.gs0/out_ports"
|
||||
|
||||
# Create configuration
|
||||
mkdir -p "$GADGET_DIR/$GADGET_NAME/configs/c.1"
|
||||
mkdir -p "$GADGET_DIR/$GADGET_NAME/configs/c.1/strings/0x409"
|
||||
echo "Audio + MIDI" > "$GADGET_DIR/$GADGET_NAME/configs/c.1/strings/0x409/configuration"
|
||||
echo 250 > "$GADGET_DIR/$GADGET_NAME/configs/c.1/MaxPower"
|
||||
|
||||
# Link both functions to the same config (composite device)
|
||||
ln -s "$GADGET_DIR/$GADGET_NAME/functions/uac1.gs0" "$GADGET_DIR/$GADGET_NAME/configs/c.1/"
|
||||
ln -s "$GADGET_DIR/$GADGET_NAME/functions/midi.gs0" "$GADGET_DIR/$GADGET_NAME/configs/c.1/"
|
||||
|
||||
# Bind to UDC
|
||||
echo "$udc" > "$GADGET_DIR/$GADGET_NAME/UDC"
|
||||
echo "USB gadget '$GADGET_NAME' bound to $udc (UAC1 audio + gmidi)"
|
||||
}
|
||||
|
||||
case "${1:-start}" in
|
||||
start)
|
||||
udc=$(find_udc)
|
||||
create_gadget "$udc"
|
||||
;;
|
||||
stop)
|
||||
if [ -d "$GADGET_DIR/$GADGET_NAME" ]; then
|
||||
udc=$(cat "$GADGET_DIR/$GADGET_NAME/UDC" 2>/dev/null || true)
|
||||
[ -n "$udc" ] && echo "" > "$GADGET_DIR/$GADGET_NAME/UDC" 2>/dev/null || true
|
||||
fi
|
||||
echo "USB gadget '$GADGET_NAME' stopped"
|
||||
;;
|
||||
status)
|
||||
if [ -d "$GADGET_DIR/$GADGET_NAME/UDC" ]; then
|
||||
echo "Gadget: $(cat "$GADGET_DIR/$GADGET_NAME/UDC" 2>/dev/null || echo 'not bound')"
|
||||
else
|
||||
echo "Gadget: not configured"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|status}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user