mirror of
https://github.com/linux-usb-gadgets/libusbgx.git
synced 2025-07-22 00:45:07 +03:00
libusbgx: common: Add alloc_inst() and free_inst() callbacks
Those callback can be used by specific function type to allocate and then free more memory than in raw usbg_function structure. Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
This commit is contained in:
parent
8c5f9cde66
commit
5ea221a027
10 changed files with 166 additions and 42 deletions
|
@ -46,6 +46,14 @@ struct usbg_function_type
|
|||
/* Name of this function type */
|
||||
char *name;
|
||||
|
||||
/* Called to allocate instance of function */
|
||||
int (*alloc_inst)(struct usbg_function_type *, usbg_function_type,
|
||||
const char *, const char *, usbg_gadget *,
|
||||
struct usbg_function **);
|
||||
|
||||
/* Called to free memory used by function */
|
||||
void (*free_inst)(struct usbg_function_type *, struct usbg_function *);
|
||||
|
||||
/*
|
||||
* Called when user would like to remove this function.
|
||||
* If this callback is provided it will be always called
|
||||
|
@ -252,6 +260,55 @@ int usbg_check_dir(const char *path);
|
|||
#define usbg_config_is_string(node) \
|
||||
(config_setting_type(node) == CONFIG_TYPE_STRING)
|
||||
|
||||
int usbg_init_function(struct usbg_function *f,
|
||||
struct usbg_function_type *ops,
|
||||
usbg_function_type type,
|
||||
const char *type_name,
|
||||
const char *instance,
|
||||
const char *path,
|
||||
struct usbg_gadget *parent);
|
||||
|
||||
int usbg_cleanup_function(struct usbg_function *f);
|
||||
|
||||
#define GENERIC_ALLOC_INST(prefix, _type, _member) \
|
||||
static int prefix##_alloc_inst(struct usbg_function_type *type, \
|
||||
usbg_function_type type_code, \
|
||||
const char *instance, const char *path, \
|
||||
struct usbg_gadget *parent, \
|
||||
struct usbg_function **f) \
|
||||
{ \
|
||||
_type *ff; \
|
||||
int ret; \
|
||||
\
|
||||
ff = malloc(sizeof(*ff)); \
|
||||
if (!ff) \
|
||||
return USBG_ERROR_NO_MEM; \
|
||||
\
|
||||
ret = usbg_init_function(&ff->_member, type, type_code, \
|
||||
type->name, instance, path, parent); \
|
||||
if (ret != USBG_SUCCESS) \
|
||||
goto free_func; \
|
||||
\
|
||||
*f = &ff->_member; \
|
||||
\
|
||||
return ret; \
|
||||
\
|
||||
free_func: \
|
||||
free(ff); \
|
||||
out: \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define GENERIC_FREE_INST(prefix, _type, _member) \
|
||||
static void prefix##_free_inst(struct usbg_function_type *type, \
|
||||
struct usbg_function *f) \
|
||||
{ \
|
||||
_type *ff = container_of(f, _type, _member); \
|
||||
\
|
||||
usbg_cleanup_function(&ff->_member); \
|
||||
free(ff); \
|
||||
}
|
||||
|
||||
typedef int (*usbg_attr_get_func)(const char *, const char *, const char *, void *);
|
||||
typedef int (*usbg_attr_set_func)(const char *, const char *, const char *, void *);
|
||||
|
||||
|
|
|
@ -18,6 +18,14 @@
|
|||
#include <libconfig.h>
|
||||
#endif
|
||||
|
||||
struct usbg_f_ether {
|
||||
struct usbg_function func;
|
||||
};
|
||||
|
||||
GENERIC_ALLOC_INST(ether, struct usbg_f_ether, func);
|
||||
|
||||
GENERIC_FREE_INST(ether, struct usbg_f_ether, func);
|
||||
|
||||
static int ether_set_attrs(struct usbg_function *f,
|
||||
const usbg_function_attrs *f_attrs)
|
||||
{
|
||||
|
@ -216,6 +224,8 @@ out:
|
|||
#endif /* HAS_LIBCONFIG */
|
||||
|
||||
#define ETHER_FUNCTION_OPTS \
|
||||
.alloc_inst = ether_alloc_inst, \
|
||||
.free_inst = ether_free_inst, \
|
||||
.set_attrs = ether_set_attrs, \
|
||||
.get_attrs = ether_get_attrs, \
|
||||
.cleanup_attrs = ether_cleanup_attrs, \
|
||||
|
|
|
@ -17,6 +17,14 @@
|
|||
#include <libconfig.h>
|
||||
#endif
|
||||
|
||||
struct usbg_f_fs {
|
||||
struct usbg_function func;
|
||||
};
|
||||
|
||||
GENERIC_ALLOC_INST(ffs, struct usbg_f_fs, func);
|
||||
|
||||
GENERIC_FREE_INST(ffs, struct usbg_f_fs, func);
|
||||
|
||||
static int ffs_set_attrs(struct usbg_function *f,
|
||||
const usbg_function_attrs *f_attrs)
|
||||
{
|
||||
|
@ -72,6 +80,8 @@ static int ffs_libconfig_export(struct usbg_function *f,
|
|||
|
||||
struct usbg_function_type usbg_f_type_ffs = {
|
||||
.name = "ffs",
|
||||
.alloc_inst = ffs_alloc_inst,
|
||||
.free_inst = ffs_free_inst,
|
||||
.set_attrs = ffs_set_attrs,
|
||||
.get_attrs = ffs_get_attrs,
|
||||
.cleanup_attrs = ffs_cleanup_attrs,
|
||||
|
|
|
@ -17,6 +17,14 @@
|
|||
#include <libconfig.h>
|
||||
#endif
|
||||
|
||||
struct usbg_f_loopback {
|
||||
struct usbg_function func;
|
||||
};
|
||||
|
||||
GENERIC_ALLOC_INST(loopback, struct usbg_f_loopback, func);
|
||||
|
||||
GENERIC_FREE_INST(loopback, struct usbg_f_loopback, func);
|
||||
|
||||
static int loopback_set_attrs(struct usbg_function *f,
|
||||
const usbg_function_attrs *f_attrs)
|
||||
{
|
||||
|
@ -141,6 +149,8 @@ out:
|
|||
|
||||
struct usbg_function_type usbg_f_type_loopback = {
|
||||
.name = "loopback",
|
||||
.alloc_inst = loopback_alloc_inst,
|
||||
.free_inst = loopback_free_inst,
|
||||
.set_attrs = loopback_set_attrs,
|
||||
.get_attrs = loopback_get_attrs,
|
||||
#ifdef HAS_LIBCONFIG
|
||||
|
|
|
@ -18,6 +18,14 @@
|
|||
#include <libconfig.h>
|
||||
#endif
|
||||
|
||||
struct usbg_f_midi {
|
||||
struct usbg_function func;
|
||||
};
|
||||
|
||||
GENERIC_ALLOC_INST(midi, struct usbg_f_midi, func);
|
||||
|
||||
GENERIC_FREE_INST(midi, struct usbg_f_midi, func);
|
||||
|
||||
static int midi_set_attrs(struct usbg_function *f,
|
||||
const usbg_function_attrs *f_attrs)
|
||||
{
|
||||
|
@ -216,6 +224,8 @@ out:
|
|||
|
||||
struct usbg_function_type usbg_f_type_midi = {
|
||||
.name = "midi",
|
||||
.alloc_inst = midi_alloc_inst,
|
||||
.free_inst = midi_free_inst,
|
||||
.set_attrs = midi_set_attrs,
|
||||
.get_attrs = midi_get_attrs,
|
||||
.cleanup_attrs = midi_cleanup_attrs,
|
||||
|
|
|
@ -21,6 +21,14 @@
|
|||
#include <libconfig.h>
|
||||
#endif
|
||||
|
||||
struct usbg_f_ms {
|
||||
struct usbg_function func;
|
||||
};
|
||||
|
||||
GENERIC_ALLOC_INST(ms, struct usbg_f_ms, func);
|
||||
|
||||
GENERIC_FREE_INST(ms, struct usbg_f_ms, func);
|
||||
|
||||
static inline int lun_select(const struct dirent *dent)
|
||||
{
|
||||
int ret;
|
||||
|
@ -652,6 +660,8 @@ out:
|
|||
|
||||
struct usbg_function_type usbg_f_type_ms = {
|
||||
.name = "mass_storage",
|
||||
.alloc_inst = ms_alloc_inst,
|
||||
.free_inst = ms_free_inst,
|
||||
.set_attrs = ms_set_attrs,
|
||||
.get_attrs = ms_get_attrs,
|
||||
.cleanup_attrs = ms_cleanup_attrs,
|
||||
|
|
|
@ -18,6 +18,14 @@
|
|||
#include <libconfig.h>
|
||||
#endif
|
||||
|
||||
struct usbg_f_phonet {
|
||||
struct usbg_function func;
|
||||
};
|
||||
|
||||
GENERIC_ALLOC_INST(phonet, struct usbg_f_phonet, func);
|
||||
|
||||
GENERIC_FREE_INST(phonet, struct usbg_f_phonet, func);
|
||||
|
||||
static int phonet_set_attrs(struct usbg_function *f,
|
||||
const usbg_function_attrs *f_attrs)
|
||||
{
|
||||
|
@ -71,6 +79,8 @@ static int phonet_libconfig_export(struct usbg_function *f,
|
|||
|
||||
struct usbg_function_type usbg_f_type_phonet = {
|
||||
.name = "phonet",
|
||||
.alloc_inst = phonet_alloc_inst,
|
||||
.free_inst = phonet_free_inst,
|
||||
.set_attrs = phonet_set_attrs,
|
||||
.get_attrs = phonet_get_attrs,
|
||||
.cleanup_attrs = phonet_cleanup_attrs,
|
||||
|
|
|
@ -17,6 +17,14 @@
|
|||
#include <libconfig.h>
|
||||
#endif
|
||||
|
||||
struct usbg_f_serial {
|
||||
struct usbg_function func;
|
||||
};
|
||||
|
||||
GENERIC_ALLOC_INST(serial, struct usbg_f_serial, func);
|
||||
|
||||
GENERIC_FREE_INST(serial, struct usbg_f_serial, func);
|
||||
|
||||
static int serial_set_attrs(struct usbg_function *f,
|
||||
const usbg_function_attrs *f_attrs)
|
||||
{
|
||||
|
@ -92,6 +100,8 @@ static int serial_libconfig_import(struct usbg_function *f,
|
|||
|
||||
/* We don' import port_num as it is read only */
|
||||
#define SERIAL_FUNCTION_OPTS \
|
||||
.alloc_inst = serial_alloc_inst, \
|
||||
.free_inst = serial_free_inst, \
|
||||
.set_attrs = serial_set_attrs, \
|
||||
.get_attrs = serial_get_attrs, \
|
||||
SERIAL_LIBCONFIG_DEP_OPS, \
|
||||
|
|
48
src/usbg.c
48
src/usbg.c
|
@ -284,10 +284,8 @@ static inline void usbg_free_binding(usbg_binding *b)
|
|||
|
||||
static inline void usbg_free_function(usbg_function *f)
|
||||
{
|
||||
free(f->path);
|
||||
free(f->name);
|
||||
free(f->label);
|
||||
free(f);
|
||||
if (f->ops->free_inst)
|
||||
f->ops->free_inst(f->ops, f);
|
||||
}
|
||||
|
||||
static void usbg_free_config(usbg_config *c)
|
||||
|
@ -426,46 +424,16 @@ out:
|
|||
return c;
|
||||
}
|
||||
|
||||
static usbg_function *usbg_allocate_function(const char *path,
|
||||
usbg_function_type type, const char *instance, usbg_gadget *parent)
|
||||
static usbg_function *
|
||||
usbg_allocate_function(const char *path, usbg_function_type type,
|
||||
const char *instance, usbg_gadget *parent)
|
||||
{
|
||||
usbg_function *f;
|
||||
const char *type_name;
|
||||
int ret;
|
||||
|
||||
f = malloc(sizeof(*f));
|
||||
if (!f)
|
||||
goto out;
|
||||
|
||||
f->label = NULL;
|
||||
type_name = usbg_get_function_type_str(type);
|
||||
if (!type_name) {
|
||||
free(f);
|
||||
f = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = asprintf(&(f->name), "%s.%s", type_name, instance);
|
||||
if (ret < 0) {
|
||||
free(f);
|
||||
f = NULL;
|
||||
goto out;
|
||||
}
|
||||
f->instance = f->name + strlen(type_name) + 1;
|
||||
f->path = strdup(path);
|
||||
f->parent = parent;
|
||||
f->type = type;
|
||||
f->ops = function_types[type];
|
||||
|
||||
if (!(f->path)) {
|
||||
free(f->name);
|
||||
free(f->path);
|
||||
free(f);
|
||||
f = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
return f;
|
||||
ret = function_types[type]->alloc_inst(function_types[type], type,
|
||||
instance, path, parent, &f);
|
||||
return ret == 0 ? f : NULL;
|
||||
}
|
||||
|
||||
static usbg_binding *usbg_allocate_binding(const char *path, const char *name,
|
||||
|
|
|
@ -265,7 +265,30 @@ int usbg_check_dir(const char *path)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int usbg_init_function(struct usbg_function *f,
|
||||
struct usbg_function_type *ops,
|
||||
usbg_function_type type,
|
||||
const char *type_name,
|
||||
const char *instance,
|
||||
const char *path,
|
||||
struct usbg_gadget *parent)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = asprintf(&(f->name), "%s.%s", type_name, instance);
|
||||
if (ret < 0)
|
||||
return USBG_ERROR_NO_MEM;
|
||||
|
||||
f->instance = f->name + strlen(type_name) + 1;
|
||||
f->path = strdup(path);
|
||||
f->parent = parent;
|
||||
f->type = type;
|
||||
f->ops = ops;
|
||||
f->label = NULL;
|
||||
memset(&f->fnode, 0, sizeof(f->fnode));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usbg_get_ether_addr(const char *path, const char *name,
|
||||
const char *attr, void *val)
|
||||
|
@ -423,3 +446,9 @@ int usbg_set_config_node_ether_addr(config_setting_t *root,
|
|||
return usbg_set_config_node_string(root, node_name, &ptr);
|
||||
}
|
||||
|
||||
int usbg_cleanup_function(struct usbg_function *f)
|
||||
{
|
||||
free(f->path);
|
||||
free(f->name);
|
||||
free(f->label);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue