Debugging methods for FunctionFS Usb gadget in STM32MP1: HDMI-USB C PA10 pin conflict
Hi,
I am working on a functionFS usb gadget based on gmidi. Following the gadget_configfs.rst and using stm32_usbotg_eth_config.sh as starting point was straight forward. After writing the shell script and modifying my device tree configuration to support high-speed OTG in the usb-c port as explained in the USB device tree guide, the usb gadget loaded with no errors and it was recognised by Mac, Windows and Linux hosts as usb-midi.
USB-MIDI Shell script:
configfs="/sys/kernel/config/usb_gadget"
g=g1 #Gadget name
c=c.1 #Configuration name
d="${configfs}/${g}" #gadget path
func_midi=midi.usb0 #Midi Function declaration
#Product and Vendor for getting recognised
VENDOR_ID="0x1d6b"
PRODUCT_ID="0x0104"
#Take the serial from the MP1 and make it a serial for our USB MIDI
get_mac_address_from_serial_number(){
sha1sum /proc/device-tree/serial-number \
| fold -1 \
| sed -n '1{h;d};2{y/1235679abdef/000444888ccc/;H;d};13{g;s/\n//g;p;q};s/^/:/;N;H;d'
}
#To call the gadget
do_start() {
#Call dependacy. We are using FunctionFS so only libcomposite is needed
if [ ! -d ${configfs} ]; then #Check if dependancy is already enabled
modprobe libcomposite
if [ ! -d ${configfs} ]; then
exit 1
fi
fi
if [ -d ${d} ]; then
exit 0
fi
udc=$(ls -1 /sys/class/udc/) #Check if there is a UDC driver
if [ -z $udc ]; then
echo "No UDC driver registered"
exit 1
fi
#Create main file structure
mkdir "${d}"
echo ${VENDOR_ID} > "${d}/idVendor"
echo ${PRODUCT_ID} > "${d}/idProduct"
echo 0x0200 > "${d}/bcdUSB"
echo "0xEF" > "${d}/bDeviceClass"
echo "0x02" > "${d}/bDeviceSubClass"
echo "0x01" > "${d}/bDeviceProtocol"
echo "0x0100" > "${d}/bcdDevice"
#Sign the driver
mkdir -p "${d}/strings/0x409"
tr -d '\0' < /proc/device-tree/serial-number > "${d}/strings/0x409/serialnumber"
echo "xxxx" > "${d}/strings/0x409/manufacturer"
echo "***" > "${d}/strings/0x409/product"
# Config
mkdir -p "${d}/configs/${c}"
mkdir -p "${d}/configs/${c}/strings/0x409"
echo "Config 1: MIDI" > "${d}/configs/${c}/strings/0x409/configuration"
echo 500 > "${d}/configs/${c}/MaxPower"
echo 0xC0 > "${d}/configs/${c}/bmAttributes" # self powered device
#MIDI function configuration
mkdir -p "${d}/functions/${func_midi}"
# Set up the midi device and serial after RNDIS
ln -s "${d}/functions/${func_midi}" "${d}/configs/${c}"
echo "${udc}" > "${d}/UDC" #Enable the driver
sleep 0.2 # Wait a bit
}
#To eject the gadget
do_stop() {
echo "" > "${d}/UDC" #Empty the UDC
#Delete all contents based on their priorities
rm -f "${d}/os_desc/${c}"
[ -d "${d}/configs/${c}/${func_midi}" ] &&rm -f "${d}/configs/${c}/${func_midi}"
[ -d "${d}/strings/0x409/" ] && rmdir "${d}/strings/0x409/"
[ -d "${d}/configs/${c}/strings/0x409" ] && rmdir "${d}/configs/${c}/strings/0x409"
[ -d "${d}/configs/${c}" ] && rmdir "${d}/configs/${c}"
[ -d "${d}/functions/${func_midi}" ] && rmdir "${d}/functions/${func_midi}"
[ -d "${d}" ] && rmdir "${d}"
}
case $1 in
start)
echo "Starting midi-usb gadget"
do_start $2
;;
stop)
echo "Stoping midi-usb gadget"
do_stop
;;
*)
echo "Usage: $0 (stop | start)"
;;
esacThe issue is that every few minutes the host stops sending and receiving messages. I tried multiple cables and hosts and the result is that midi data will stop arriving to the host and the MP1 in the same time, after a couple of minutes. If I reset the usb cable or stop and start the usb gadget data will flow again for a similar period of time.
In order to debug this issue I used usbmon on the MP1 and wireshark on a host Mac. On the host mac I could see that when the driver freezes it receives a URB with an unknown request and then a URB with an abort request. After these two messages no midi messages can go in or out but the device is still seen as a connected usb-midi device on the host.
Trying to understand why this happens I looked at f_midi.c. There I could see that an abort URB is send when hardware forces ep reset.
/* this endpoint is normally active while we're configured */
case -ECONNABORTED: /* hardware forced ep reset */
case -ECONNRESET: /* request dequeued */
case -ESHUTDOWN: /* disconnect from host */At this point I am looking for ways to debug why the hardware forces ep reset and when but I can not find a way to debug this. Any ideas or points will be highly appreciated.
