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