Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: gadget: FunctionFS: add configfs support

Add support for using FunctionFS in configfs-based USB gadgets.

[ balbi@ti.com : removed redefinition of VERBOSE_DEBUG and few
trailing whitespaces ]

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>
Signed-off-by: Felipe Balbi <balbi@ti.com>

authored by

Andrzej Pietrasiewicz and committed by
Felipe Balbi
b658499f 3d8d72a4

+103 -1
+9
Documentation/ABI/testing/configfs-usb-gadget-ffs
··· 1 + What: /config/usb-gadget/gadget/functions/ffs.name 2 + Date: Nov 2013 3 + KenelVersion: 3.13 4 + Description: The purpose of this directory is to create and remove it. 5 + 6 + A corresponding USB function instance is created/removed. 7 + There are no attributes here. 8 + 9 + All parameters are set through FunctionFS.
+12
drivers/usb/gadget/Kconfig
··· 701 701 test software, like the "usbtest" driver, to put your hardware 702 702 and its driver through a basic set of functional tests. 703 703 704 + config USB_CONFIGFS_F_FS 705 + boolean "Function filesystem (FunctionFS)" 706 + depends on USB_CONFIGFS 707 + select USB_F_FS 708 + help 709 + The Function Filesystem (FunctionFS) lets one create USB 710 + composite functions in user space in the same way GadgetFS 711 + lets one create USB gadgets in user space. This allows creation 712 + of composite gadgets such that some of the functions are 713 + implemented in kernel space (for instance Ethernet, serial or 714 + mass storage) and other are implemented in user space. 715 + 704 716 config USB_ZERO 705 717 tristate "Gadget Zero (DEVELOPMENT)" 706 718 select USB_LIBCOMPOSITE
+79 -1
drivers/usb/gadget/f_fs.c
··· 29 29 #include <linux/usb/functionfs.h> 30 30 31 31 #include "u_fs.h" 32 + #include "configfs.h" 32 33 33 34 #define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */ 34 35 ··· 162 161 EXPORT_SYMBOL(ffs_lock); 163 162 164 163 static struct ffs_dev *ffs_find_dev(const char *name); 164 + static int _ffs_name_dev(struct ffs_dev *dev, const char *name); 165 165 static void *ffs_acquire_dev(const char *dev_name); 166 166 static void ffs_release_dev(struct ffs_data *ffs_data); 167 167 static int ffs_ready(struct ffs_data *ffs); ··· 2263 2261 if (strcmp(dev->name, name) == 0) 2264 2262 return dev; 2265 2263 } 2266 - 2264 + 2267 2265 return NULL; 2268 2266 } 2269 2267 ··· 2297 2295 return _ffs_find_dev(name); 2298 2296 } 2299 2297 2298 + /* Configfs support *********************************************************/ 2299 + 2300 + static inline struct f_fs_opts *to_ffs_opts(struct config_item *item) 2301 + { 2302 + return container_of(to_config_group(item), struct f_fs_opts, 2303 + func_inst.group); 2304 + } 2305 + 2306 + static void ffs_attr_release(struct config_item *item) 2307 + { 2308 + struct f_fs_opts *opts = to_ffs_opts(item); 2309 + 2310 + usb_put_function_instance(&opts->func_inst); 2311 + } 2312 + 2313 + static struct configfs_item_operations ffs_item_ops = { 2314 + .release = ffs_attr_release, 2315 + }; 2316 + 2317 + static struct config_item_type ffs_func_type = { 2318 + .ct_item_ops = &ffs_item_ops, 2319 + .ct_owner = THIS_MODULE, 2320 + }; 2321 + 2322 + 2300 2323 /* Function registration interface ******************************************/ 2301 2324 2302 2325 static void ffs_free_inst(struct usb_function_instance *f) ··· 2335 2308 kfree(opts); 2336 2309 } 2337 2310 2311 + #define MAX_INST_NAME_LEN 40 2312 + 2313 + static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name) 2314 + { 2315 + struct f_fs_opts *opts; 2316 + char *ptr; 2317 + const char *tmp; 2318 + int name_len, ret; 2319 + 2320 + name_len = strlen(name) + 1; 2321 + if (name_len > MAX_INST_NAME_LEN) 2322 + return -ENAMETOOLONG; 2323 + 2324 + ptr = kstrndup(name, name_len, GFP_KERNEL); 2325 + if (!ptr) 2326 + return -ENOMEM; 2327 + 2328 + opts = to_f_fs_opts(fi); 2329 + tmp = NULL; 2330 + 2331 + ffs_dev_lock(); 2332 + 2333 + tmp = opts->dev->name_allocated ? opts->dev->name : NULL; 2334 + ret = _ffs_name_dev(opts->dev, ptr); 2335 + if (ret) { 2336 + kfree(ptr); 2337 + ffs_dev_unlock(); 2338 + return ret; 2339 + } 2340 + opts->dev->name_allocated = true; 2341 + 2342 + ffs_dev_unlock(); 2343 + 2344 + kfree(tmp); 2345 + 2346 + return 0; 2347 + } 2348 + 2338 2349 static struct usb_function_instance *ffs_alloc_inst(void) 2339 2350 { 2340 2351 struct f_fs_opts *opts; ··· 2382 2317 if (!opts) 2383 2318 return ERR_PTR(-ENOMEM); 2384 2319 2320 + opts->func_inst.set_inst_name = ffs_set_inst_name; 2385 2321 opts->func_inst.free_func_inst = ffs_free_inst; 2386 2322 ffs_dev_lock(); 2387 2323 dev = ffs_alloc_dev(); ··· 2392 2326 return ERR_CAST(dev); 2393 2327 } 2394 2328 opts->dev = dev; 2329 + dev->opts = opts; 2395 2330 2331 + config_group_init_type_name(&opts->func_inst.group, "", 2332 + &ffs_func_type); 2396 2333 return &opts->func_inst; 2397 2334 } 2398 2335 ··· 2553 2484 void ffs_free_dev(struct ffs_dev *dev) 2554 2485 { 2555 2486 list_del(&dev->entry); 2487 + if (dev->name_allocated) 2488 + kfree(dev->name); 2556 2489 kfree(dev); 2557 2490 if (list_empty(&ffs_devices)) 2558 2491 functionfs_cleanup(); ··· 2643 2572 2644 2573 if (ffs_obj->ffs_closed_callback) 2645 2574 ffs_obj->ffs_closed_callback(ffs); 2575 + 2576 + if (!ffs_obj->opts || ffs_obj->opts->no_configfs 2577 + || !ffs_obj->opts->func_inst.group.cg_item.ci_parent) 2578 + goto done; 2579 + 2580 + unregister_gadget_item(ffs_obj->opts-> 2581 + func_inst.group.cg_item.ci_parent->ci_parent); 2646 2582 done: 2647 2583 ffs_dev_unlock(); 2648 2584 }
+3
drivers/usb/gadget/u_fs.h
··· 35 35 36 36 #define ENTER() pr_vdebug("%s()\n", __func__) 37 37 38 + struct f_fs_opts; 38 39 39 40 struct ffs_dev { 40 41 const char *name; 42 + bool name_allocated; 41 43 bool mounted; 42 44 bool desc_ready; 43 45 bool single; 44 46 struct ffs_data *ffs_data; 47 + struct f_fs_opts *opts; 45 48 struct list_head entry; 46 49 47 50 int (*ffs_ready_callback)(struct ffs_data *ffs);