mirror of
https://github.com/linux-usb-gadgets/libusbgx.git
synced 2025-07-23 02:35:06 +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 */
|
/* Name of this function type */
|
||||||
char *name;
|
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.
|
* Called when user would like to remove this function.
|
||||||
* If this callback is provided it will be always called
|
* 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) \
|
#define usbg_config_is_string(node) \
|
||||||
(config_setting_type(node) == CONFIG_TYPE_STRING)
|
(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_get_func)(const char *, const char *, const char *, void *);
|
||||||
typedef int (*usbg_attr_set_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>
|
#include <libconfig.h>
|
||||||
#endif
|
#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,
|
static int ether_set_attrs(struct usbg_function *f,
|
||||||
const usbg_function_attrs *f_attrs)
|
const usbg_function_attrs *f_attrs)
|
||||||
{
|
{
|
||||||
|
@ -216,6 +224,8 @@ out:
|
||||||
#endif /* HAS_LIBCONFIG */
|
#endif /* HAS_LIBCONFIG */
|
||||||
|
|
||||||
#define ETHER_FUNCTION_OPTS \
|
#define ETHER_FUNCTION_OPTS \
|
||||||
|
.alloc_inst = ether_alloc_inst, \
|
||||||
|
.free_inst = ether_free_inst, \
|
||||||
.set_attrs = ether_set_attrs, \
|
.set_attrs = ether_set_attrs, \
|
||||||
.get_attrs = ether_get_attrs, \
|
.get_attrs = ether_get_attrs, \
|
||||||
.cleanup_attrs = ether_cleanup_attrs, \
|
.cleanup_attrs = ether_cleanup_attrs, \
|
||||||
|
|
|
@ -17,6 +17,14 @@
|
||||||
#include <libconfig.h>
|
#include <libconfig.h>
|
||||||
#endif
|
#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,
|
static int ffs_set_attrs(struct usbg_function *f,
|
||||||
const usbg_function_attrs *f_attrs)
|
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 = {
|
struct usbg_function_type usbg_f_type_ffs = {
|
||||||
.name = "ffs",
|
.name = "ffs",
|
||||||
|
.alloc_inst = ffs_alloc_inst,
|
||||||
|
.free_inst = ffs_free_inst,
|
||||||
.set_attrs = ffs_set_attrs,
|
.set_attrs = ffs_set_attrs,
|
||||||
.get_attrs = ffs_get_attrs,
|
.get_attrs = ffs_get_attrs,
|
||||||
.cleanup_attrs = ffs_cleanup_attrs,
|
.cleanup_attrs = ffs_cleanup_attrs,
|
||||||
|
|
|
@ -17,6 +17,14 @@
|
||||||
#include <libconfig.h>
|
#include <libconfig.h>
|
||||||
#endif
|
#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,
|
static int loopback_set_attrs(struct usbg_function *f,
|
||||||
const usbg_function_attrs *f_attrs)
|
const usbg_function_attrs *f_attrs)
|
||||||
{
|
{
|
||||||
|
@ -141,6 +149,8 @@ out:
|
||||||
|
|
||||||
struct usbg_function_type usbg_f_type_loopback = {
|
struct usbg_function_type usbg_f_type_loopback = {
|
||||||
.name = "loopback",
|
.name = "loopback",
|
||||||
|
.alloc_inst = loopback_alloc_inst,
|
||||||
|
.free_inst = loopback_free_inst,
|
||||||
.set_attrs = loopback_set_attrs,
|
.set_attrs = loopback_set_attrs,
|
||||||
.get_attrs = loopback_get_attrs,
|
.get_attrs = loopback_get_attrs,
|
||||||
#ifdef HAS_LIBCONFIG
|
#ifdef HAS_LIBCONFIG
|
||||||
|
|
|
@ -18,6 +18,14 @@
|
||||||
#include <libconfig.h>
|
#include <libconfig.h>
|
||||||
#endif
|
#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,
|
static int midi_set_attrs(struct usbg_function *f,
|
||||||
const usbg_function_attrs *f_attrs)
|
const usbg_function_attrs *f_attrs)
|
||||||
{
|
{
|
||||||
|
@ -216,6 +224,8 @@ out:
|
||||||
|
|
||||||
struct usbg_function_type usbg_f_type_midi = {
|
struct usbg_function_type usbg_f_type_midi = {
|
||||||
.name = "midi",
|
.name = "midi",
|
||||||
|
.alloc_inst = midi_alloc_inst,
|
||||||
|
.free_inst = midi_free_inst,
|
||||||
.set_attrs = midi_set_attrs,
|
.set_attrs = midi_set_attrs,
|
||||||
.get_attrs = midi_get_attrs,
|
.get_attrs = midi_get_attrs,
|
||||||
.cleanup_attrs = midi_cleanup_attrs,
|
.cleanup_attrs = midi_cleanup_attrs,
|
||||||
|
|
|
@ -21,6 +21,14 @@
|
||||||
#include <libconfig.h>
|
#include <libconfig.h>
|
||||||
#endif
|
#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)
|
static inline int lun_select(const struct dirent *dent)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -652,6 +660,8 @@ out:
|
||||||
|
|
||||||
struct usbg_function_type usbg_f_type_ms = {
|
struct usbg_function_type usbg_f_type_ms = {
|
||||||
.name = "mass_storage",
|
.name = "mass_storage",
|
||||||
|
.alloc_inst = ms_alloc_inst,
|
||||||
|
.free_inst = ms_free_inst,
|
||||||
.set_attrs = ms_set_attrs,
|
.set_attrs = ms_set_attrs,
|
||||||
.get_attrs = ms_get_attrs,
|
.get_attrs = ms_get_attrs,
|
||||||
.cleanup_attrs = ms_cleanup_attrs,
|
.cleanup_attrs = ms_cleanup_attrs,
|
||||||
|
|
|
@ -18,6 +18,14 @@
|
||||||
#include <libconfig.h>
|
#include <libconfig.h>
|
||||||
#endif
|
#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,
|
static int phonet_set_attrs(struct usbg_function *f,
|
||||||
const usbg_function_attrs *f_attrs)
|
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 = {
|
struct usbg_function_type usbg_f_type_phonet = {
|
||||||
.name = "phonet",
|
.name = "phonet",
|
||||||
|
.alloc_inst = phonet_alloc_inst,
|
||||||
|
.free_inst = phonet_free_inst,
|
||||||
.set_attrs = phonet_set_attrs,
|
.set_attrs = phonet_set_attrs,
|
||||||
.get_attrs = phonet_get_attrs,
|
.get_attrs = phonet_get_attrs,
|
||||||
.cleanup_attrs = phonet_cleanup_attrs,
|
.cleanup_attrs = phonet_cleanup_attrs,
|
||||||
|
|
|
@ -17,6 +17,14 @@
|
||||||
#include <libconfig.h>
|
#include <libconfig.h>
|
||||||
#endif
|
#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,
|
static int serial_set_attrs(struct usbg_function *f,
|
||||||
const usbg_function_attrs *f_attrs)
|
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 */
|
/* We don' import port_num as it is read only */
|
||||||
#define SERIAL_FUNCTION_OPTS \
|
#define SERIAL_FUNCTION_OPTS \
|
||||||
|
.alloc_inst = serial_alloc_inst, \
|
||||||
|
.free_inst = serial_free_inst, \
|
||||||
.set_attrs = serial_set_attrs, \
|
.set_attrs = serial_set_attrs, \
|
||||||
.get_attrs = serial_get_attrs, \
|
.get_attrs = serial_get_attrs, \
|
||||||
SERIAL_LIBCONFIG_DEP_OPS, \
|
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)
|
static inline void usbg_free_function(usbg_function *f)
|
||||||
{
|
{
|
||||||
free(f->path);
|
if (f->ops->free_inst)
|
||||||
free(f->name);
|
f->ops->free_inst(f->ops, f);
|
||||||
free(f->label);
|
|
||||||
free(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usbg_free_config(usbg_config *c)
|
static void usbg_free_config(usbg_config *c)
|
||||||
|
@ -426,46 +424,16 @@ out:
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static usbg_function *usbg_allocate_function(const char *path,
|
static usbg_function *
|
||||||
usbg_function_type type, const char *instance, usbg_gadget *parent)
|
usbg_allocate_function(const char *path, usbg_function_type type,
|
||||||
|
const char *instance, usbg_gadget *parent)
|
||||||
{
|
{
|
||||||
usbg_function *f;
|
usbg_function *f;
|
||||||
const char *type_name;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
f = malloc(sizeof(*f));
|
ret = function_types[type]->alloc_inst(function_types[type], type,
|
||||||
if (!f)
|
instance, path, parent, &f);
|
||||||
goto out;
|
return ret == 0 ? f : NULL;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static usbg_binding *usbg_allocate_binding(const char *path, const char *name,
|
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;
|
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,
|
int usbg_get_ether_addr(const char *path, const char *name,
|
||||||
const char *attr, void *val)
|
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);
|
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