USB device mode descriptor configuration in linux

1k Views Asked by At

I am currently working on some preliminaries for the integration of Apple CarPlay on an infotainment unit (IU) based on Linux. One requirement of Apple is a USB role reversal, where the IU starts as USB host and becomes a USB device. The Apple device is in the end the USB Host.

The Apple specification requires, that the IU must present a configuration with three different interfaces, an iAP2 interface, a USB NCM control interface and a USB NCM data interface. An example configuration is given in the specification. It defines things like Class, Subclass, Protocol, Attributes, Endpoints, etc. This required configuration seems to be covered by the Device descriptor, configuration descriptor, interface descriptor and endpoint descriptor which is supplied by the device upon connection to a host.

For the NCM support, I activated the USB Gadget support and set Network Control Model (NCM) Support under USB Gadget precomposed configurations. For the USB interface, we use the DWC3 driver. As soon as I set the driver into the device mode, this NCM gadget driver is loaded and a new NIC appears.

How can I configure the USB descriptors of the USB device (the linux based IU) which are sent to the USB host (the Apple device)? As said above, two NCM interfaces and one iAP2 interface must be offered. I have found some hints that this might be done with libcomposite through /sys/kernel/config/usb_gadget/ once the configfs is enabled (e.g. https://unix.stackexchange.com/questions/631138/unable-to-set-usb-gadget-device-class-and-protocol). Is this somewhere documented? Shall different endpoints have subfolders like they have under /sys/bus/usb/devices?

Afaik each interface can have a separate driver. Does this apply for both sides, Host and devicen side? How are the driver and the defined interfaces in the descriptors linked? I assume the USB device driver must have some sort of configuration of the descriptors as well as the associated drivers for each interface? The two NCM interfaces shall be handled by the NCM driver and the iAP2 interface by the iAP2 driver.

1

There are 1 best solutions below

0
SeVe On

As I figured it out now, I would like to answer my own questions and provide some details to this topic. USB Descriptors of the USB device can be configured through the configfs. Therefore CONFIG_USB_CONFIGFS needs to be enabled in buildroot and the corresponding gadget (Network Control Model (CDC NCM) in my case) needs to be selected (<*>). You then need to mount the configfs, create a new folder for the gadget and will find several files in place, where you can customize some of the USB descriptors. This procedure is described in detail in the kernel configuration docu for the Linux USB gadget configurable through configfs. They list an example directory structure which tells you what descriptors are modifyable

  ./strings/0x409/serialnumber
  ./strings/0x409/product
  ./strings/0x409/manufacturer
  ./configs/c.1/bmAttributes
  ./configs/c.1/MaxPower
  ./bcdUSB
  ./bcdDevice
  ./idProduct
  ./idVendor
  ./bMaxPacketSize0
  ./bDeviceProtocol
  ./bDeviceSubClass
  ./bDeviceClass

The Gadget function itself can also offer configuration through the configfs, however this depends on the used gadget. In case of the NCM, the MAC Addresses, the interface name and queue length multiplier for high and super speed can be configured

  ./functions/ncm.usb0/ifname
  ./functions/ncm.usb0/qmult
  ./functions/ncm.usb0/host_addr
  ./functions/ncm.usb0/dev_addr

What is called interface on the USB host side is a function on the USB device side. When you create/associate a new function (like NCM) to the gadget, this will appear as interface on the USB host side (Some functions like NCM will create multiple interfaces). You can assign multiple functions to the gadget (mass storage, MIDI, NCM, ...) and the host will see multiple interfaces. The configuration of those functions/interfaces e.g. regarding endpoints is limited to the files available in the configfs. Endpoints, Packet size, etc regarding NCM is not configurable as this is more or less hardcoded in the source code which also defines the remaining descriptors, not configurable through the configfs and the behavior of the function itself.

If a configuration beyond the offered files in the configfs is required, the source code of the function needs to be changed. But one then needs to take care, that this still reflects the capabilities of the interface!