Skip to content

Commit

Permalink
usb: gadget: FunctionFS: add configfs support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andrzej Pietrasiewicz authored and Felipe Balbi committed Dec 12, 2013
1 parent 3d8d72a commit b658499
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 1 deletion.
9 changes: 9 additions & 0 deletions Documentation/ABI/testing/configfs-usb-gadget-ffs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
What: /config/usb-gadget/gadget/functions/ffs.name
Date: Nov 2013
KenelVersion: 3.13
Description: The purpose of this directory is to create and remove it.

A corresponding USB function instance is created/removed.
There are no attributes here.

All parameters are set through FunctionFS.
12 changes: 12 additions & 0 deletions drivers/usb/gadget/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,18 @@ config USB_CONFIGFS_F_LB_SS
test software, like the "usbtest" driver, to put your hardware
and its driver through a basic set of functional tests.

config USB_CONFIGFS_F_FS
boolean "Function filesystem (FunctionFS)"
depends on USB_CONFIGFS
select USB_F_FS
help
The Function Filesystem (FunctionFS) lets one create USB
composite functions in user space in the same way GadgetFS
lets one create USB gadgets in user space. This allows creation
of composite gadgets such that some of the functions are
implemented in kernel space (for instance Ethernet, serial or
mass storage) and other are implemented in user space.

config USB_ZERO
tristate "Gadget Zero (DEVELOPMENT)"
select USB_LIBCOMPOSITE
Expand Down
80 changes: 79 additions & 1 deletion drivers/usb/gadget/f_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <linux/usb/functionfs.h>

#include "u_fs.h"
#include "configfs.h"

#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */

Expand Down Expand Up @@ -161,6 +162,7 @@ DEFINE_MUTEX(ffs_lock);
EXPORT_SYMBOL(ffs_lock);

static struct ffs_dev *ffs_find_dev(const char *name);
static int _ffs_name_dev(struct ffs_dev *dev, const char *name);
static void *ffs_acquire_dev(const char *dev_name);
static void ffs_release_dev(struct ffs_data *ffs_data);
static int ffs_ready(struct ffs_data *ffs);
Expand Down Expand Up @@ -2261,7 +2263,7 @@ static struct ffs_dev *_ffs_find_dev(const char *name)
if (strcmp(dev->name, name) == 0)
return dev;
}

return NULL;
}

Expand Down Expand Up @@ -2295,6 +2297,31 @@ static struct ffs_dev *ffs_find_dev(const char *name)
return _ffs_find_dev(name);
}

/* Configfs support *********************************************************/

static inline struct f_fs_opts *to_ffs_opts(struct config_item *item)
{
return container_of(to_config_group(item), struct f_fs_opts,
func_inst.group);
}

static void ffs_attr_release(struct config_item *item)
{
struct f_fs_opts *opts = to_ffs_opts(item);

usb_put_function_instance(&opts->func_inst);
}

static struct configfs_item_operations ffs_item_ops = {
.release = ffs_attr_release,
};

static struct config_item_type ffs_func_type = {
.ct_item_ops = &ffs_item_ops,
.ct_owner = THIS_MODULE,
};


/* Function registration interface ******************************************/

static void ffs_free_inst(struct usb_function_instance *f)
Expand All @@ -2308,6 +2335,44 @@ static void ffs_free_inst(struct usb_function_instance *f)
kfree(opts);
}

#define MAX_INST_NAME_LEN 40

static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name)
{
struct f_fs_opts *opts;
char *ptr;
const char *tmp;
int name_len, ret;

name_len = strlen(name) + 1;
if (name_len > MAX_INST_NAME_LEN)
return -ENAMETOOLONG;

ptr = kstrndup(name, name_len, GFP_KERNEL);
if (!ptr)
return -ENOMEM;

opts = to_f_fs_opts(fi);
tmp = NULL;

ffs_dev_lock();

tmp = opts->dev->name_allocated ? opts->dev->name : NULL;
ret = _ffs_name_dev(opts->dev, ptr);
if (ret) {
kfree(ptr);
ffs_dev_unlock();
return ret;
}
opts->dev->name_allocated = true;

ffs_dev_unlock();

kfree(tmp);

return 0;
}

static struct usb_function_instance *ffs_alloc_inst(void)
{
struct f_fs_opts *opts;
Expand All @@ -2317,6 +2382,7 @@ static struct usb_function_instance *ffs_alloc_inst(void)
if (!opts)
return ERR_PTR(-ENOMEM);

opts->func_inst.set_inst_name = ffs_set_inst_name;
opts->func_inst.free_func_inst = ffs_free_inst;
ffs_dev_lock();
dev = ffs_alloc_dev();
Expand All @@ -2326,7 +2392,10 @@ static struct usb_function_instance *ffs_alloc_inst(void)
return ERR_CAST(dev);
}
opts->dev = dev;
dev->opts = opts;

config_group_init_type_name(&opts->func_inst.group, "",
&ffs_func_type);
return &opts->func_inst;
}

Expand Down Expand Up @@ -2484,6 +2553,8 @@ EXPORT_SYMBOL(ffs_single_dev);
void ffs_free_dev(struct ffs_dev *dev)
{
list_del(&dev->entry);
if (dev->name_allocated)
kfree(dev->name);
kfree(dev);
if (list_empty(&ffs_devices))
functionfs_cleanup();
Expand Down Expand Up @@ -2572,6 +2643,13 @@ static void ffs_closed(struct ffs_data *ffs)

if (ffs_obj->ffs_closed_callback)
ffs_obj->ffs_closed_callback(ffs);

if (!ffs_obj->opts || ffs_obj->opts->no_configfs
|| !ffs_obj->opts->func_inst.group.cg_item.ci_parent)
goto done;

unregister_gadget_item(ffs_obj->opts->
func_inst.group.cg_item.ci_parent->ci_parent);
done:
ffs_dev_unlock();
}
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/gadget/u_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@

#define ENTER() pr_vdebug("%s()\n", __func__)

struct f_fs_opts;

struct ffs_dev {
const char *name;
bool name_allocated;
bool mounted;
bool desc_ready;
bool single;
struct ffs_data *ffs_data;
struct f_fs_opts *opts;
struct list_head entry;

int (*ffs_ready_callback)(struct ffs_data *ffs);
Expand Down

0 comments on commit b658499

Please sign in to comment.