^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) ====================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) How FunctionFS works
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) ====================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) From kernel point of view it is just a composite function with some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) unique behaviour. It may be added to an USB configuration only after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) the user space driver has registered by writing descriptors and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) strings (the user space program has to provide the same information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) that kernel level composite functions provide when they are added to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) the configuration).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) This in particular means that the composite initialisation functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) may not be in init section (ie. may not use the __init tag).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) From user space point of view it is a file system which when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) mounted provides an "ep0" file. User space driver need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) write descriptors and strings to that file. It does not need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) to worry about endpoints, interfaces or strings numbers but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) simply provide descriptors such as if the function was the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) only one (endpoints and strings numbers starting from one and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) interface numbers starting from zero). The FunctionFS changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) them as needed also handling situation when numbers differ in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) different configurations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) When descriptors and strings are written "ep#" files appear
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) (one for each declared endpoint) which handle communication on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) a single endpoint. Again, FunctionFS takes care of the real
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) numbers and changing of the configuration (which means that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) "ep1" file may be really mapped to (say) endpoint 3 (and when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) configuration changes to (say) endpoint 2)). "ep0" is used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) for receiving events and handling setup requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) When all files are closed the function disables itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) What I also want to mention is that the FunctionFS is designed in such
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) a way that it is possible to mount it several times so in the end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) a gadget could use several FunctionFS functions. The idea is that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) each FunctionFS instance is identified by the device name used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) when mounting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) One can imagine a gadget that has an Ethernet, MTP and HID interfaces
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) where the last two are implemented via FunctionFS. On user space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) level it would look like this::
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) $ insmod g_ffs.ko idVendor=<ID> iSerialNumber=<string> functions=mtp,hid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) $ mkdir /dev/ffs-mtp && mount -t functionfs mtp /dev/ffs-mtp
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) $ ( cd /dev/ffs-mtp && mtp-daemon ) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) $ mkdir /dev/ffs-hid && mount -t functionfs hid /dev/ffs-hid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) $ ( cd /dev/ffs-hid && hid-daemon ) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) On kernel level the gadget checks ffs_data->dev_name to identify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) whether it's FunctionFS designed for MTP ("mtp") or HID ("hid").
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) If no "functions" module parameters is supplied, the driver accepts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) just one function with any name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) When "functions" module parameter is supplied, only functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) with listed names are accepted. In particular, if the "functions"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) parameter's value is just a one-element list, then the behaviour
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) is similar to when there is no "functions" at all; however,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) only a function with the specified name is accepted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) The gadget is registered only after all the declared function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) filesystems have been mounted and USB descriptors of all functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) have been written to their ep0's.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) Conversely, the gadget is unregistered after the first USB function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) closes its endpoints.