| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106 |
- ====================
- How FunctionFS works
- ====================
- Overview
- ========
- From kernel point of view it is just a composite function with some
- unique behaviour. It may be added to an USB configuration only after
- the user space driver has registered by writing descriptors and
- strings (the user space program has to provide the same information
- that kernel level composite functions provide when they are added to
- the configuration).
- This in particular means that the composite initialisation functions
- may not be in init section (ie. may not use the __init tag).
- From user space point of view it is a file system which when
- mounted provides an "ep0" file. User space driver need to
- write descriptors and strings to that file. It does not need
- to worry about endpoints, interfaces or strings numbers but
- simply provide descriptors such as if the function was the
- only one (endpoints and strings numbers starting from one and
- interface numbers starting from zero). The FunctionFS changes
- them as needed also handling situation when numbers differ in
- different configurations.
- For more information about FunctionFS descriptors see :doc:`functionfs-desc`
- When descriptors and strings are written "ep#" files appear
- (one for each declared endpoint) which handle communication on
- a single endpoint. Again, FunctionFS takes care of the real
- numbers and changing of the configuration (which means that
- "ep1" file may be really mapped to (say) endpoint 3 (and when
- configuration changes to (say) endpoint 2)). "ep0" is used
- for receiving events and handling setup requests.
- When all files are closed the function disables itself.
- What I also want to mention is that the FunctionFS is designed in such
- a way that it is possible to mount it several times so in the end
- a gadget could use several FunctionFS functions. The idea is that
- each FunctionFS instance is identified by the device name used
- when mounting.
- One can imagine a gadget that has an Ethernet, MTP and HID interfaces
- where the last two are implemented via FunctionFS. On user space
- level it would look like this::
- $ insmod g_ffs.ko idVendor=<ID> iSerialNumber=<string> functions=mtp,hid
- $ mkdir /dev/ffs-mtp && mount -t functionfs mtp /dev/ffs-mtp
- $ ( cd /dev/ffs-mtp && mtp-daemon ) &
- $ mkdir /dev/ffs-hid && mount -t functionfs hid /dev/ffs-hid
- $ ( cd /dev/ffs-hid && hid-daemon ) &
- On kernel level the gadget checks ffs_data->dev_name to identify
- whether its FunctionFS is designed for MTP ("mtp") or HID ("hid").
- If no "functions" module parameters is supplied, the driver accepts
- just one function with any name.
- When "functions" module parameter is supplied, only functions
- with listed names are accepted. In particular, if the "functions"
- parameter's value is just a one-element list, then the behaviour
- is similar to when there is no "functions" at all; however,
- only a function with the specified name is accepted.
- The gadget is registered only after all the declared function
- filesystems have been mounted and USB descriptors of all functions
- have been written to their ep0's.
- Conversely, the gadget is unregistered after the first USB function
- closes its endpoints.
- DMABUF interface
- ================
- FunctionFS additionally supports a DMABUF based interface, where the
- userspace can attach DMABUF objects (externally created) to an endpoint,
- and subsequently use them for data transfers.
- A userspace application can then use this interface to share DMABUF
- objects between several interfaces, allowing it to transfer data in a
- zero-copy fashion, for instance between IIO and the USB stack.
- As part of this interface, three new IOCTLs have been added. These three
- IOCTLs have to be performed on a data endpoint (ie. not ep0). They are:
- ``FUNCTIONFS_DMABUF_ATTACH(int)``
- Attach the DMABUF object, identified by its file descriptor, to the
- data endpoint. Returns zero on success, and a negative errno value
- on error.
- ``FUNCTIONFS_DMABUF_DETACH(int)``
- Detach the given DMABUF object, identified by its file descriptor,
- from the data endpoint. Returns zero on success, and a negative
- errno value on error. Note that closing the endpoint's file
- descriptor will automatically detach all attached DMABUFs.
- ``FUNCTIONFS_DMABUF_TRANSFER(struct usb_ffs_dmabuf_transfer_req *)``
- Enqueue the previously attached DMABUF to the transfer queue.
- The argument is a structure that packs the DMABUF's file descriptor,
- the size in bytes to transfer (which should generally correspond to
- the size of the DMABUF), and a 'flags' field which is unused
- for now. Returns zero on success, and a negative errno value on
- error.
|