162306a36Sopenharmony_ci====================
262306a36Sopenharmony_ciHow FunctionFS works
362306a36Sopenharmony_ci====================
462306a36Sopenharmony_ci
562306a36Sopenharmony_ciFrom kernel point of view it is just a composite function with some
662306a36Sopenharmony_ciunique behaviour.  It may be added to an USB configuration only after
762306a36Sopenharmony_cithe user space driver has registered by writing descriptors and
862306a36Sopenharmony_cistrings (the user space program has to provide the same information
962306a36Sopenharmony_cithat kernel level composite functions provide when they are added to
1062306a36Sopenharmony_cithe configuration).
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ciThis in particular means that the composite initialisation functions
1362306a36Sopenharmony_cimay not be in init section (ie. may not use the __init tag).
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ciFrom user space point of view it is a file system which when
1662306a36Sopenharmony_cimounted provides an "ep0" file.  User space driver need to
1762306a36Sopenharmony_ciwrite descriptors and strings to that file.  It does not need
1862306a36Sopenharmony_cito worry about endpoints, interfaces or strings numbers but
1962306a36Sopenharmony_cisimply provide descriptors such as if the function was the
2062306a36Sopenharmony_cionly one (endpoints and strings numbers starting from one and
2162306a36Sopenharmony_ciinterface numbers starting from zero).  The FunctionFS changes
2262306a36Sopenharmony_cithem as needed also handling situation when numbers differ in
2362306a36Sopenharmony_cidifferent configurations.
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ciWhen descriptors and strings are written "ep#" files appear
2662306a36Sopenharmony_ci(one for each declared endpoint) which handle communication on
2762306a36Sopenharmony_cia single endpoint.  Again, FunctionFS takes care of the real
2862306a36Sopenharmony_cinumbers and changing of the configuration (which means that
2962306a36Sopenharmony_ci"ep1" file may be really mapped to (say) endpoint 3 (and when
3062306a36Sopenharmony_ciconfiguration changes to (say) endpoint 2)).  "ep0" is used
3162306a36Sopenharmony_cifor receiving events and handling setup requests.
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ciWhen all files are closed the function disables itself.
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ciWhat I also want to mention is that the FunctionFS is designed in such
3662306a36Sopenharmony_cia way that it is possible to mount it several times so in the end
3762306a36Sopenharmony_cia gadget could use several FunctionFS functions. The idea is that
3862306a36Sopenharmony_cieach FunctionFS instance is identified by the device name used
3962306a36Sopenharmony_ciwhen mounting.
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ciOne can imagine a gadget that has an Ethernet, MTP and HID interfaces
4262306a36Sopenharmony_ciwhere the last two are implemented via FunctionFS.  On user space
4362306a36Sopenharmony_cilevel it would look like this::
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci  $ insmod g_ffs.ko idVendor=<ID> iSerialNumber=<string> functions=mtp,hid
4662306a36Sopenharmony_ci  $ mkdir /dev/ffs-mtp && mount -t functionfs mtp /dev/ffs-mtp
4762306a36Sopenharmony_ci  $ ( cd /dev/ffs-mtp && mtp-daemon ) &
4862306a36Sopenharmony_ci  $ mkdir /dev/ffs-hid && mount -t functionfs hid /dev/ffs-hid
4962306a36Sopenharmony_ci  $ ( cd /dev/ffs-hid && hid-daemon ) &
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ciOn kernel level the gadget checks ffs_data->dev_name to identify
5262306a36Sopenharmony_ciwhether its FunctionFS is designed for MTP ("mtp") or HID ("hid").
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ciIf no "functions" module parameters is supplied, the driver accepts
5562306a36Sopenharmony_cijust one function with any name.
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ciWhen "functions" module parameter is supplied, only functions
5862306a36Sopenharmony_ciwith listed names are accepted. In particular, if the "functions"
5962306a36Sopenharmony_ciparameter's value is just a one-element list, then the behaviour
6062306a36Sopenharmony_ciis similar to when there is no "functions" at all; however,
6162306a36Sopenharmony_cionly a function with the specified name is accepted.
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ciThe gadget is registered only after all the declared function
6462306a36Sopenharmony_cifilesystems have been mounted and USB descriptors of all functions
6562306a36Sopenharmony_cihave been written to their ep0's.
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ciConversely, the gadget is unregistered after the first USB function
6862306a36Sopenharmony_cicloses its endpoints.
69