struct usbg_config;
struct usbg_function;
struct usbg_binding;
+struct usbg_udc;
/**
* @brief State of the gadget devices in the system
typedef struct usbg_binding usbg_binding;
/**
+ * @brief USB device controler
+ */
+typedef struct usbg_udc usbg_udc;
+
+/**
* @typedef usbg_gadget_attr
* @brief Gadget attributes which can be set using
* usbg_set_gadget_attr() function.
*/
extern usbg_config *usbg_get_config(usbg_gadget *g, int id, const char *label);
+/**
+ * @brief Get a udc by name
+ * @param s Pointer to state
+ * @param name Name of the udc
+ * @return Pointer to udc or NULL if a matching udc isn't found
+ */
+extern usbg_udc *usbg_get_udc(usbg_state *s, const char *name);
+
/* USB gadget/config/function/binding removal */
/**
char *path;
TAILQ_HEAD(ghead, usbg_gadget) gadgets;
+ TAILQ_HEAD(uhead, usbg_udc) udcs;
config_t *last_failed_import;
};
char *path;
};
+struct usbg_udc
+{
+ TAILQ_ENTRY(usbg_udc) unode;
+ usbg_state *parent;
+ usbg_gadget *gadget;
+
+ char *name;
+};
+
/**
* @var function_names
* @brief Name strings for supported USB function types
free(g);
}
+static void usbg_free_udc(usbg_udc *u)
+{
+ free(u->name);
+ free(u);
+}
+
static void usbg_free_state(usbg_state *s)
{
usbg_gadget *g;
+ usbg_udc *u;
+
while (!TAILQ_EMPTY(&s->gadgets)) {
g = TAILQ_FIRST(&s->gadgets);
TAILQ_REMOVE(&s->gadgets, g, gnode);
usbg_free_gadget(g);
}
+
+ while (!TAILQ_EMPTY(&s->udcs)) {
+ u = TAILQ_FIRST(&s->udcs);
+ TAILQ_REMOVE(&s->udcs, u, unode);
+ usbg_free_udc(u);
+ }
+
if (s->last_failed_import) {
config_destroy(s->last_failed_import);
free(s->last_failed_import);
return b;
}
+static usbg_udc *usbg_allocate_udc(usbg_state *parent, const char *name)
+{
+ usbg_udc *u;
+
+ u = malloc(sizeof(*u));
+ if (!u)
+ goto out;
+
+ u->gadget = NULL;
+ u->parent = parent;
+ u->name = strdup(name);
+ if (!u->name) {
+ free(u);
+ u = NULL;
+ }
+
+ out:
+ return u;
+}
+
static int ubsg_rm_file(const char *path, const char *name)
{
int ret = USBG_SUCCESS;
return ret;
}
+static int usbg_parse_udcs(usbg_state *s)
+{
+ usbg_udc *u;
+ int n, i;
+ int ret = USBG_SUCCESS;
+ struct dirent **dent;
+
+ n = scandir("/sys/class/udc", &dent, file_select, alphasort);
+ if (n < 0) {
+ ret = usbg_translate_error(errno);
+ goto out;
+ }
+
+ for (i = 0; i < n; ++i) {
+ if (ret == USBG_SUCCESS) {
+ u = usbg_allocate_udc(s, dent[i]->d_name);
+ if (u)
+ TAILQ_INSERT_TAIL(&s->udcs, u, unode);
+ else
+ ret = USBG_ERROR_NO_MEM;
+ }
+
+ free(dent[i]);
+ }
+ free(dent);
+
+out:
+ return ret;
+}
+
static int usbg_init_state(char *path, usbg_state *s)
{
int ret = USBG_SUCCESS;
s->path = path;
s->last_failed_import = NULL;
TAILQ_INIT(&s->gadgets);
+ TAILQ_INIT(&s->udcs);
+
+ ret = usbg_parse_udcs(s);
+ if (ret != USBG_SUCCESS) {
+ ERROR("Unable to parse udcs");
+ goto out;
+ }
ret = usbg_parse_gadgets(path, s);
if (ret != USBG_SUCCESS)
ERROR("unable to parse %s\n", path);
+out:
return ret;
}
return c;
}
+usbg_udc *usbg_get_udc(usbg_state *s, const char *name)
+{
+ usbg_udc *u;
+
+ TAILQ_FOREACH(u, &s->udcs, unode)
+ if (!strcmp(u->name, name))
+ return u;
+
+ return NULL;
+}
+
usbg_binding *usbg_get_binding(usbg_config *c, const char *name)
{
usbg_binding *b;