Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 1 | ============================================ |
| 2 | Linux USB gadget configured through configfs |
| 3 | ============================================ |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 4 | |
| 5 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 6 | 25th April 2013 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | Overview |
| 12 | ======== |
| 13 | |
| 14 | A USB Linux Gadget is a device which has a UDC (USB Device Controller) and can |
| 15 | be connected to a USB Host to extend it with additional functions like a serial |
| 16 | port or a mass storage capability. |
| 17 | |
| 18 | A gadget is seen by its host as a set of configurations, each of which contains |
| 19 | a number of interfaces which, from the gadget's perspective, are known as |
| 20 | functions, each function representing e.g. a serial connection or a SCSI disk. |
| 21 | |
| 22 | Linux provides a number of functions for gadgets to use. |
| 23 | |
| 24 | Creating a gadget means deciding what configurations there will be |
| 25 | and which functions each configuration will provide. |
| 26 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 27 | Configfs (please see `Documentation/filesystems/configfs/*`) lends itself nicely |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 28 | for the purpose of telling the kernel about the above mentioned decision. |
| 29 | This document is about how to do it. |
| 30 | |
| 31 | It also describes how configfs integration into gadget is designed. |
| 32 | |
| 33 | |
| 34 | |
| 35 | |
| 36 | Requirements |
| 37 | ============ |
| 38 | |
| 39 | In order for this to work configfs must be available, so CONFIGFS_FS must be |
| 40 | 'y' or 'm' in .config. As of this writing USB_LIBCOMPOSITE selects CONFIGFS_FS. |
| 41 | |
| 42 | |
| 43 | |
| 44 | |
| 45 | Usage |
| 46 | ===== |
| 47 | |
| 48 | (The original post describing the first function |
| 49 | made available through configfs can be seen here: |
| 50 | http://www.spinics.net/lists/linux-usb/msg76388.html) |
| 51 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 52 | :: |
| 53 | |
| 54 | $ modprobe libcomposite |
| 55 | $ mount none $CONFIGFS_HOME -t configfs |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 56 | |
| 57 | where CONFIGFS_HOME is the mount point for configfs |
| 58 | |
| 59 | 1. Creating the gadgets |
| 60 | ----------------------- |
| 61 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 62 | For each gadget to be created its corresponding directory must be created:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 63 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 64 | $ mkdir $CONFIGFS_HOME/usb_gadget/<gadget name> |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 65 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 66 | e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 67 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 68 | $ mkdir $CONFIGFS_HOME/usb_gadget/g1 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 69 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 70 | ... |
| 71 | ... |
| 72 | ... |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 73 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 74 | $ cd $CONFIGFS_HOME/usb_gadget/g1 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 75 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 76 | Each gadget needs to have its vendor id <VID> and product id <PID> specified:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 77 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 78 | $ echo <VID> > idVendor |
| 79 | $ echo <PID> > idProduct |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 80 | |
| 81 | A gadget also needs its serial number, manufacturer and product strings. |
| 82 | In order to have a place to store them, a strings subdirectory must be created |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 83 | for each language, e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 84 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 85 | $ mkdir strings/0x409 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 86 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 87 | Then the strings can be specified:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 88 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 89 | $ echo <serial number> > strings/0x409/serialnumber |
| 90 | $ echo <manufacturer> > strings/0x409/manufacturer |
| 91 | $ echo <product> > strings/0x409/product |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 92 | |
| 93 | 2. Creating the configurations |
| 94 | ------------------------------ |
| 95 | |
| 96 | Each gadget will consist of a number of configurations, their corresponding |
| 97 | directories must be created: |
| 98 | |
| 99 | $ mkdir configs/<name>.<number> |
| 100 | |
| 101 | where <name> can be any string which is legal in a filesystem and the |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 102 | <number> is the configuration's number, e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 103 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 104 | $ mkdir configs/c.1 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 105 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 106 | ... |
| 107 | ... |
| 108 | ... |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 109 | |
| 110 | Each configuration also needs its strings, so a subdirectory must be created |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 111 | for each language, e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 112 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 113 | $ mkdir configs/c.1/strings/0x409 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 114 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 115 | Then the configuration string can be specified:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 116 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 117 | $ echo <configuration> > configs/c.1/strings/0x409/configuration |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 118 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 119 | Some attributes can also be set for a configuration, e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 120 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 121 | $ echo 120 > configs/c.1/MaxPower |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 122 | |
| 123 | 3. Creating the functions |
| 124 | ------------------------- |
| 125 | |
| 126 | The gadget will provide some functions, for each function its corresponding |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 127 | directory must be created:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 128 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 129 | $ mkdir functions/<name>.<instance name> |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 130 | |
| 131 | where <name> corresponds to one of allowed function names and instance name |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 132 | is an arbitrary string allowed in a filesystem, e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 133 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 134 | $ mkdir functions/ncm.usb0 # usb_f_ncm.ko gets loaded with request_module() |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 135 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 136 | ... |
| 137 | ... |
| 138 | ... |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 139 | |
| 140 | Each function provides its specific set of attributes, with either read-only |
| 141 | or read-write access. Where applicable they need to be written to as |
| 142 | appropriate. |
| 143 | Please refer to Documentation/ABI/*/configfs-usb-gadget* for more information. |
| 144 | |
| 145 | 4. Associating the functions with their configurations |
| 146 | ------------------------------------------------------ |
| 147 | |
| 148 | At this moment a number of gadgets is created, each of which has a number of |
| 149 | configurations specified and a number of functions available. What remains |
| 150 | is specifying which function is available in which configuration (the same |
| 151 | function can be used in multiple configurations). This is achieved with |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 152 | creating symbolic links:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 153 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 154 | $ ln -s functions/<name>.<instance name> configs/<name>.<number> |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 155 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 156 | e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 157 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 158 | $ ln -s functions/ncm.usb0 configs/c.1 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 159 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 160 | ... |
| 161 | ... |
| 162 | ... |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 163 | |
| 164 | 5. Enabling the gadget |
| 165 | ---------------------- |
| 166 | |
| 167 | All the above steps serve the purpose of composing the gadget of |
| 168 | configurations and functions. |
| 169 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 170 | An example directory structure might look like this:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 171 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 172 | . |
| 173 | ./strings |
| 174 | ./strings/0x409 |
| 175 | ./strings/0x409/serialnumber |
| 176 | ./strings/0x409/product |
| 177 | ./strings/0x409/manufacturer |
| 178 | ./configs |
| 179 | ./configs/c.1 |
| 180 | ./configs/c.1/ncm.usb0 -> ../../../../usb_gadget/g1/functions/ncm.usb0 |
| 181 | ./configs/c.1/strings |
| 182 | ./configs/c.1/strings/0x409 |
| 183 | ./configs/c.1/strings/0x409/configuration |
| 184 | ./configs/c.1/bmAttributes |
| 185 | ./configs/c.1/MaxPower |
| 186 | ./functions |
| 187 | ./functions/ncm.usb0 |
| 188 | ./functions/ncm.usb0/ifname |
| 189 | ./functions/ncm.usb0/qmult |
| 190 | ./functions/ncm.usb0/host_addr |
| 191 | ./functions/ncm.usb0/dev_addr |
| 192 | ./UDC |
| 193 | ./bcdUSB |
| 194 | ./bcdDevice |
| 195 | ./idProduct |
| 196 | ./idVendor |
| 197 | ./bMaxPacketSize0 |
| 198 | ./bDeviceProtocol |
| 199 | ./bDeviceSubClass |
| 200 | ./bDeviceClass |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 201 | |
| 202 | |
| 203 | Such a gadget must be finally enabled so that the USB host can enumerate it. |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 204 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 205 | In order to enable the gadget it must be bound to a UDC (USB Device |
| 206 | Controller):: |
| 207 | |
| 208 | $ echo <udc name> > UDC |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 209 | |
| 210 | where <udc name> is one of those found in /sys/class/udc/* |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 211 | e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 212 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 213 | $ echo s3c-hsotg > UDC |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 214 | |
| 215 | |
| 216 | 6. Disabling the gadget |
| 217 | ----------------------- |
| 218 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 219 | :: |
| 220 | |
| 221 | $ echo "" > UDC |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 222 | |
| 223 | 7. Cleaning up |
| 224 | -------------- |
| 225 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 226 | Remove functions from configurations:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 227 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 228 | $ rm configs/<config name>.<number>/<function> |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 229 | |
| 230 | where <config name>.<number> specify the configuration and <function> is |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 231 | a symlink to a function being removed from the configuration, e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 232 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 233 | $ rm configs/c.1/ncm.usb0 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 234 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 235 | ... |
| 236 | ... |
| 237 | ... |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 238 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 239 | Remove strings directories in configurations: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 240 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 241 | $ rmdir configs/<config name>.<number>/strings/<lang> |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 242 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 243 | e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 244 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 245 | $ rmdir configs/c.1/strings/0x409 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 246 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 247 | ... |
| 248 | ... |
| 249 | ... |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 250 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 251 | and remove the configurations:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 252 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 253 | $ rmdir configs/<config name>.<number> |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 254 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 255 | e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 256 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 257 | rmdir configs/c.1 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 258 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 259 | ... |
| 260 | ... |
| 261 | ... |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 262 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 263 | Remove functions (function modules are not unloaded, though): |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 264 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 265 | $ rmdir functions/<name>.<instance name> |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 266 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 267 | e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 268 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 269 | $ rmdir functions/ncm.usb0 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 270 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 271 | ... |
| 272 | ... |
| 273 | ... |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 274 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 275 | Remove strings directories in the gadget:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 276 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 277 | $ rmdir strings/<lang> |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 278 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 279 | e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 280 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 281 | $ rmdir strings/0x409 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 282 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 283 | and finally remove the gadget:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 284 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 285 | $ cd .. |
| 286 | $ rmdir <gadget name> |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 287 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 288 | e.g.:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 289 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 290 | $ rmdir g1 |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 291 | |
| 292 | |
| 293 | |
| 294 | |
| 295 | Implementation design |
| 296 | ===================== |
| 297 | |
| 298 | Below the idea of how configfs works is presented. |
| 299 | In configfs there are items and groups, both represented as directories. |
| 300 | The difference between an item and a group is that a group can contain |
| 301 | other groups. In the picture below only an item is shown. |
| 302 | Both items and groups can have attributes, which are represented as files. |
| 303 | The user can create and remove directories, but cannot remove files, |
| 304 | which can be read-only or read-write, depending on what they represent. |
| 305 | |
| 306 | The filesystem part of configfs operates on config_items/groups and |
| 307 | configfs_attributes which are generic and of the same type for all |
| 308 | configured elements. However, they are embedded in usage-specific |
| 309 | larger structures. In the picture below there is a "cs" which contains |
| 310 | a config_item and an "sa" which contains a configfs_attribute. |
| 311 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 312 | The filesystem view would be like this:: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 313 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 314 | ./ |
| 315 | ./cs (directory) |
| 316 | | |
| 317 | +--sa (file) |
| 318 | | |
| 319 | . |
| 320 | . |
| 321 | . |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 322 | |
| 323 | Whenever a user reads/writes the "sa" file, a function is called |
| 324 | which accepts a struct config_item and a struct configfs_attribute. |
| 325 | In the said function the "cs" and "sa" are retrieved using the well |
| 326 | known container_of technique and an appropriate sa's function (show or |
| 327 | store) is called and passed the "cs" and a character buffer. The "show" |
| 328 | is for displaying the file's contents (copy data from the cs to the |
| 329 | buffer), while the "store" is for modifying the file's contents (copy data |
| 330 | from the buffer to the cs), but it is up to the implementer of the |
| 331 | two functions to decide what they actually do. |
| 332 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 333 | :: |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 334 | |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 335 | typedef struct configured_structure cs; |
| 336 | typedef struct specific_attribute sa; |
| 337 | |
| 338 | sa |
| 339 | +----------------------------------+ |
| 340 | cs | (*show)(cs *, buffer); | |
| 341 | +-----------------+ | (*store)(cs *, buffer, length); | |
| 342 | | | | | |
| 343 | | +-------------+ | | +------------------+ | |
| 344 | | | struct |-|----|------>|struct | | |
| 345 | | | config_item | | | |configfs_attribute| | |
| 346 | | +-------------+ | | +------------------+ | |
| 347 | | | +----------------------------------+ |
| 348 | | data to be set | . |
| 349 | | | . |
| 350 | +-----------------+ . |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 351 | |
| 352 | The file names are decided by the config item/group designer, while |
| 353 | the directories in general can be named at will. A group can have |
| 354 | a number of its default sub-groups created automatically. |
| 355 | |
| 356 | For more information on configfs please see |
Mauro Carvalho Chehab | d80b500 | 2019-04-15 23:56:01 -0300 | [diff] [blame] | 357 | `Documentation/filesystems/configfs/*`. |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 358 | |
| 359 | The concepts described above translate to USB gadgets like this: |
| 360 | |
| 361 | 1. A gadget has its config group, which has some attributes (idVendor, |
| 362 | idProduct etc) and default sub-groups (configs, functions, strings). |
| 363 | Writing to the attributes causes the information to be stored in |
| 364 | appropriate locations. In the configs, functions and strings sub-groups |
| 365 | a user can create their sub-groups to represent configurations, functions, |
| 366 | and groups of strings in a given language. |
| 367 | |
| 368 | 2. The user creates configurations and functions, in the configurations |
| 369 | creates symbolic links to functions. This information is used when the |
| 370 | gadget's UDC attribute is written to, which means binding the gadget |
| 371 | to the UDC. The code in drivers/usb/gadget/configfs.c iterates over |
| 372 | all configurations, and in each configuration it iterates over all |
| 373 | functions and binds them. This way the whole gadget is bound. |
| 374 | |
| 375 | 3. The file drivers/usb/gadget/configfs.c contains code for |
| 376 | |
| 377 | - gadget's config_group |
| 378 | - gadget's default groups (configs, functions, strings) |
| 379 | - associating functions with configurations (symlinks) |
| 380 | |
| 381 | 4. Each USB function naturally has its own view of what it wants |
| 382 | configured, so config_groups for particular functions are defined |
| 383 | in the functions implementation files drivers/usb/gadget/f_*.c. |
| 384 | |
Frans Klaver | 720a8d3 | 2014-10-01 15:30:31 +0200 | [diff] [blame] | 385 | 5. Function's code is written in such a way that it uses |
Andrzej Pietrasiewicz | 5e654a4 | 2013-06-13 10:37:25 +0200 | [diff] [blame] | 386 | |
| 387 | usb_get_function_instance(), which, in turn, calls request_module. |
| 388 | So, provided that modprobe works, modules for particular functions |
| 389 | are loaded automatically. Please note that the converse is not true: |
| 390 | after a gadget is disabled and torn down, the modules remain loaded. |