Kernel USB Gadget
Configfs Interface
Matt Porter
Linaro
Overview
● Prereqs: understand USB
● Linux USB Terminology
● Brief history of USB gadget subsystem
● Other filesystem-based gadget interfaces
● Using USB gadget configfs
● libusbg
● Demo
Linux USB Terminology
● USB host driver - The USB Host Controller
driver
● USB device driver - USB host-resident driver
that supports a USB peripheral
● UDC driver - USB Device Controller driver
● Gadget driver - Driver implementing
peripheral functionality
Linux USB Gadget History
● David Brownell introduces gadget framework
in early 2003
○ the community endlessly debates the term “gadget”
○ supports only monolithic gadget drivers
○ g_zero and g_ether
○ a few usb device controller drivers
Linux USB Gadget History
● gadgetfs introduced in late 2003
○ enables userspace gadget drivers
○ MTP/PTP is a common use case
[Link]
Linux USB Gadget History
● composite framework added in 2008
○ enables multi-function (or USB composite) gadget
drivers
○ existing gadget drivers slowly moved over to
compositable function implementations
[Link]
Linux USB Gadget History
● FunctionFS added in 2010
○ compositable version of gadgetfs
○ now userspace gadget functions can be combined
with kernel gadget functions in a composite gadget
○ e.g. mass storage (kernel) + MTP (via FunctionFS)
But still… something is missing...
Flexibility!
We are still stuck creating custom kernel
modules to glue N instances of M functions
together for our unique use cases
USB Gadget ConfigFS
● Our hero finally arrives in 3.11
● What is it?
● A userspace API for creation of
arbitrary USB composite devices using
reusable kernel gadget function drivers.
● Supports all major existing gadget
functions except FunctionFS and mass
storage in 3.11
● 3.13 added conversion of FunctionFS
and mass storage
Huh? Explain all these filesystems!
● Review
○ GadgetFS - original monolithic kernel driver that
provides an interface to implement userspace
gadget drivers
○ FunctionFS - rewrite of GadgetFS to support
userspace gadget functions that can be combined
into a USB composite gadget.
○ USB Gadget ConfigFS - interface that allows
definition of arbitrary functions and configurations to
define an application specific USB composite device
from userspace.
But why use configfs?
● sysfs versus configfs
○ sysfs exposes kernel created objects to userspace
○ configfs allows userspace instantiation of kernel
objects
● configfs is the appropriate model for creation
of gadget devices
○ create the gadget device and bind to a UDC driver
from userspace
Enabling USB Gadget ConfigFS
Exact steps
Mounting USB Gadget ConfigFS
Exact steps
# mount -t configfs none /sys/kernel/config
# cd /sys/kernel/config/
# ls
usb_gadget
# cd usb_gadget
If USB Gadget configfs support
is enabled we’ll have a
usb_gadget subdirectory present
Create 2xACM + ECM Gadget
Exact steps
# mkdir g1
# cd g1
# ls
UDC bDeviceProtocol bMaxPacketSize0 bcdUSB functions
idVendor
bDeviceClass bDeviceSubClass bcdDevice configs idProduct strings
By creating the g1 directory, we’
ve instantiated a new gadget
device template to fill in.
Create 2xACM + ECM Gadget
Exact steps
# echo "0x1d6b" > idVendor Write in our vendor/product IDs
# echo "0x0104" > idProduct
# mkdir strings/0x409
# ls strings/0x409/ Instantiate English language
manufacturer product serialnumber strings
# echo "0123456789" > strings/0x409/serialnumber
# echo "Foo Inc." > strings/0x409/manufacturer
# echo "Bar Gadget" > strings/0x409/product
Write in our serial number,
manufacturer, and product
descriptor strings
Create 2xACM + ECM Gadget
Exact steps
# mkdir functions/acm.GS0
Create function instances. Note that
# mkdir functions/acm.GS1
multiple function instances of the same
# mkdir functions/ecm.usb0
type must have a unique extension
Create 2xACM + ECM Gadget
Exact steps
# mkdir configs/c.1 Create a configuration instance
# ls configs/c.1
MaxPower bmAttributes strings
Create English language strings and
# mkdir configs/c.1/strings/0x409
write in a description for this device
# ls configs/c.1/strings/0x409/
configuration
configuration
# echo "CDC 2xACM+ECM" > configs/c.1/strings/0x409/configuration
# ln -s functions/acm.GS0 configs/c.1
# ln -s functions/acm.GS1 configs/c.1 Bind each of our function instances to
# ln -s functions/ecm.usb0 configs/c.1 this configuration
Create 2xACM + ECM Gadget
Exact steps
# ls /sys/class/udc/
Verify which UDC drivers are available
[Link]
# echo "[Link]" > UDC
Attach the created gadget device to
our UDC driver.
libusbg
● Library providing C API to USB Gadget
Configfs
○ Supports creation and removal of gadgets
○ Full API docs at [Link]
○ Source at git://[Link]/libusbg/[Link]
● Status
○ Patch review conducted on linux-usb-devel list
○ Starting to gain major contributions in cleanups and
API improvements
■ Major contributions have come from Samsung, in
particular, Krzysztof Opasiak
libusbg-based 2xACM + ECM Gadget
usbg_gadget_strs g_strs = {
"0123456789", /* Serial number */
"Foo Inc.", /* Manufacturer */
"Bar Gadget" /* Product string */
};
usbg_config_strs c_strs = {
"CDC 2xACM+ECM"
};
usbg_init("/sys/kernel/config", &s); Use function
usbg_create_gadget(s, "g1", &g_attrs, &g_strs, &g); enums let the
usbg_create_function(g, F_ACM, "GS0", NULL, &f_acm0);
compiler catch
our typos
usbg_create_function(g, F_ACM, "GS1", NULL, &f_acm1);
usbg_create_function(g, F_ECM, "usb0", NULL, &f_ecm);
usbg_create_config(g, 1, "The only one", NULL, &c_strs, &c);
usbg_add_config_function(c, "acm.GS0", f_acm0);
usbg_add_config_function(c, "acm.GS1", f_acm1);
Default UDC will
usbg_add_config_function(c, "ecm.usb0", f_ecm); just use the first or
usbg_enable_gadget(g, DEFAULT_UDC); only one listed in
usbg_cleanup(s); sysfs
Demo