Naming convention of Config FS should not be exposed
to user of library. All API functions should use
configuration ID (configuration number) as unique
identificator and configuration label as human
readable description.

Signed-off-by: Krzysztof Opasiak <k.opas...@samsung.com>
---
 examples/gadget-acm-ecm.c |    4 +-
 examples/show-gadgets.c   |    9 +-
 include/usbg/usbg.h       |   35 +++++---
 src/usbg.c                |  200 +++++++++++++++++++++++++++++++--------------
 4 files changed, 168 insertions(+), 80 deletions(-)

diff --git a/examples/gadget-acm-ecm.c b/examples/gadget-acm-ecm.c
index 8eb4aeb..7a8b71b 100644
--- a/examples/gadget-acm-ecm.c
+++ b/examples/gadget-acm-ecm.c
@@ -97,8 +97,8 @@ int main(void)
                goto out2;
        }
 
-       usbg_ret = usbg_create_config(g, "c.1", NULL /* use defaults */, 
&c_strs,
-                       &c);
+       usbg_ret = usbg_create_config(g, 1, "The only one",
+                       NULL /* use defaults */, &c_strs, &c);
        if (usbg_ret != USBG_SUCCESS) {
                fprintf(stderr, "Error creating config\n");
                fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret),
diff --git a/examples/show-gadgets.c b/examples/show-gadgets.c
index 971beb4..1ae3860 100644
--- a/examples/show-gadgets.c
+++ b/examples/show-gadgets.c
@@ -57,7 +57,7 @@ void show_gadget(usbg_gadget *g)
        fprintf(stdout, "  idVendor\t\t0x%04x\n", g_attrs.idVendor);
        fprintf(stdout, "  idProduct\t\t0x%04x\n", g_attrs.idProduct);
 
-       usbg_get_gadget_strs(g, LANG_US_ENG, &g_strs);
+       usbg_ret = usbg_get_gadget_strs(g, LANG_US_ENG, &g_strs);
        if (usbg_ret != USBG_SUCCESS) {
                fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret),
                                usbg_strerror(usbg_ret));
@@ -121,10 +121,11 @@ void show_config(usbg_config *c)
        usbg_function_type type;
        usbg_config_attrs c_attrs;
        usbg_config_strs c_strs;
-       int usbg_ret;
+       int usbg_ret, id;
 
