Struggling to set up a composite ethernet / audio / mass storage Linux USB gadget
by struppel from LinuxQuestions.org on (#5DS0M)
I would like to set up a Linux USB gadget with multiple device functions. When plugged in to a host device (Windows/Linux/Android) the Linux system should be detected as an Audio Device (UAC1/UAC2 Device) with audio in- and output, as an ethernet port to establish to communicate over USB and as a mass storage device to transfer files easily.
I am already able to configure all of these functionalities individually and they work fine. But when bring them together (see script below), I have problems with the UAC1 audio device at the host. Mass storage and ethernet work fine at the host device (in my case Windows 10). Also the Audio Gagdet shows up in the device manager, but with an error code: The device cannot be started (code 10).
I have already ruled out that it is due to mass storage, because mass storage gadget and audio gadget work fine together. Therefore, I think that the problem is due to the interaction between the ethernet (RNDIS) and the audio gadget.
A big part of my code is based on this script:
https://gist.github.com/Gadgetoid/c5...4c3e77360011e2
Does someone know how to fix this problem?
Here is my script:
Code:
#!/bin/bash
ID_VENDOR="0x1d6b"
ID_PRODUCT="0x0104"
MAC_HOST="00:dc:c8:f7:75:14"
MAC_DEV="00:dd:dc:eb:6d:a1"
GADGET_NAME="xy"
#Load libcomposite if not if not already loaded.
if [ ! -d /sys/kernel/config/usb_gadget ]; then
modprobe libcomposite
fi
mount none cfg -t configfs
# Create USB Gadget
mkdir /sys/kernel/config/usb_gadget/$GADGET_NAME
cd /sys/kernel/config/usb_gadget/$GADGET_NAME
# Configure USB Device
echo "0x0200" > bcdUSB
echo "0x02" > bDeviceClass
echo "0x00" > bDeviceSubClass
echo "0x3066" > bcdDevice
echo $ID_VENDOR > idVendor
echo $ID_PRODUCT > idProduct
# Windows extensions to force config
echo "1" > os_desc/use
echo "0xcd" > os_desc/b_vendor_code
echo "MSFT100" > os_desc/qw_sign
# Device Descriptors
mkdir strings/0x409
echo "000001" > strings/0x409/serialnumber
echo "xxy" > strings/0x409/manufacturer
echo "xxy" > strings/0x409/product
## Config #1 for OSX / Linux
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "CDC Mass Audio+Storage+RNDIS" > configs/c.1/strings/0x409/configuration
#mkdir functions/ecm.usb0 # OSX/Linux
mkdir functions/rndis.usb0 # Windows
mkdir functions/mass_storage.sonoStorage
# Config Audio Device
mkdir functions/uac1.usb0
echo 0x1 > functions/uac1.usb0/c_chmask
echo 48000 > functions/uac1.usb0/c_srate
echo 0xf > functions/uac1.usb0/p_chmask
echo 48000 > functions/uac1.usb0/p_srate
echo 250 > configs/c.1/MaxPower
# Config Mass Storage
echo "/dev/mmcblk0p1" > functions/mass_storage.sonoStorage/lun.0/file
echo 0 > functions/mass_storage.sonoStorage/stall
echo 0 > functions/mass_storage.sonoStorage/lun.0/cdrom
echo 0 > functions/mass_storage.sonoStorage/lun.0/nofua
echo 1 > functions/mass_storage.sonoStorage/lun.0/removable
echo "sonoStorage" > functions/mass_storage.sonoStorage/lun.0/inquiry_string
# Help Windows to find the right Driver (RNDIS)
echo "RNDIS" > functions/rndis.usb0/os_desc/interface.rndis/compatible_id # Windows RNDIS Drivers
echo "5162001" > functions/rndis.usb0/os_desc/interface.rndis/sub_compatible_id #Windows RNDIS 6.0 Driver
echo $MAC_HOST > functions/rndis.usb0/host_addr
echo $MAC_DEV > functions/rndis.usb0/dev_addr
# Set up the rndis device (only rndis, uac & mass_storage later)
ln -s functions/rndis.usb0 configs/c.1
# Tell Windows to use config #1
ln -s configs/c.1 os_desc
# Show Windows the RNDIS device with
echo "0x02" > bDeviceClass
echo "0x02" > bDeviceSubClass
# Attach the gadget to UDC
echo "fe980000.usb" > UDC
# Give it time to install
sleep 5
# Yank it back
echo "" > UDC
# Load Mass Storage Device to UDC
ln -s functions/mass_storage.sonoStorage configs/c.1
# Load Audio Device to UDC
ln -s functions/uac1.usb0 configs/c.1/
# Reset bDeviceClass to 0x00
# This is essential to make it work in Windows 10
# Basically forces it to use device information
# in the descriptors versus assuming a particular class.
echo "0x00" > bDeviceClass
# Re-attach the gadget
echo "fe980000.usb" > UDC
# Last config
ifconfig usb0 up 10.0.55.1Thanks in advance


I am already able to configure all of these functionalities individually and they work fine. But when bring them together (see script below), I have problems with the UAC1 audio device at the host. Mass storage and ethernet work fine at the host device (in my case Windows 10). Also the Audio Gagdet shows up in the device manager, but with an error code: The device cannot be started (code 10).
I have already ruled out that it is due to mass storage, because mass storage gadget and audio gadget work fine together. Therefore, I think that the problem is due to the interaction between the ethernet (RNDIS) and the audio gadget.
A big part of my code is based on this script:
https://gist.github.com/Gadgetoid/c5...4c3e77360011e2
Does someone know how to fix this problem?
Here is my script:
Code:
#!/bin/bash
ID_VENDOR="0x1d6b"
ID_PRODUCT="0x0104"
MAC_HOST="00:dc:c8:f7:75:14"
MAC_DEV="00:dd:dc:eb:6d:a1"
GADGET_NAME="xy"
#Load libcomposite if not if not already loaded.
if [ ! -d /sys/kernel/config/usb_gadget ]; then
modprobe libcomposite
fi
mount none cfg -t configfs
# Create USB Gadget
mkdir /sys/kernel/config/usb_gadget/$GADGET_NAME
cd /sys/kernel/config/usb_gadget/$GADGET_NAME
# Configure USB Device
echo "0x0200" > bcdUSB
echo "0x02" > bDeviceClass
echo "0x00" > bDeviceSubClass
echo "0x3066" > bcdDevice
echo $ID_VENDOR > idVendor
echo $ID_PRODUCT > idProduct
# Windows extensions to force config
echo "1" > os_desc/use
echo "0xcd" > os_desc/b_vendor_code
echo "MSFT100" > os_desc/qw_sign
# Device Descriptors
mkdir strings/0x409
echo "000001" > strings/0x409/serialnumber
echo "xxy" > strings/0x409/manufacturer
echo "xxy" > strings/0x409/product
## Config #1 for OSX / Linux
mkdir configs/c.1
mkdir configs/c.1/strings/0x409
echo "CDC Mass Audio+Storage+RNDIS" > configs/c.1/strings/0x409/configuration
#mkdir functions/ecm.usb0 # OSX/Linux
mkdir functions/rndis.usb0 # Windows
mkdir functions/mass_storage.sonoStorage
# Config Audio Device
mkdir functions/uac1.usb0
echo 0x1 > functions/uac1.usb0/c_chmask
echo 48000 > functions/uac1.usb0/c_srate
echo 0xf > functions/uac1.usb0/p_chmask
echo 48000 > functions/uac1.usb0/p_srate
echo 250 > configs/c.1/MaxPower
# Config Mass Storage
echo "/dev/mmcblk0p1" > functions/mass_storage.sonoStorage/lun.0/file
echo 0 > functions/mass_storage.sonoStorage/stall
echo 0 > functions/mass_storage.sonoStorage/lun.0/cdrom
echo 0 > functions/mass_storage.sonoStorage/lun.0/nofua
echo 1 > functions/mass_storage.sonoStorage/lun.0/removable
echo "sonoStorage" > functions/mass_storage.sonoStorage/lun.0/inquiry_string
# Help Windows to find the right Driver (RNDIS)
echo "RNDIS" > functions/rndis.usb0/os_desc/interface.rndis/compatible_id # Windows RNDIS Drivers
echo "5162001" > functions/rndis.usb0/os_desc/interface.rndis/sub_compatible_id #Windows RNDIS 6.0 Driver
echo $MAC_HOST > functions/rndis.usb0/host_addr
echo $MAC_DEV > functions/rndis.usb0/dev_addr
# Set up the rndis device (only rndis, uac & mass_storage later)
ln -s functions/rndis.usb0 configs/c.1
# Tell Windows to use config #1
ln -s configs/c.1 os_desc
# Show Windows the RNDIS device with
echo "0x02" > bDeviceClass
echo "0x02" > bDeviceSubClass
# Attach the gadget to UDC
echo "fe980000.usb" > UDC
# Give it time to install
sleep 5
# Yank it back
echo "" > UDC
# Load Mass Storage Device to UDC
ln -s functions/mass_storage.sonoStorage configs/c.1
# Load Audio Device to UDC
ln -s functions/uac1.usb0 configs/c.1/
# Reset bDeviceClass to 0x00
# This is essential to make it work in Windows 10
# Basically forces it to use device information
# in the descriptors versus assuming a particular class.
echo "0x00" > bDeviceClass
# Re-attach the gadget
echo "fe980000.usb" > UDC
# Last config
ifconfig usb0 up 10.0.55.1Thanks in advance