Add structure to store informations about available udcs instead of using their names as a string. Signed-off-by: Krzysztof Opasiak <k.opasiak@xxxxxxxxxxx> --- include/usbg/usbg.h | 14 ++++++++ src/usbg.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h index 3f5d561..c0e19d0 100644 --- a/include/usbg/usbg.h +++ b/include/usbg/usbg.h @@ -61,6 +61,7 @@ struct usbg_gadget; struct usbg_config; struct usbg_function; struct usbg_binding; +struct usbg_udc; /** * @brief State of the gadget devices in the system @@ -88,6 +89,11 @@ typedef struct usbg_function usbg_function; typedef struct usbg_binding usbg_binding; /** + * @brief USB device controler + */ +typedef struct usbg_udc usbg_udc; + +/** * @typedef usbg_gadget_attrs * @brief USB gadget device attributes */ @@ -312,6 +318,14 @@ extern usbg_function *usbg_get_function(usbg_gadget *g, */ 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 */ /** diff --git a/src/usbg.c b/src/usbg.c index 5f910f0..5f44cbd 100644 --- a/src/usbg.c +++ b/src/usbg.c @@ -42,6 +42,7 @@ struct usbg_state char *path; TAILQ_HEAD(ghead, usbg_gadget) gadgets; + TAILQ_HEAD(uhead, usbg_udc) udcs; config_t *last_failed_import; }; @@ -93,6 +94,15 @@ struct usbg_binding 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 @@ -582,15 +592,30 @@ static void usbg_free_gadget(usbg_gadget *g) 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); @@ -724,6 +749,26 @@ static usbg_binding *usbg_allocate_binding(const char *path, const char *name, 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; @@ -1246,6 +1291,36 @@ static int usbg_parse_gadgets(const char *path, usbg_state *s) 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; @@ -1254,11 +1329,19 @@ static int usbg_init_state(char *path, usbg_state *s) 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) { + ERRORNO("Unable to parse udcs"); + goto out; + } ret = usbg_parse_gadgets(path, s); if (ret != USBG_SUCCESS) ERRORNO("unable to parse %s\n", path); +out: return ret; } @@ -1373,6 +1456,17 @@ usbg_config *usbg_get_config(usbg_gadget *g, int id, const char *label) 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; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html