-       usbg_get_config_name(c, buf, USBG_MAX_STR_LENGTH);
-       fprintf(stdout, "  Configuration '%s'\n", buf);
+       usbg_get_config_label(c, buf, USBG_MAX_STR_LENGTH);
+       id = usbg_get_config_id(c);
+       fprintf(stdout, "  Configuration: '%s' ID: %d\n", buf, id);
 
        usbg_ret = usbg_get_config_attrs(c, &c_attrs);
        if (usbg_ret != USBG_SUCCESS) {
diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h
index fadbe07..1407f10 100644
--- a/include/usbg/usbg.h
+++ b/include/usbg/usbg.h
@@ -37,6 +37,7 @@
 
 #define DEFAULT_UDC            NULL
 #define LANG_US_ENG            0x0409
+#define DEFAULT_CONFIG_LABEL "config"
 
 #define USBG_MAX_STR_LENGTH 256
 #define USBG_MAX_PATH_LENGTH PATH_MAX
@@ -266,10 +267,14 @@ extern usbg_function *usbg_get_function(usbg_gadget *g,
 /**
  * @brief Get a configuration by name
  * @param g Pointer to gadget
- * @param name Name of the configuration
+ * @param id Identify of configuration
+ * @param label Configuration label. If not NULL this function will return
+ * valid value only if configuration with given id exist and has this label.
+ * If NULL this function will return config with given id (if such exist)
+ * and ignore this param.
  * @return Pointer to config or NULL if a matching config isn't found
  */
-extern usbg_config *usbg_get_config(usbg_gadget *g, const char *name);
+extern usbg_config *usbg_get_config(usbg_gadget *g, int id, const char *label);
 
 /* USB gadget allocation and configuration */
 
@@ -491,31 +496,39 @@ extern const char 
*usbg_get_function_type_str(usbg_function_type type);
 /**
  * @brief Create a new USB gadget configuration
  * @param g Pointer to gadget
- * @param name Name of configuration
+ * @param id Identify of configuration
+ * @param label configuration label, if NULL, default is used
  * @param c_attrs Configuration attributes to be set
  * @param c_strs Configuration strings to be set
  * @param c Pointer to be filled with pointer to configuration
  * @note Given strings are assumed to be in US English
  * @return 0 on success usbg_error if error occurred
  */
-extern int usbg_create_config(usbg_gadget *g, char *name,
+extern int usbg_create_config(usbg_gadget *g, int id, const char *label,
                usbg_config_attrs *c_attrs, usbg_config_strs *c_strs, 
usbg_config **c);
 
 /**
- * @brief Get config name length
- * @param c Config which name length should be returned
- * @return Length of name string or usbg_error if error occurred.
+ * @brief Get config label length
+ * @param c Config which label length should be returned
+ * @return Length of label or usbg_error if error occurred.
  */
-extern size_t usbg_get_config_name_len(usbg_config *c);
+extern size_t usbg_get_config_label_len(usbg_config *c);
 
 /**
- * @brieg Get config name
+ * @brieg Get config label
  * @param c Pointer to config
- * @param buf Buffer where name should be copied
+ * @param buf Buffer where label should be copied
  * @param len Length of given buffer
  * @return 0 on success or usbg_error if error occurred.
  */
-extern int usbg_get_config_name(usbg_config *c, char *buf, size_t len);
+extern int usbg_get_config_label(usbg_config *c, char *buf, size_t len);
+
+/**
+ * @brieg Get config id
+ * @param c Pointer to config
+ * @return Configuration id or usbg_error if error occurred.
+ */
+extern int usbg_get_config_id(usbg_config *c);
 
 /**
  * @brief Set the USB configuration attributes
diff --git a/src/usbg.c b/src/usbg.c
index 8f8049f..d73943c 100644
--- a/src/usbg.c
+++ b/src/usbg.c
@@ -25,6 +25,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <ctype.h>
 
 #define STRINGS_DIR "strings"
 #define CONFIGS_DIR "configs"
@@ -62,6 +63,8 @@ struct usbg_config
 
        char *name;
        char *path;
+       char *label;
+       int id;
 };
 
 struct usbg_function
@@ -324,6 +327,39 @@ out:
        return ret;
 }
 
+static int usbg_split_config_label_id(const char *full_name,
+               char **label)
+{
+       int ret = USBG_ERROR_INVALID_PARAM;
+       char *dot, *endptr, *id_string;
+
+       dot = strrchr(full_name, '.');
+       id_string = dot + 1;
+       if (!dot || dot == full_name || *id_string == '\0'
+                       || isspace(*id_string))
+               goto out;
+
+       *label = strndup(full_name, dot - full_name);
+       if (!*label)
+               goto out;
+
+       errno = 0; /* clear errno */
+       ret = strtol(id_string, &endptr, 10);
+       if (errno) {
+               /* error occurred */
+               ret = usbg_translate_error(errno);
+               free(*label);
+               *label = NULL;
+               goto out;
+       }
+
+       if (*endptr != '\0' || ret < 0 || ret > 255)
+               ret = USBG_ERROR_INVALID_PARAM;
+
+out:
+       return ret;
+}
+
 static int bindings_select(const struct dirent *dent)
 {
        if (dent->d_type == DT_LNK)
@@ -483,6 +519,7 @@ static void usbg_free_config(usbg_config *c)
        }
        free(c->path);
        free(c->name);
+       free(c->label);
        free(c);
 }
 
@@ -542,26 +579,39 @@ static usbg_gadget *usbg_allocate_gadget(char *path, char 
*name,
        return g;
 }
 
-static usbg_config *usbg_allocate_config(char *path, char *name,
-               usbg_gadget *parent)
+static usbg_config *usbg_allocate_config(const char *path, const char *label,
+               int id, usbg_gadget *parent)
 {
        usbg_config *c;
+       int ret;
 
        c = malloc(sizeof(*c));
-       if (c) {
-               TAILQ_INIT(&c->bindings);
-               c->name = strdup(name);
-               c->path = strdup(path);
-               c->parent = parent;
-
-               if (!(c->name) || !(c->path)) {
-                       free(c->name);
-                       free(c->path);
-                       free(c);
-                       c = NULL;
-               }
+       if (!c)
+               goto out;
+
+       TAILQ_INIT(&c->bindings);
+
+       ret = asprintf(&(c->name), "%s.%d", label, id);
+       if (ret < 0) {
+               free(c);
+               c = NULL;
+               goto out;
+       }
+
+       c->path = strdup(path);
+       c->label = strdup(label);
+       c->parent = parent;
+       c->id = id;
+
+       if (!(c->path) || !(c->label)) {
+               free(c->name);
+               free(c->path);
+               free(c->label);
+               free(c);
+               c = NULL;
        }
 
+out:
        return c;
 }
 
@@ -875,9 +925,36 @@ out:
        return ret;
 }
 
-static int usbg_parse_configs(char *path, usbg_gadget *g)
+static int usbg_parse_config(const char *path, const char *name,
+               usbg_gadget *g)
 {
+       int ret;
+       char *label = NULL;
        usbg_config *c;
+
+       ret = usbg_split_config_label_id(name, &label);
+       if (ret <= 0)
+               goto out;
+
+       c = usbg_allocate_config(path, label, ret, g);
+       if (!c) {
+               ret = USBG_ERROR_NO_MEM;
+               goto out;
+       }
+
+       ret = usbg_parse_config_bindings(c);
+       if (ret == USBG_SUCCESS)
+               TAILQ_INSERT_TAIL(&g->configs, c, cnode);
+       else
+               usbg_free_config(c);
+
+out:
+       free(label);
+       return ret;
+}
+
+static int usbg_parse_configs(char *path, usbg_gadget *g)
+{
        int i, n;
        int ret = USBG_SUCCESS;
        struct dirent **dent;
@@ -891,27 +968,19 @@ static int usbg_parse_configs(char *path, usbg_gadget *g)
        }
 
        n = scandir(cpath, &dent, file_select, alphasort);
-       if (n >= 0) {
-               for (i = 0; i < n; i++) {
-                       if (ret == USBG_SUCCESS) {
-                               c = usbg_allocate_config(cpath, 
dent[i]->d_name, g);
-                               if (c) {
-                                       ret = usbg_parse_config_bindings(c);
-                                       if (ret == USBG_SUCCESS)
-                                               TAILQ_INSERT_TAIL(&g->configs, 
c, cnode);
-                                       else
-                                               usbg_free_config(c);
-                               } else {
-                                       ret = USBG_ERROR_NO_MEM;
-                               }
-                       }
-                       free(dent[i]);
-               }
-               free(dent);
-       } else {
+       if (n < 0) {
                ret = usbg_translate_error(errno);
+               goto out;
        }
 
+       for (i = 0; i < n; i++) {
+               ret = ret == USBG_SUCCESS ?
+                               usbg_parse_config(cpath, dent[i]->d_name, g)
+                               : ret;
+               free(dent[i]);
+       }
+       free(dent);
+
 out:
        return ret;
 }
@@ -1161,15 +1230,15 @@ usbg_function *usbg_get_function(usbg_gadget *g,
        return f;
 }
 
-usbg_config *usbg_get_config(usbg_gadget *g, const char *name)
+usbg_config *usbg_get_config(usbg_gadget *g, int id, const char *label)
 {
-       usbg_config *c;
+       usbg_config *c = NULL;
 
        TAILQ_FOREACH(c, &g->configs, cnode)
-               if (!strcmp(c->name, name))
-                       return c;
+               if (c->id == id && (!label || !strcmp(c->label, label)))
+                       break;
 
-       return NULL;
+       return c;
 }
 
 usbg_binding *usbg_get_binding(usbg_config *c, const char *name)
@@ -1610,7 +1679,7 @@ out:
        return ret;
 }
 
-int usbg_create_config(usbg_gadget *g, char *name,
+int usbg_create_config(usbg_gadget *g, int id, const char *label,
                usbg_config_attrs *c_attrs, usbg_config_strs *c_strs, 
usbg_config **c)
 {
        char cpath[USBG_MAX_PATH_LENGTH];
@@ -1618,15 +1687,15 @@ int usbg_create_config(usbg_gadget *g, char *name,
        int ret = USBG_ERROR_INVALID_PARAM;
        int n, free_space;
 
-       if (!g || !c)
+       if (!g || !c || id <= 0 || id > 255)
                goto out;
 
-       /**
-        * @todo Check for legal configuration name
-        */
-       conf = usbg_get_config(g, name);
+       if (!label)
+               label = DEFAULT_CONFIG_LABEL;
+
+       conf = usbg_get_config(g, id, NULL);
        if (conf) {
-               ERROR("duplicate configuration name\n");
+               ERROR("duplicate configuration id\n");
                ret = USBG_ERROR_EXIST;
                goto out;
        }
@@ -1638,7 +1707,7 @@ int usbg_create_config(usbg_gadget *g, char *name,
                goto out;
        }
 
-       *c = usbg_allocate_config(cpath, name, g);
+       *c = usbg_allocate_config(cpath, label, id, g);
        conf = *c;
        if (!conf) {
                ERRORNO("allocating configuration\n");
@@ -1648,22 +1717,22 @@ int usbg_create_config(usbg_gadget *g, char *name,
 
        free_space = sizeof(cpath) - n;
        /* Append string at the end of previous one */
-       n = snprintf(&(cpath[n]), free_space, "/%s", name);
+       n = snprintf(&(cpath[n]), free_space, "/%s", (*c)->name);
        if (n < free_space) {
-               ret = mkdir(cpath, S_IRWXU | S_IRWXG | S_IRWXO);
-               if (!ret) {
-                       ret = USBG_SUCCESS;
-                       if (c_attrs)
-                               ret = usbg_set_config_attrs(conf, c_attrs);
+               ret = USBG_ERROR_PATH_TOO_LONG;
+       }
 
-                       if (ret == USBG_SUCCESS && c_strs)
-                               ret = usbg_set_config_string(conf, LANG_US_ENG,
-                                               c_strs->configuration);
-               } else {
-                       ret = usbg_translate_error(errno);
-               }
+       ret = mkdir(cpath, S_IRWXU | S_IRWXG | S_IRWXO);
+       if (!ret) {
+               ret = USBG_SUCCESS;
+               if (c_attrs)
+                       ret = usbg_set_config_attrs(conf, c_attrs);
+
+               if (ret == USBG_SUCCESS && c_strs)
+                       ret = usbg_set_config_string(conf, LANG_US_ENG,
+                                       c_strs->configuration);
        } else {
-               ret = USBG_ERROR_PATH_TOO_LONG;
+               ret = usbg_translate_error(errno);
        }
 
        if (ret == USBG_SUCCESS)
@@ -1676,22 +1745,27 @@ out:
        return ret;
 }
 
-size_t usbg_get_config_name_len(usbg_config *c)
+size_t usbg_get_config_label_len(usbg_config *c)
 {
-       return c ? strlen(c->name) : USBG_ERROR_INVALID_PARAM;
+       return c ? strlen(c->label) : USBG_ERROR_INVALID_PARAM;
 }
 
-int usbg_get_config_name(usbg_config *c, char *buf, size_t len)
+int usbg_get_config_label(usbg_config *c, char *buf, size_t len)
 {
        int ret = USBG_SUCCESS;
        if (c && buf)
-               strncpy(buf, c->name, len);
+               strncpy(buf, c->label, len);
        else
                ret = USBG_ERROR_INVALID_PARAM;
 
        return ret;
 }
 
+int usbg_get_config_id(usbg_config *c)
+{
+       return c ? c->id : USBG_ERROR_INVALID_PARAM;
+}
+
 size_t usbg_get_function_instance_len(usbg_function *f)
 {
        return f ? strlen(f->instance) : USBG_ERROR_INVALID_PARAM;
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to