aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrzej Pietrasiewicz <andrzej.p@samsung.com>2012-05-14 09:51:52 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-14 12:25:44 -0400
commit581791f5c7a480b2cc3431af9a6e799ffd51eb5e (patch)
tree3284544e5a67e91ec612fc0a715cff66b250a283
parent304f0b2453ea377b8f987aa5f9e1ccda0e3adfa7 (diff)
FunctionFS: enable multiple functions
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Acked-by: Michal Nazarewicz <mina86@mina86.com> Cc: Felipe Balbi <balbi@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--Documentation/usb/functionfs.txt67
-rw-r--r--drivers/usb/gadget/f_fs.c38
-rw-r--r--drivers/usb/gadget/g_ffs.c200
-rw-r--r--include/linux/usb/functionfs.h4
4 files changed, 277 insertions, 32 deletions
diff --git a/Documentation/usb/functionfs.txt b/Documentation/usb/functionfs.txt
new file mode 100644
index 000000000000..eaaaea019fc7
--- /dev/null
+++ b/Documentation/usb/functionfs.txt
@@ -0,0 +1,67 @@
1*How FunctionFS works*
2
3From kernel point of view it is just a composite function with some
4unique behaviour. It may be added to an USB configuration only after
5the user space driver has registered by writing descriptors and
6strings (the user space program has to provide the same information
7that kernel level composite functions provide when they are added to
8the configuration).
9
10This in particular means that the composite initialisation functions
11may not be in init section (ie. may not use the __init tag).
12
13From user space point of view it is a file system which when
14mounted provides an "ep0" file. User space driver need to
15write descriptors and strings to that file. It does not need
16to worry about endpoints, interfaces or strings numbers but
17simply provide descriptors such as if the function was the
18only one (endpoints and strings numbers starting from one and
19interface numbers starting from zero). The FunctionFS changes
20them as needed also handling situation when numbers differ in
21different configurations.
22
23When descriptors and strings are written "ep#" files appear
24(one for each declared endpoint) which handle communication on
25a single endpoint. Again, FunctionFS takes care of the real
26numbers and changing of the configuration (which means that
27"ep1" file may be really mapped to (say) endpoint 3 (and when
28configuration changes to (say) endpoint 2)). "ep0" is used
29for receiving events and handling setup requests.
30
31When all files are closed the function disables itself.
32
33What I also want to mention is that the FunctionFS is designed in such
34a way that it is possible to mount it several times so in the end
35a gadget could use several FunctionFS functions. The idea is that
36each FunctionFS instance is identified by the device name used
37when mounting.
38
39One can imagine a gadget that has an Ethernet, MTP and HID interfaces
40where the last two are implemented via FunctionFS. On user space
41level it would look like this:
42
43$ insmod g_ffs.ko idVendor=<ID> iSerialNumber=<string> functions=mtp,hid
44$ mkdir /dev/ffs-mtp && mount -t functionfs mtp /dev/ffs-mtp
45$ ( cd /dev/ffs-mtp && mtp-daemon ) &
46$ mkdir /dev/ffs-hid && mount -t functionfs hid /dev/ffs-hid
47$ ( cd /dev/ffs-hid && hid-daemon ) &
48
49On kernel level the gadget checks ffs_data->dev_name to identify
50whether it's FunctionFS designed for MTP ("mtp") or HID ("hid").
51
52If no "functions" module parameters is supplied, the driver accepts
53just one function with any name.
54
55When "functions" module parameter is supplied, only functions
56with listed names are accepted. In particular, if the "functions"
57parameter's value is just a one-element list, then the behaviour
58is similar to when there is no "functions" at all; however,
59only a function with the specified name is accepted.
60
61The gadget is registered only after all the declared function
62filesystems have been mounted and USB descriptors of all functions
63have been written to their ep0's.
64
65Conversely, the gadget is unregistered after the first USB function
66closes its endpoints.
67
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 1d4c535671a7..dcd1c7fbb016 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -1031,6 +1031,12 @@ struct ffs_sb_fill_data {
1031 struct ffs_file_perms perms; 1031 struct ffs_file_perms perms;
1032 umode_t root_mode; 1032 umode_t root_mode;
1033 const char *dev_name; 1033 const char *dev_name;
1034 union {
1035 /* set by ffs_fs_mount(), read by ffs_sb_fill() */
1036 void *private_data;
1037 /* set by ffs_sb_fill(), read by ffs_fs_mount */
1038 struct ffs_data *ffs_data;
1039 };
1034}; 1040};
1035 1041
1036static int ffs_sb_fill(struct super_block *sb, void *_data, int silent) 1042static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
@@ -1047,8 +1053,14 @@ static int ffs_sb_fill(struct super_block *sb, void *_data, int silent)
1047 goto Enomem; 1053 goto Enomem;
1048 1054
1049 ffs->sb = sb; 1055 ffs->sb = sb;
1050 ffs->dev_name = data->dev_name; 1056 ffs->dev_name = kstrdup(data->dev_name, GFP_KERNEL);
1057 if (unlikely(!ffs->dev_name))
1058 goto Enomem;
1051 ffs->file_perms = data->perms; 1059 ffs->file_perms = data->perms;
1060 ffs->private_data = data->private_data;
1061
1062 /* used by the caller of this function */
1063 data->ffs_data = ffs;
1052 1064
1053 sb->s_fs_info = ffs; 1065 sb->s_fs_info = ffs;
1054 sb->s_blocksize = PAGE_CACHE_SIZE; 1066 sb->s_blocksize = PAGE_CACHE_SIZE;
@@ -1167,20 +1179,29 @@ ffs_fs_mount(struct file_system_type *t, int flags,
1167 }, 1179 },
1168 .root_mode = S_IFDIR | 0500, 1180 .root_mode = S_IFDIR | 0500,
1169 }; 1181 };
1182 struct dentry *rv;
1170 int ret; 1183 int ret;
1184 void *ffs_dev;
1171 1185
1172 ENTER(); 1186 ENTER();
1173 1187
1174 ret = functionfs_check_dev_callback(dev_name);
1175 if (unlikely(ret < 0))
1176 return ERR_PTR(ret);
1177
1178 ret = ffs_fs_parse_opts(&data, opts); 1188 ret = ffs_fs_parse_opts(&data, opts);
1179 if (unlikely(ret < 0)) 1189 if (unlikely(ret < 0))
1180 return ERR_PTR(ret); 1190 return ERR_PTR(ret);
1181 1191
1192 ffs_dev = functionfs_acquire_dev_callback(dev_name);
1193 if (IS_ERR(ffs_dev))
1194 return ffs_dev;
1195
1182 data.dev_name = dev_name; 1196 data.dev_name = dev_name;
1183 return mount_single(t, flags, &data, ffs_sb_fill); 1197 data.private_data = ffs_dev;
1198 rv = mount_nodev(t, flags, &data, ffs_sb_fill);
1199
1200 /* data.ffs_data is set by ffs_sb_fill */
1201 if (IS_ERR(rv))
1202 functionfs_release_dev_callback(data.ffs_data);
1203
1204 return rv;
1184} 1205}
1185 1206
1186static void 1207static void
@@ -1189,8 +1210,10 @@ ffs_fs_kill_sb(struct super_block *sb)
1189 ENTER(); 1210 ENTER();
1190 1211
1191 kill_litter_super(sb); 1212 kill_litter_super(sb);
1192 if (sb->s_fs_info) 1213 if (sb->s_fs_info) {
1214 functionfs_release_dev_callback(sb->s_fs_info);
1193 ffs_data_put(sb->s_fs_info); 1215 ffs_data_put(sb->s_fs_info);
1216 }
1194} 1217}
1195 1218
1196static struct file_system_type ffs_fs_type = { 1219static struct file_system_type ffs_fs_type = {
@@ -1256,6 +1279,7 @@ static void ffs_data_put(struct ffs_data *ffs)
1256 ffs_data_clear(ffs); 1279 ffs_data_clear(ffs);
1257 BUG_ON(waitqueue_active(&ffs->ev.waitq) || 1280 BUG_ON(waitqueue_active(&ffs->ev.waitq) ||
1258 waitqueue_active(&ffs->ep0req_completion.wait)); 1281 waitqueue_active(&ffs->ep0req_completion.wait));
1282 kfree(ffs->dev_name);
1259 kfree(ffs); 1283 kfree(ffs);
1260 } 1284 }
1261} 1285}
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c
index a85eaf40b948..d3ace9002a6a 100644
--- a/drivers/usb/gadget/g_ffs.c
+++ b/drivers/usb/gadget/g_ffs.c
@@ -67,6 +67,15 @@ MODULE_LICENSE("GPL");
67#define GFS_VENDOR_ID 0x1d6b /* Linux Foundation */ 67#define GFS_VENDOR_ID 0x1d6b /* Linux Foundation */
68#define GFS_PRODUCT_ID 0x0105 /* FunctionFS Gadget */ 68#define GFS_PRODUCT_ID 0x0105 /* FunctionFS Gadget */
69 69
70#define GFS_MAX_DEVS 10
71
72struct gfs_ffs_obj {
73 const char *name;
74 bool mounted;
75 bool desc_ready;
76 struct ffs_data *ffs_data;
77};
78
70static struct usb_device_descriptor gfs_dev_desc = { 79static struct usb_device_descriptor gfs_dev_desc = {
71 .bLength = sizeof gfs_dev_desc, 80 .bLength = sizeof gfs_dev_desc,
72 .bDescriptorType = USB_DT_DEVICE, 81 .bDescriptorType = USB_DT_DEVICE,
@@ -78,12 +87,17 @@ static struct usb_device_descriptor gfs_dev_desc = {
78 .idProduct = cpu_to_le16(GFS_PRODUCT_ID), 87 .idProduct = cpu_to_le16(GFS_PRODUCT_ID),
79}; 88};
80 89
90static char *func_names[GFS_MAX_DEVS];
91static unsigned int func_num;
92
81module_param_named(bDeviceClass, gfs_dev_desc.bDeviceClass, byte, 0644); 93module_param_named(bDeviceClass, gfs_dev_desc.bDeviceClass, byte, 0644);
82MODULE_PARM_DESC(bDeviceClass, "USB Device class"); 94MODULE_PARM_DESC(bDeviceClass, "USB Device class");
83module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte, 0644); 95module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte, 0644);
84MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass"); 96MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass");
85module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte, 0644); 97module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte, 0644);
86MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol"); 98MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
99module_param_array_named(functions, func_names, charp, &func_num, 0);
100MODULE_PARM_DESC(functions, "USB Functions list");
87 101
88static const struct usb_descriptor_header *gfs_otg_desc[] = { 102static const struct usb_descriptor_header *gfs_otg_desc[] = {
89 (const struct usb_descriptor_header *) 103 (const struct usb_descriptor_header *)
@@ -158,13 +172,34 @@ static struct usb_composite_driver gfs_driver = {
158 .iProduct = DRIVER_DESC, 172 .iProduct = DRIVER_DESC,
159}; 173};
160 174
161static struct ffs_data *gfs_ffs_data; 175static DEFINE_MUTEX(gfs_lock);
162static unsigned long gfs_registered; 176static unsigned int missing_funcs;
177static bool gfs_ether_setup;
178static bool gfs_registered;
179static bool gfs_single_func;
180static struct gfs_ffs_obj *ffs_tab;
163 181
164static int __init gfs_init(void) 182static int __init gfs_init(void)
165{ 183{
184 int i;
185
166 ENTER(); 186 ENTER();
167 187
188 if (!func_num) {
189 gfs_single_func = true;
190 func_num = 1;
191 }
192
193 ffs_tab = kcalloc(func_num, sizeof *ffs_tab, GFP_KERNEL);
194 if (!ffs_tab)
195 return -ENOMEM;
196
197 if (!gfs_single_func)
198 for (i = 0; i < func_num; i++)
199 ffs_tab[i].name = func_names[i];
200
201 missing_funcs = func_num;
202
168 return functionfs_init(); 203 return functionfs_init();
169} 204}
170module_init(gfs_init); 205module_init(gfs_init);
@@ -172,63 +207,165 @@ module_init(gfs_init);
172static void __exit gfs_exit(void) 207static void __exit gfs_exit(void)
173{ 208{
174 ENTER(); 209 ENTER();
210 mutex_lock(&gfs_lock);
175 211
176 if (test_and_clear_bit(0, &gfs_registered)) 212 if (gfs_registered)
177 usb_composite_unregister(&gfs_driver); 213 usb_composite_unregister(&gfs_driver);
214 gfs_registered = false;
178 215
179 functionfs_cleanup(); 216 functionfs_cleanup();
217
218 mutex_unlock(&gfs_lock);
219 kfree(ffs_tab);
180} 220}
181module_exit(gfs_exit); 221module_exit(gfs_exit);
182 222
223static struct gfs_ffs_obj *gfs_find_dev(const char *dev_name)
224{
225 int i;
226
227 ENTER();
228
229 if (gfs_single_func)
230 return &ffs_tab[0];
231
232 for (i = 0; i < func_num; i++)
233 if (strcmp(ffs_tab[i].name, dev_name) == 0)
234 return &ffs_tab[i];
235
236 return NULL;
237}
238
183static int functionfs_ready_callback(struct ffs_data *ffs) 239static int functionfs_ready_callback(struct ffs_data *ffs)
184{ 240{
241 struct gfs_ffs_obj *ffs_obj;
185 int ret; 242 int ret;
186 243
187 ENTER(); 244 ENTER();
245 mutex_lock(&gfs_lock);
246
247 ffs_obj = ffs->private_data;
248 if (!ffs_obj) {
249 ret = -EINVAL;
250 goto done;
251 }
252
253 if (WARN_ON(ffs_obj->desc_ready)) {
254 ret = -EBUSY;
255 goto done;
256 }
257 ffs_obj->desc_ready = true;
258 ffs_obj->ffs_data = ffs;
188 259
189 if (WARN_ON(test_and_set_bit(0, &gfs_registered))) 260 if (--missing_funcs) {
190 return -EBUSY; 261 ret = 0;
262 goto done;
263 }
264
265 if (gfs_registered) {
266 ret = -EBUSY;
267 goto done;
268 }
269 gfs_registered = true;
191 270
192 gfs_ffs_data = ffs;
193 ret = usb_composite_probe(&gfs_driver, gfs_bind); 271 ret = usb_composite_probe(&gfs_driver, gfs_bind);
194 if (unlikely(ret < 0)) 272 if (unlikely(ret < 0))
195 clear_bit(0, &gfs_registered); 273 gfs_registered = false;
274
275done:
276 mutex_unlock(&gfs_lock);
196 return ret; 277 return ret;
197} 278}
198 279
199static void functionfs_closed_callback(struct ffs_data *ffs) 280static void functionfs_closed_callback(struct ffs_data *ffs)
200{ 281{
282 struct gfs_ffs_obj *ffs_obj;
283
201 ENTER(); 284 ENTER();
285 mutex_lock(&gfs_lock);
202 286
203 if (test_and_clear_bit(0, &gfs_registered)) 287 ffs_obj = ffs->private_data;
288 if (!ffs_obj)
289 goto done;
290
291 ffs_obj->desc_ready = false;
292 missing_funcs++;
293
294 if (gfs_registered)
204 usb_composite_unregister(&gfs_driver); 295 usb_composite_unregister(&gfs_driver);
296 gfs_registered = false;
297
298done:
299 mutex_unlock(&gfs_lock);
205} 300}
206 301
207static int functionfs_check_dev_callback(const char *dev_name) 302static void *functionfs_acquire_dev_callback(const char *dev_name)
208{ 303{
209 return 0; 304 struct gfs_ffs_obj *ffs_dev;
305
306 ENTER();
307 mutex_lock(&gfs_lock);
308
309 ffs_dev = gfs_find_dev(dev_name);
310 if (!ffs_dev) {
311 ffs_dev = ERR_PTR(-ENODEV);
312 goto done;
313 }
314
315 if (ffs_dev->mounted) {
316 ffs_dev = ERR_PTR(-EBUSY);
317 goto done;
318 }
319 ffs_dev->mounted = true;
320
321done:
322 mutex_unlock(&gfs_lock);
323 return ffs_dev;
210} 324}
211 325
326static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
327{
328 struct gfs_ffs_obj *ffs_dev;
329
330 ENTER();
331 mutex_lock(&gfs_lock);
332
333 ffs_dev = ffs_data->private_data;
334 if (ffs_dev)
335 ffs_dev->mounted = false;
336
337 mutex_unlock(&gfs_lock);
338}
339
340/*
341 * It is assumed that gfs_bind is called from a context where gfs_lock is held
342 */
212static int gfs_bind(struct usb_composite_dev *cdev) 343static int gfs_bind(struct usb_composite_dev *cdev)
213{ 344{
214 int ret, i; 345 int ret, i;
215 346
216 ENTER(); 347 ENTER();
217 348
218 if (WARN_ON(!gfs_ffs_data)) 349 if (missing_funcs)
219 return -ENODEV; 350 return -ENODEV;
220 351
221 ret = gether_setup(cdev->gadget, gfs_hostaddr); 352 ret = gether_setup(cdev->gadget, gfs_hostaddr);
222 if (unlikely(ret < 0)) 353 if (unlikely(ret < 0))
223 goto error_quick; 354 goto error_quick;
355 gfs_ether_setup = true;
224 356
225 ret = usb_string_ids_tab(cdev, gfs_strings); 357 ret = usb_string_ids_tab(cdev, gfs_strings);
226 if (unlikely(ret < 0)) 358 if (unlikely(ret < 0))
227 goto error; 359 goto error;
228 360
229 ret = functionfs_bind(gfs_ffs_data, cdev); 361 for (i = func_num; --i; ) {
230 if (unlikely(ret < 0)) 362 ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);
231 goto error; 363 if (unlikely(ret < 0)) {
364 while (++i < func_num)
365 functionfs_unbind(ffs_tab[i].ffs_data);
366 goto error;
367 }
368 }
232 369
233 for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) { 370 for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
234 struct gfs_configuration *c = gfs_configurations + i; 371 struct gfs_configuration *c = gfs_configurations + i;
@@ -246,16 +383,22 @@ static int gfs_bind(struct usb_composite_dev *cdev)
246 return 0; 383 return 0;
247 384
248error_unbind: 385error_unbind:
249 functionfs_unbind(gfs_ffs_data); 386 for (i = 0; i < func_num; i++)
387 functionfs_unbind(ffs_tab[i].ffs_data);
250error: 388error:
251 gether_cleanup(); 389 gether_cleanup();
252error_quick: 390error_quick:
253 gfs_ffs_data = NULL; 391 gfs_ether_setup = false;
254 return ret; 392 return ret;
255} 393}
256 394
395/*
396 * It is assumed that gfs_unbind is called from a context where gfs_lock is held
397 */
257static int gfs_unbind(struct usb_composite_dev *cdev) 398static int gfs_unbind(struct usb_composite_dev *cdev)
258{ 399{
400 int i;
401
259 ENTER(); 402 ENTER();
260 403
261 /* 404 /*
@@ -266,22 +409,29 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
266 * from composite on orror recovery, but what you're gonna 409 * from composite on orror recovery, but what you're gonna
267 * do...? 410 * do...?
268 */ 411 */
269 if (gfs_ffs_data) { 412 if (gfs_ether_setup)
270 gether_cleanup(); 413 gether_cleanup();
271 functionfs_unbind(gfs_ffs_data); 414 gfs_ether_setup = false;
272 gfs_ffs_data = NULL; 415
273 } 416 for (i = func_num; --i; )
417 if (ffs_tab[i].ffs_data)
418 functionfs_unbind(ffs_tab[i].ffs_data);
274 419
275 return 0; 420 return 0;
276} 421}
277 422
423/*
424 * It is assumed that gfs_do_config is called from a context where
425 * gfs_lock is held
426 */
278static int gfs_do_config(struct usb_configuration *c) 427static int gfs_do_config(struct usb_configuration *c)
279{ 428{
280 struct gfs_configuration *gc = 429 struct gfs_configuration *gc =
281 container_of(c, struct gfs_configuration, c); 430 container_of(c, struct gfs_configuration, c);
431 int i;
282 int ret; 432 int ret;
283 433
284 if (WARN_ON(!gfs_ffs_data)) 434 if (missing_funcs)
285 return -ENODEV; 435 return -ENODEV;
286 436
287 if (gadget_is_otg(c->cdev->gadget)) { 437 if (gadget_is_otg(c->cdev->gadget)) {
@@ -295,9 +445,11 @@ static int gfs_do_config(struct usb_configuration *c)
295 return ret; 445 return ret;
296 } 446 }
297 447
298 ret = functionfs_bind_config(c->cdev, c, gfs_ffs_data); 448 for (i = 0; i < func_num; i++) {
299 if (unlikely(ret < 0)) 449 ret = functionfs_bind_config(c->cdev, c, ffs_tab[i].ffs_data);
300 return ret; 450 if (unlikely(ret < 0))
451 return ret;
452 }
301 453
302 /* 454 /*
303 * After previous do_configs there may be some invalid 455 * After previous do_configs there may be some invalid
diff --git a/include/linux/usb/functionfs.h b/include/linux/usb/functionfs.h
index 7587ef934ba8..a843d0851364 100644
--- a/include/linux/usb/functionfs.h
+++ b/include/linux/usb/functionfs.h
@@ -190,8 +190,10 @@ static int functionfs_ready_callback(struct ffs_data *ffs)
190 __attribute__((warn_unused_result, nonnull)); 190 __attribute__((warn_unused_result, nonnull));
191static void functionfs_closed_callback(struct ffs_data *ffs) 191static void functionfs_closed_callback(struct ffs_data *ffs)
192 __attribute__((nonnull)); 192 __attribute__((nonnull));
193static int functionfs_check_dev_callback(const char *dev_name) 193static void *functionfs_acquire_dev_callback(const char *dev_name)
194 __attribute__((warn_unused_result, nonnull)); 194 __attribute__((warn_unused_result, nonnull));
195static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
196 __attribute__((nonnull));
195 197
196 198
197#endif 199#endif