usb-ctrl: add a way to mount composite gdts
The usb-vhub has a limited number of usb-gadget ports. The BMC features
might want to attach usb-device count greater than the aspeed-vhub
contains ports. One of the ways to solve the issue could be by attaching
usb-gadget functions to a composite usb interface.
The change brings a way to mount mass_storage and cdc-based devices
under composite device configuration (VID/PID: 1D6B:0104)
This make possible to mount bouth device functions under single
vhub-port.
Tested:
* Insert usb-gadget:mass-storage device is success:
```bash
#: usb-ctrl insert usb0 /tmp/image.iso cdrom
```
* Insert usb-gadget:usb-ecm device for same port is success:
```bash
#: usb-ctrl ecm usb0 on A0:C5:F2:15:B5:89 A0:C5:F2:15:B5:88
```
* the sysfs displays function-descriptors for both interfaces:
```bash
#: root@vegman-r120-020323000A:~# cd /sys/kernel/config/usb_gadget
#: root@vegman-r120-020323000A:~# ls -la ./usb0/functions/
drwxr-xr-x 4 root root 0 Dec 14 12:13 .
drwxr-xr-x 6 root root 0 Dec 14 12:14 ..
drwxr-xr-x 2 root root 0 Dec 14 12:13 ecm.usb0
drwxr-xr-x 3 root root 0 Dec 14 12:11 mass_storage.usb0
```
* eject one of the mounted device works properly, another one stay
online:
```bash
#: usb-ctrl ecm usb0 off
#: ls -la /sys/kernel/config/usb_gadget/usb0/functions/
drwxr-xr-x 3 root root 0 Dec 14 12:19 .
drwxr-xr-x 6 root root 0 Dec 14 12:19 ..
drwxr-xr-x 3 root root 0 Dec 14 12:11 mass_storage.usb0
```
* output on the host side
```bash
#: root@ubuntu:/home/ubuntu# lsusb -d 1d6b:0104 -v
Bus 001 Device 003: ID 1d6b:0104 Linux Foundation Multifunction ...
Device Descriptor:
...
idVendor 0x1d6b Linux Foundation
idProduct 0x0104 Multifunction Composite Gadget
...
Interface Descriptor:
...
bInterfaceClass 8 Mass Storage
bInterfaceSubClass 6 SCSI
bInterfaceProtocol 80 Bulk-Only
iInterface 5 Mass Storage
...
Interface Descriptor:
...
bInterfaceClass 2 Communications
bInterfaceSubClass 6 Ethernet Networking
bInterfaceProtocol 0
iInterface 7 CDC Ethernet Control Model (ECM)
...
```
Change-Id: I6f54ac5c116ee0bb08e9d18c33267f5b401c2c00
Signed-off-by: Igor Kononenko <i.kononenko.e@gmail.com>
diff --git a/usb-ctrl/usb-ctrl b/usb-ctrl/usb-ctrl
index 4d228fd..943e7d4 100644
--- a/usb-ctrl/usb-ctrl
+++ b/usb-ctrl/usb-ctrl
@@ -151,29 +151,49 @@
local intf_type="$4"
local bmc_mac="$3"
local host_mac="$4"
-
- if [ -d "$GADGET_BASE/${name}" ]; then
- echo "Device ${name} already exists" >&2
- return 1
- fi
- mkdir "$GADGET_BASE/${name}"
- cd "$GADGET_BASE/${name}"
-
- echo 0x1d6b > idVendor # Linux Foundation
- echo 0x0105 > idProduct # FunctionFS Gadget
- mkdir strings/0x409
- local machineid
- machineid=$(cat /etc/machine-id)
- local data="OpenBMC USB gadget device serial number"
- local serial
- serial=$( echo -n "${machineid}${data}${machineid}" | \
- sha256sum | cut -b 0-12 )
- echo "$serial" > strings/0x409/serialnumber
- echo "OpenBMC" > strings/0x409/manufacturer
- echo "OpenBMC USB Device" > strings/0x409/product
+ # By default, the gadget is not multifunctional
+ local is_multifunction=false
+ local gadget_function
+ local dev=
gadget_function="functions/${dev_type}.${name}"
- mkdir configs/c.1
+
+ # Checking whether the device is already attached
+ if [ -d "$GADGET_BASE/${name}" ]; then
+ # Checking whether requested function is attached
+ if [ -d "$GADGET_BASE/${name}/${gadget_function}" ]; then
+ echo "Function ${dev_type}.${name} already exists" >&2
+ return 1
+ fi
+
+ # if the requested function is not configured but the device
+ # is connected, it is assumed that the device is multifunctional
+ is_multifunction=true
+ fi
+
+ if [ "${is_multifunction}" = false ]; then
+ mkdir "$GADGET_BASE/${name}"
+ cd "$GADGET_BASE/${name}"
+ echo 0x1d6b > idVendor # Linux Foundation
+ echo 0x0104 > idProduct # Multifunction Composite Gadget
+
+ mkdir strings/0x409
+ local machineid
+ machineid=$(cat /etc/machine-id)
+ local data="OpenBMC USB gadget device serial number"
+ local serial
+ serial=$( echo -n "${machineid}${data}${machineid}" | \
+ sha256sum | cut -b 0-12 )
+ echo "$serial" > strings/0x409/serialnumber
+ echo "OpenBMC" > strings/0x409/manufacturer
+ echo "OpenBMC USB Device" > strings/0x409/product
+
+ mkdir configs/c.1
+ else
+ cd "$GADGET_BASE/${name}"
+ udc=$(cat "$GADGET_BASE/${name}/UDC")
+ fi
+
mkdir "${gadget_function}"
case "${dev_type}" in
mass_storage)
@@ -186,13 +206,18 @@
echo "${host_mac}" > "${gadget_function}/host_addr"
;;
esac
- mkdir configs/c.1/strings/0x409
+ if [ "${is_multifunction}" = false ]; then
+ mkdir configs/c.1/strings/0x409
- echo "Conf 1" > configs/c.1/strings/0x409/configuration
- echo 120 > configs/c.1/MaxPower
+ echo "Conf 1" > configs/c.1/strings/0x409/configuration
+ echo 120 > configs/c.1/MaxPower
+ dev=$(which_dev)
+ else
+ dev=$(cat "$GADGET_BASE/${name}/UDC")
+ # reattach UDC to reconfigure interface descriptors.
+ echo '' > UDC
+ fi
ln -s "${gadget_function}" configs/c.1
- local dev
- dev=$(which_dev)
echo "$dev" > UDC
}
@@ -202,13 +227,27 @@
{
local name="$1"
local dev_type="$2"
+ local func_cnt
+ local udc
+
+ func_cnt=$(find "$GADGET_BASE/${name}/functions/" -maxdepth 1 -mindepth 1 | wc -l)
+ udc=$(cat "$GADGET_BASE/${name}/UDC")
echo '' > "$GADGET_BASE/${name}/UDC"
+ # remove function
rm -f "$GADGET_BASE/${name}/configs/c.1/${dev_type}.${name}"
+ rmdir "$GADGET_BASE/${name}/functions/${dev_type}.${name}"
+
+ # check wether composite device is used
+ if [ "${func_cnt}" -gt 1 ]; then
+ # bring the device back online
+ echo "${udc}" > "$GADGET_BASE/${name}/UDC"
+ return 0;
+ fi
+
rmdir "$GADGET_BASE/${name}/configs/c.1/strings/0x409"
rmdir "$GADGET_BASE/${name}/configs/c.1"
- rmdir "$GADGET_BASE/${name}/functions/${dev_type}.${name}"
rmdir "$GADGET_BASE/${name}/strings/0x409"
rmdir "$GADGET_BASE/${name}"
}