Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 354651
b: refs/heads/master
c: 0062f6e
h: refs/heads/master
i:
  354649: bd407ed
  354647: b2170d3
v: v3
  • Loading branch information
Sebastian Andrzej Siewior authored and Felipe Balbi committed Jan 21, 2013
1 parent c91c514 commit c1ca84b
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 59835ad727876f6ce5c18ce075e144a8fa989461
refs/heads/master: 0062f6e56f70bd2230ba1ebd1667d1b32a1af3b2
116 changes: 116 additions & 0 deletions trunk/drivers/usb/gadget/functions.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/err.h>

#include <linux/usb/composite.h>

static LIST_HEAD(func_list);
static DEFINE_MUTEX(func_lock);

static struct usb_function_instance *try_get_usb_function_instance(const char *name)
{
struct usb_function_driver *fd;
struct usb_function_instance *fi;

fi = ERR_PTR(-ENOENT);
mutex_lock(&func_lock);
list_for_each_entry(fd, &func_list, list) {

if (strcmp(name, fd->name))
continue;

if (!try_module_get(fd->mod)) {
fi = ERR_PTR(-EBUSY);
break;
}
fi = fd->alloc_inst();
if (IS_ERR(fi))
module_put(fd->mod);
else
fi->fd = fd;
break;
}
mutex_unlock(&func_lock);
return fi;
}

struct usb_function_instance *usb_get_function_instance(const char *name)
{
struct usb_function_instance *fi;
int ret;

fi = try_get_usb_function_instance(name);
if (!IS_ERR(fi))
return fi;
ret = PTR_ERR(fi);
if (ret != -ENOENT)
return fi;
ret = request_module("usbfunc:%s", name);
if (ret < 0)
return ERR_PTR(ret);
return try_get_usb_function_instance(name);
}
EXPORT_SYMBOL_GPL(usb_get_function_instance);

struct usb_function *usb_get_function(struct usb_function_instance *fi)
{
struct usb_function *f;

f = fi->fd->alloc_func(fi);
if (IS_ERR(f))
return f;
f->fi = fi;
return f;
}
EXPORT_SYMBOL_GPL(usb_get_function);

void usb_put_function_instance(struct usb_function_instance *fi)
{
struct module *mod;

if (!fi)
return;

mod = fi->fd->mod;
fi->free_func_inst(fi);
module_put(mod);
}
EXPORT_SYMBOL_GPL(usb_put_function_instance);

void usb_put_function(struct usb_function *f)
{
if (!f)
return;

f->free_func(f);
}
EXPORT_SYMBOL_GPL(usb_put_function);

int usb_function_register(struct usb_function_driver *newf)
{
struct usb_function_driver *fd;
int ret;

ret = -EEXIST;

mutex_lock(&func_lock);
list_for_each_entry(fd, &func_list, list) {
if (!strcmp(fd->name, newf->name))
goto out;
}
ret = 0;
list_add_tail(&newf->list, &func_list);
out:
mutex_unlock(&func_lock);
return ret;
}
EXPORT_SYMBOL_GPL(usb_function_register);

void usb_function_unregister(struct usb_function_driver *fd)
{
mutex_lock(&func_lock);
list_del(&fd->list);
mutex_unlock(&func_lock);
}
EXPORT_SYMBOL_GPL(usb_function_unregister);
1 change: 1 addition & 0 deletions trunk/include/linux/usb/composite.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ struct usb_function {
/* internals */
struct list_head list;
DECLARE_BITMAP(endpoints, 32);
const struct usb_function_instance *fi;
};

int usb_add_function(struct usb_configuration *, struct usb_function *);
Expand Down

0 comments on commit c1ca84b

Please sign in to comment.