usb: gadget: FunctionFS: add devices management code
This will be required in order to use the new function interface (usb_get_function_instance/usb_put_function_instance) Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com> Signed-off-by: Kyunmgin Park <kyungmin.park@samsung.com> Acked-by: Michal Nazarewicz <mina86@mina86.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
e72c39c069
commit
4b187fceec
|
@ -90,7 +90,7 @@ enum ffs_state {
|
|||
|
||||
/*
|
||||
* We've got descriptors and strings. We are or have called
|
||||
* functionfs_ready_callback(). functionfs_bind() may have
|
||||
* ffs_ready(). functionfs_bind() may have
|
||||
* been called but we don't know.
|
||||
*
|
||||
* This is the only state in which operations on epfiles may
|
||||
|
@ -103,7 +103,7 @@ enum ffs_state {
|
|||
* we encounter an unrecoverable error. The only
|
||||
* unrecoverable error is situation when after reading strings
|
||||
* from user space we fail to initialise epfiles or
|
||||
* functionfs_ready_callback() returns with error (<0).
|
||||
* ffs_ready() returns with error (<0).
|
||||
*
|
||||
* In this state no open(2), read(2) or write(2) (both on ep0
|
||||
* as well as epfile) may succeed (at this point epfiles are
|
||||
|
@ -361,6 +361,15 @@ ffs_sb_create_file(struct super_block *sb, const char *name, void *data,
|
|||
const struct file_operations *fops,
|
||||
struct dentry **dentry_p);
|
||||
|
||||
/* Devices management *******************************************************/
|
||||
|
||||
DEFINE_MUTEX(ffs_lock);
|
||||
|
||||
static struct ffs_dev *ffs_find_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);
|
||||
static void ffs_closed(struct ffs_data *ffs);
|
||||
|
||||
/* Misc helper functions ****************************************************/
|
||||
|
||||
|
@ -486,7 +495,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
|
|||
ffs->state = FFS_ACTIVE;
|
||||
mutex_unlock(&ffs->mutex);
|
||||
|
||||
ret = functionfs_ready_callback(ffs);
|
||||
ret = ffs_ready(ffs);
|
||||
if (unlikely(ret < 0)) {
|
||||
ffs->state = FFS_CLOSING;
|
||||
return ret;
|
||||
|
@ -1218,7 +1227,7 @@ ffs_fs_mount(struct file_system_type *t, int flags,
|
|||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ffs_dev = functionfs_acquire_dev_callback(dev_name);
|
||||
ffs_dev = ffs_acquire_dev(dev_name);
|
||||
if (IS_ERR(ffs_dev)) {
|
||||
ffs_data_put(ffs);
|
||||
return ERR_CAST(ffs_dev);
|
||||
|
@ -1228,7 +1237,7 @@ ffs_fs_mount(struct file_system_type *t, int flags,
|
|||
|
||||
rv = mount_nodev(t, flags, &data, ffs_sb_fill);
|
||||
if (IS_ERR(rv) && data.ffs_data) {
|
||||
functionfs_release_dev_callback(data.ffs_data);
|
||||
ffs_release_dev(data.ffs_data);
|
||||
ffs_data_put(data.ffs_data);
|
||||
}
|
||||
return rv;
|
||||
|
@ -1241,7 +1250,7 @@ ffs_fs_kill_sb(struct super_block *sb)
|
|||
|
||||
kill_litter_super(sb);
|
||||
if (sb->s_fs_info) {
|
||||
functionfs_release_dev_callback(sb->s_fs_info);
|
||||
ffs_release_dev(sb->s_fs_info);
|
||||
ffs_data_put(sb->s_fs_info);
|
||||
}
|
||||
}
|
||||
|
@ -1354,7 +1363,7 @@ static void ffs_data_clear(struct ffs_data *ffs)
|
|||
ENTER();
|
||||
|
||||
if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags))
|
||||
functionfs_closed_callback(ffs);
|
||||
ffs_closed(ffs);
|
||||
|
||||
BUG_ON(ffs->gadget);
|
||||
|
||||
|
@ -2466,6 +2475,221 @@ static int ffs_func_revmap_intf(struct ffs_function *func, u8 intf)
|
|||
}
|
||||
|
||||
|
||||
/* Devices management *******************************************************/
|
||||
|
||||
static LIST_HEAD(ffs_devices);
|
||||
|
||||
static struct ffs_dev *_ffs_find_dev(const char *name)
|
||||
{
|
||||
struct ffs_dev *dev;
|
||||
|
||||
list_for_each_entry(dev, &ffs_devices, entry) {
|
||||
if (!dev->name || !name)
|
||||
continue;
|
||||
if (strcmp(dev->name, name) == 0)
|
||||
return dev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ffs_lock must be taken by the caller of this function
|
||||
*/
|
||||
static struct ffs_dev *ffs_get_single_dev(void)
|
||||
{
|
||||
struct ffs_dev *dev;
|
||||
|
||||
if (list_is_singular(&ffs_devices)) {
|
||||
dev = list_first_entry(&ffs_devices, struct ffs_dev, entry);
|
||||
if (dev->single)
|
||||
return dev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* ffs_lock must be taken by the caller of this function
|
||||
*/
|
||||
static struct ffs_dev *ffs_find_dev(const char *name)
|
||||
{
|
||||
struct ffs_dev *dev;
|
||||
|
||||
dev = ffs_get_single_dev();
|
||||
if (dev)
|
||||
return dev;
|
||||
|
||||
return _ffs_find_dev(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* ffs_lock must be taken by the caller of this function
|
||||
*/
|
||||
struct ffs_dev *ffs_alloc_dev(void)
|
||||
{
|
||||
struct ffs_dev *dev;
|
||||
int ret;
|
||||
|
||||
if (ffs_get_single_dev())
|
||||
return ERR_PTR(-EBUSY);
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (list_empty(&ffs_devices)) {
|
||||
ret = functionfs_init();
|
||||
if (ret) {
|
||||
kfree(dev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
}
|
||||
|
||||
list_add(&dev->entry, &ffs_devices);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
/*
|
||||
* ffs_lock must be taken by the caller of this function
|
||||
* The caller is responsible for "name" being available whenever f_fs needs it
|
||||
*/
|
||||
static int _ffs_name_dev(struct ffs_dev *dev, const char *name)
|
||||
{
|
||||
struct ffs_dev *existing;
|
||||
|
||||
existing = _ffs_find_dev(name);
|
||||
if (existing)
|
||||
return -EBUSY;
|
||||
|
||||
dev->name = name;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller is responsible for "name" being available whenever f_fs needs it
|
||||
*/
|
||||
int ffs_name_dev(struct ffs_dev *dev, const char *name)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ffs_dev_lock();
|
||||
ret = _ffs_name_dev(dev, name);
|
||||
ffs_dev_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ffs_single_dev(struct ffs_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
ffs_dev_lock();
|
||||
|
||||
if (!list_is_singular(&ffs_devices))
|
||||
ret = -EBUSY;
|
||||
else
|
||||
dev->single = true;
|
||||
|
||||
ffs_dev_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* ffs_lock must be taken by the caller of this function
|
||||
*/
|
||||
void ffs_free_dev(struct ffs_dev *dev)
|
||||
{
|
||||
list_del(&dev->entry);
|
||||
kfree(dev);
|
||||
if (list_empty(&ffs_devices))
|
||||
functionfs_cleanup();
|
||||
}
|
||||
|
||||
static void *ffs_acquire_dev(const char *dev_name)
|
||||
{
|
||||
struct ffs_dev *ffs_dev;
|
||||
|
||||
ENTER();
|
||||
ffs_dev_lock();
|
||||
|
||||
ffs_dev = ffs_find_dev(dev_name);
|
||||
if (!ffs_dev)
|
||||
ffs_dev = ERR_PTR(-ENODEV);
|
||||
else if (ffs_dev->mounted)
|
||||
ffs_dev = ERR_PTR(-EBUSY);
|
||||
else
|
||||
ffs_dev->mounted = true;
|
||||
|
||||
ffs_dev_unlock();
|
||||
return ffs_dev;
|
||||
}
|
||||
|
||||
static void ffs_release_dev(struct ffs_data *ffs_data)
|
||||
{
|
||||
struct ffs_dev *ffs_dev;
|
||||
|
||||
ENTER();
|
||||
ffs_dev_lock();
|
||||
|
||||
ffs_dev = ffs_data->private_data;
|
||||
if (ffs_dev)
|
||||
ffs_dev->mounted = false;
|
||||
|
||||
ffs_dev_unlock();
|
||||
}
|
||||
|
||||
static int ffs_ready(struct ffs_data *ffs)
|
||||
{
|
||||
struct ffs_dev *ffs_obj;
|
||||
int ret = 0;
|
||||
|
||||
ENTER();
|
||||
ffs_dev_lock();
|
||||
|
||||
ffs_obj = ffs->private_data;
|
||||
if (!ffs_obj) {
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
if (WARN_ON(ffs_obj->desc_ready)) {
|
||||
ret = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ffs_obj->desc_ready = true;
|
||||
ffs_obj->ffs_data = ffs;
|
||||
|
||||
if (ffs_obj->ffs_ready_callback)
|
||||
ret = ffs_obj->ffs_ready_callback(ffs);
|
||||
|
||||
done:
|
||||
ffs_dev_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ffs_closed(struct ffs_data *ffs)
|
||||
{
|
||||
struct ffs_dev *ffs_obj;
|
||||
|
||||
ENTER();
|
||||
ffs_dev_lock();
|
||||
|
||||
ffs_obj = ffs->private_data;
|
||||
if (!ffs_obj)
|
||||
goto done;
|
||||
|
||||
ffs_obj->desc_ready = false;
|
||||
|
||||
if (ffs_obj->ffs_closed_callback)
|
||||
ffs_obj->ffs_closed_callback(ffs);
|
||||
done:
|
||||
ffs_dev_unlock();
|
||||
}
|
||||
|
||||
/* Misc helper functions ****************************************************/
|
||||
|
||||
static int ffs_mutex_lock(struct mutex *mutex, unsigned nonblock)
|
||||
|
|
|
@ -157,6 +157,8 @@ struct gfs_configuration {
|
|||
#endif
|
||||
};
|
||||
|
||||
static int functionfs_ready_callback(struct ffs_data *ffs);
|
||||
static void functionfs_closed_callback(struct ffs_data *ffs);
|
||||
static int gfs_bind(struct usb_composite_dev *cdev);
|
||||
static int gfs_unbind(struct usb_composite_dev *cdev);
|
||||
static int gfs_do_config(struct usb_configuration *c);
|
||||
|
@ -170,172 +172,113 @@ static __refdata struct usb_composite_driver gfs_driver = {
|
|||
.unbind = gfs_unbind,
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(gfs_lock);
|
||||
static unsigned int missing_funcs;
|
||||
static bool gfs_registered;
|
||||
static bool gfs_single_func;
|
||||
static struct ffs_dev *ffs_tab;
|
||||
static struct ffs_dev **ffs_tab;
|
||||
|
||||
static int __init gfs_init(void)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
ENTER();
|
||||
|
||||
if (!func_num) {
|
||||
if (func_num < 2) {
|
||||
gfs_single_func = true;
|
||||
func_num = 1;
|
||||
}
|
||||
|
||||
ffs_tab = kcalloc(func_num, sizeof *ffs_tab, GFP_KERNEL);
|
||||
ffs_tab = kcalloc(func_num, sizeof(*ffs_tab), GFP_KERNEL);
|
||||
if (!ffs_tab)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!gfs_single_func)
|
||||
for (i = 0; i < func_num; i++)
|
||||
ffs_tab[i].name = func_names[i];
|
||||
for (i = 0; i < func_num; i++) {
|
||||
ffs_dev_lock();
|
||||
ffs_tab[i] = ffs_alloc_dev();
|
||||
ffs_dev_unlock();
|
||||
if (IS_ERR(ffs_tab[i])) {
|
||||
ret = PTR_ERR(ffs_tab[i]);
|
||||
--i;
|
||||
goto no_dev;
|
||||
}
|
||||
if (gfs_single_func)
|
||||
ret = ffs_single_dev(ffs_tab[i]);
|
||||
else
|
||||
ret = ffs_name_dev(ffs_tab[i], func_names[i]);
|
||||
if (ret)
|
||||
goto no_dev;
|
||||
ffs_tab[i]->ffs_ready_callback = functionfs_ready_callback;
|
||||
ffs_tab[i]->ffs_closed_callback = functionfs_closed_callback;
|
||||
}
|
||||
|
||||
missing_funcs = func_num;
|
||||
|
||||
return functionfs_init();
|
||||
return 0;
|
||||
no_dev:
|
||||
ffs_dev_lock();
|
||||
while (i >= 0)
|
||||
ffs_free_dev(ffs_tab[i--]);
|
||||
ffs_dev_unlock();
|
||||
kfree(ffs_tab);
|
||||
return ret;
|
||||
}
|
||||
module_init(gfs_init);
|
||||
|
||||
static void __exit gfs_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
ENTER();
|
||||
mutex_lock(&gfs_lock);
|
||||
ffs_dev_lock();
|
||||
|
||||
if (gfs_registered)
|
||||
usb_composite_unregister(&gfs_driver);
|
||||
gfs_registered = false;
|
||||
|
||||
functionfs_cleanup();
|
||||
|
||||
mutex_unlock(&gfs_lock);
|
||||
for (i = 0; i < func_num; i++)
|
||||
ffs_free_dev(ffs_tab[i]);
|
||||
ffs_dev_unlock();
|
||||
kfree(ffs_tab);
|
||||
}
|
||||
module_exit(gfs_exit);
|
||||
|
||||
static struct ffs_dev *gfs_find_dev(const char *dev_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
ENTER();
|
||||
|
||||
if (gfs_single_func)
|
||||
return &ffs_tab[0];
|
||||
|
||||
for (i = 0; i < func_num; i++)
|
||||
if (strcmp(ffs_tab[i].name, dev_name) == 0)
|
||||
return &ffs_tab[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller of this function takes ffs_lock
|
||||
*/
|
||||
static int functionfs_ready_callback(struct ffs_data *ffs)
|
||||
{
|
||||
struct ffs_dev *ffs_obj;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
ENTER();
|
||||
mutex_lock(&gfs_lock);
|
||||
if (--missing_funcs)
|
||||
return 0;
|
||||
|
||||
ffs_obj = ffs->private_data;
|
||||
if (!ffs_obj) {
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
if (gfs_registered)
|
||||
return -EBUSY;
|
||||
|
||||
if (WARN_ON(ffs_obj->desc_ready)) {
|
||||
ret = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
ffs_obj->desc_ready = true;
|
||||
ffs_obj->ffs_data = ffs;
|
||||
|
||||
if (--missing_funcs) {
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (gfs_registered) {
|
||||
ret = -EBUSY;
|
||||
goto done;
|
||||
}
|
||||
gfs_registered = true;
|
||||
|
||||
ret = usb_composite_probe(&gfs_driver);
|
||||
if (unlikely(ret < 0))
|
||||
gfs_registered = false;
|
||||
|
||||
done:
|
||||
mutex_unlock(&gfs_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* The caller of this function takes ffs_lock
|
||||
*/
|
||||
static void functionfs_closed_callback(struct ffs_data *ffs)
|
||||
{
|
||||
struct ffs_dev *ffs_obj;
|
||||
|
||||
ENTER();
|
||||
mutex_lock(&gfs_lock);
|
||||
|
||||
ffs_obj = ffs->private_data;
|
||||
if (!ffs_obj)
|
||||
goto done;
|
||||
|
||||
ffs_obj->desc_ready = false;
|
||||
missing_funcs++;
|
||||
|
||||
if (gfs_registered)
|
||||
usb_composite_unregister(&gfs_driver);
|
||||
gfs_registered = false;
|
||||
|
||||
done:
|
||||
mutex_unlock(&gfs_lock);
|
||||
}
|
||||
|
||||
static void *functionfs_acquire_dev_callback(const char *dev_name)
|
||||
{
|
||||
struct ffs_dev *ffs_dev;
|
||||
|
||||
ENTER();
|
||||
mutex_lock(&gfs_lock);
|
||||
|
||||
ffs_dev = gfs_find_dev(dev_name);
|
||||
if (!ffs_dev) {
|
||||
ffs_dev = ERR_PTR(-ENODEV);
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ffs_dev->mounted) {
|
||||
ffs_dev = ERR_PTR(-EBUSY);
|
||||
goto done;
|
||||
}
|
||||
ffs_dev->mounted = true;
|
||||
|
||||
done:
|
||||
mutex_unlock(&gfs_lock);
|
||||
return ffs_dev;
|
||||
}
|
||||
|
||||
static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
|
||||
{
|
||||
struct ffs_dev *ffs_dev;
|
||||
|
||||
ENTER();
|
||||
mutex_lock(&gfs_lock);
|
||||
|
||||
ffs_dev = ffs_data->private_data;
|
||||
if (ffs_dev)
|
||||
ffs_dev->mounted = false;
|
||||
|
||||
mutex_unlock(&gfs_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* It is assumed that gfs_bind is called from a context where gfs_lock is held
|
||||
* It is assumed that gfs_bind is called from a context where ffs_lock is held
|
||||
*/
|
||||
static int gfs_bind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
|
@ -422,10 +365,10 @@ static int gfs_bind(struct usb_composite_dev *cdev)
|
|||
gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
|
||||
|
||||
for (i = func_num; i--; ) {
|
||||
ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);
|
||||
ret = functionfs_bind(ffs_tab[i]->ffs_data, cdev);
|
||||
if (unlikely(ret < 0)) {
|
||||
while (++i < func_num)
|
||||
functionfs_unbind(ffs_tab[i].ffs_data);
|
||||
functionfs_unbind(ffs_tab[i]->ffs_data);
|
||||
goto error_rndis;
|
||||
}
|
||||
}
|
||||
|
@ -448,7 +391,7 @@ static int gfs_bind(struct usb_composite_dev *cdev)
|
|||
|
||||
error_unbind:
|
||||
for (i = 0; i < func_num; i++)
|
||||
functionfs_unbind(ffs_tab[i].ffs_data);
|
||||
functionfs_unbind(ffs_tab[i]->ffs_data);
|
||||
error_rndis:
|
||||
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
|
||||
usb_put_function_instance(fi_rndis);
|
||||
|
@ -464,7 +407,7 @@ error:
|
|||
}
|
||||
|
||||
/*
|
||||
* It is assumed that gfs_unbind is called from a context where gfs_lock is held
|
||||
* It is assumed that gfs_unbind is called from a context where ffs_lock is held
|
||||
*/
|
||||
static int gfs_unbind(struct usb_composite_dev *cdev)
|
||||
{
|
||||
|
@ -497,15 +440,15 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
|
|||
* do...?
|
||||
*/
|
||||
for (i = func_num; i--; )
|
||||
if (ffs_tab[i].ffs_data)
|
||||
functionfs_unbind(ffs_tab[i].ffs_data);
|
||||
if (ffs_tab[i]->ffs_data)
|
||||
functionfs_unbind(ffs_tab[i]->ffs_data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* It is assumed that gfs_do_config is called from a context where
|
||||
* gfs_lock is held
|
||||
* ffs_lock is held
|
||||
*/
|
||||
static int gfs_do_config(struct usb_configuration *c)
|
||||
{
|
||||
|
@ -529,7 +472,7 @@ static int gfs_do_config(struct usb_configuration *c)
|
|||
}
|
||||
|
||||
for (i = 0; i < func_num; i++) {
|
||||
ret = functionfs_bind_config(c->cdev, c, ffs_tab[i].ffs_data);
|
||||
ret = functionfs_bind_config(c->cdev, c, ffs_tab[i]->ffs_data);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -17,12 +17,36 @@
|
|||
#define U_FFS_H
|
||||
|
||||
#include <linux/usb/composite.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
struct ffs_dev {
|
||||
const char *name;
|
||||
bool mounted;
|
||||
bool desc_ready;
|
||||
bool single;
|
||||
struct ffs_data *ffs_data;
|
||||
struct list_head entry;
|
||||
|
||||
int (*ffs_ready_callback)(struct ffs_data *ffs);
|
||||
void (*ffs_closed_callback)(struct ffs_data *ffs);
|
||||
};
|
||||
|
||||
extern struct mutex ffs_lock;
|
||||
|
||||
static inline void ffs_dev_lock(void)
|
||||
{
|
||||
mutex_lock(&ffs_lock);
|
||||
}
|
||||
|
||||
static inline void ffs_dev_unlock(void)
|
||||
{
|
||||
mutex_unlock(&ffs_lock);
|
||||
}
|
||||
|
||||
struct ffs_dev *ffs_alloc_dev(void);
|
||||
int ffs_name_dev(struct ffs_dev *dev, const char *name);
|
||||
int ffs_single_dev(struct ffs_dev *dev);
|
||||
void ffs_free_dev(struct ffs_dev *dev);
|
||||
|
||||
#endif /* U_FFS_H */
|
||||
|
|
|
@ -8,10 +8,6 @@ struct ffs_data;
|
|||
struct usb_composite_dev;
|
||||
struct usb_configuration;
|
||||
|
||||
|
||||
static int functionfs_init(void) __attribute__((warn_unused_result));
|
||||
static void functionfs_cleanup(void);
|
||||
|
||||
static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)
|
||||
__attribute__((warn_unused_result, nonnull));
|
||||
static void functionfs_unbind(struct ffs_data *ffs)
|
||||
|
@ -23,14 +19,4 @@ static int functionfs_bind_config(struct usb_composite_dev *cdev,
|
|||
__attribute__((warn_unused_result, nonnull));
|
||||
|
||||
|
||||
static int functionfs_ready_callback(struct ffs_data *ffs)
|
||||
__attribute__((warn_unused_result, nonnull));
|
||||
static void functionfs_closed_callback(struct ffs_data *ffs)
|
||||
__attribute__((nonnull));
|
||||
static void *functionfs_acquire_dev_callback(const char *dev_name)
|
||||
__attribute__((warn_unused_result, nonnull));
|
||||
static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
|
||||
__attribute__((nonnull));
|
||||
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue