Functions related to gadget creation should return error codes
instead of pointer.

Signed-off-by: Krzysztof Opasiak <k.opas...@samsung.com>
---
 examples/gadget-acm-ecm.c |    4 +-
 include/usbg/usbg.h       |   21 ++--
 src/usbg.c                |  258 +++++++++++++++++++++++++++++----------------
 3 files changed, 185 insertions(+), 98 deletions(-)

diff --git a/examples/gadget-acm-ecm.c b/examples/gadget-acm-ecm.c
index 5ab42cf..b1131b4 100644
--- a/examples/gadget-acm-ecm.c
+++ b/examples/gadget-acm-ecm.c
@@ -63,8 +63,8 @@ int main(void)
                goto out1;
        }
 
-       g = usbg_create_gadget(s, "g1", &g_attrs, &g_strs);
-       if (!g) {
+       usbg_ret = usbg_create_gadget(s, "g1", &g_attrs, &g_strs, &g);
+       if (usbg_ret != USBG_SUCCESS) {
                fprintf(stderr, "Error on create gadget\n");
                goto out2;
        }
diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h
index 0d76010..f6f7a2e 100644
--- a/include/usbg/usbg.h
+++ b/include/usbg/usbg.h
@@ -186,6 +186,7 @@ typedef enum  {
        USBG_ERROR_INVALID_PARAM = -3,
        USBG_ERROR_NOT_FOUND = -4,
        USBG_ERROR_IO = -5,
+       USBG_ERROR_EXIST = -6,
        USBG_ERROR_OTHER_ERROR = -99
 } usbg_error;
 
@@ -255,10 +256,11 @@ extern usbg_config *usbg_get_config(usbg_gadget *g, const 
char *name);
  * @param name Name of the gadget
  * @param idVendor Gadget vendor ID
  * @param idProduct Gadget product ID
- * @return Pointer to gadget or NULL if the gadget cannot be created
+ * @param g Pointer to be filled with pointer to gadget
+ * @return 0 on success usbg_error if error occurred
  */
-extern usbg_gadget *usbg_create_gadget_vid_pid(usbg_state *s, char *name,
-               uint16_t idVendor, uint16_t idProduct);
+extern int usbg_create_gadget_vid_pid(usbg_state *s, char *name,
+               uint16_t idVendor, uint16_t idProduct, usbg_gadget **g);
 
 /**
  * @brief Create a new USB gadget device and set given attributes
@@ -267,18 +269,20 @@ extern usbg_gadget *usbg_create_gadget_vid_pid(usbg_state 
*s, char *name,
  * @param name Name of the gadget
  * @param g_attrs Gadget attributes to be set. If NULL setting is omitted.
  * @param g_strs Gadget strings to be set. If NULL setting is omitted.
+ * @param g Pointer to be filled with pointer to gadget
  * @note Given strings are assumed to be in US English
- * @return Pointer to gadget or NULL if the gadget cannot be created
+ * @return 0 on success usbg_error if error occurred
  */
-extern usbg_gadget *usbg_create_gadget(usbg_state *s, char *name,
-               usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs);
+extern int usbg_create_gadget(usbg_state *s, char *name,
+               usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs, 
usbg_gadget **g);
 
 /**
  * @brief Set the USB gadget attributes
  * @param g Pointer to gadget
  * @param g_attrs Gadget attributes
+ * @return 0 on success usbg_error if error occurred
  */
-extern void usbg_set_gadget_attrs(usbg_gadget *g,
+extern int usbg_set_gadget_attrs(usbg_gadget *g,
                usbg_gadget_attrs *g_attrs);
 
 /**
@@ -383,8 +387,9 @@ extern usbg_gadget_strs *usbg_get_gadget_strs(usbg_gadget 
*g, int lang,
  * @param g Pointer to gadget
  * @param lang USB language ID
  * @param g_sttrs Gadget attributes
+ * @return 0 on success usbg_error if error occurred
  */
-extern void usbg_set_gadget_strs(usbg_gadget *g, int lang,
+extern int usbg_set_gadget_strs(usbg_gadget *g, int lang,
                usbg_gadget_strs *g_strs);
 
 /**
diff --git a/src/usbg.c b/src/usbg.c
index b6aa80d..ed8070d 100644
--- a/src/usbg.c
+++ b/src/usbg.c
@@ -142,6 +142,7 @@ static int usbg_translate_error(int error)
                ret = USBG_ERROR_NO_MEM;
                break;
        case EACCES:
+       case EROFS:
                ret = USBG_ERROR_NO_ACCESS;
                break;
        case ENOENT:
@@ -155,6 +156,9 @@ static int usbg_translate_error(int error)
        case EIO:
                ret = USBG_ERROR_IO;
                break;
+       case EEXIST:
+               ret = USBG_ERROR_EXIST;
+               break;
        default:
                ret = USBG_ERROR_OTHER_ERROR;
        }
@@ -261,46 +265,49 @@ static int usbg_read_string(char *path, char *name, char 
*file, char *buf)
        return ret;
 }
 
-static void usbg_write_buf(char *path, char *name, char *file, char *buf)
+static int usbg_write_buf(char *path, char *name, char *file, char *buf)
 {
        char p[USBG_MAX_STR_LENGTH];
        FILE *fp;
-       int err;
+       int ret = USBG_SUCCESS;
 
        sprintf(p, "%s/%s/%s", path, name, file);
 
        fp = fopen(p, "w");
-       if (!fp) {
-               ERRORNO("%s\n", p);
-               return;
-       }
+       if (fp) {
+               fputs(buf, fp);
+               fflush(fp);
 
-       fputs(buf, fp);
-       fflush(fp);
-       err = ferror(fp);
-       fclose(fp);
-       
-       if (err){
-               ERROR("write error");
-               return;
+               ret = ferror(fp);
+               if (ret)
+                       ret = usbg_translate_error(errno);
+
+               fclose(fp);
+       } else {
+               /* Set error correctly */
+               ret = usbg_translate_error(errno);
        }
+
+       return ret;
 }
 
-static void usbg_write_int(char *path, char *name, char *file, int value, char 
*str)
+static int usbg_write_int(char *path, char *name, char *file, int value,
+               char *str)
 {
        char buf[USBG_MAX_STR_LENGTH];
 
        sprintf(buf, str, value);
-       usbg_write_buf(path, name, file, buf);
+       return usbg_write_buf(path, name, file, buf);
 }
 
 #define usbg_write_dec(p, n, f, v)     usbg_write_int(p, n, f, v, "%d\n")
 #define usbg_write_hex16(p, n, f, v)   usbg_write_int(p, n, f, v, "0x%04x\n")
 #define usbg_write_hex8(p, n, f, v)    usbg_write_int(p, n, f, v, "0x%02x\n")
 
-static inline void usbg_write_string(char *path, char *name, char *file, char 
*buf)
+static inline int usbg_write_string(char *path, char *name, char *file,
+               char *buf)
 {
-       usbg_write_buf(path, name, file, buf);
+       return usbg_write_buf(path, name, file, buf);
 }
 
 static inline void usbg_free_binding(usbg_binding *b)
@@ -807,96 +814,112 @@ usbg_binding *usbg_get_link_binding(usbg_config *c, 
usbg_function *f)
        return NULL;
 }
 
-static usbg_gadget *usbg_create_empty_gadget(usbg_state *s, char *name)
+static int usbg_create_empty_gadget(usbg_state *s, char *name, usbg_gadget **g)
 {
        char gpath[USBG_MAX_PATH_LENGTH];
-       usbg_gadget *g;
-       int ret;
+       int ret = USBG_SUCCESS;
 
        sprintf(gpath, "%s/%s", s->path, name);
 
-       g = malloc(sizeof(usbg_gadget));
-       if (!g) {
-               ERRORNO("allocating gadget\n");
-               return NULL;
-       }
-
-       TAILQ_INIT(&g->configs);
-       TAILQ_INIT(&g->functions);
-       strcpy(g->name, name);
-       strcpy(g->path, s->path);
-       g->parent = s;
+       *g = malloc(sizeof(usbg_gadget));
+       if (*g) {
+               usbg_gadget *gad = *g; /* alias only */
+
+               TAILQ_INIT(&gad->configs);
+               TAILQ_INIT(&gad->functions);
+               strcpy(gad->name, name);
+               strcpy(gad->path, s->path);
+               gad->parent = s;
+
+               ret = mkdir(gpath, S_IRWXU|S_IRWXG|S_IRWXO);
+               if (ret == 0) {
+                       /* Should be empty but read the default */
+                       ret = usbg_read_string(gad->path, gad->name, "UDC",
+                                gad->udc);
+                       if (ret != USBG_SUCCESS)
+                               rmdir(gpath);
+               } else {
+                       ret = usbg_translate_error(errno);
+               }
 
-       ret = mkdir(gpath, S_IRWXU|S_IRWXG|S_IRWXO);
-       if (ret < 0) {
-               ERRORNO("%s\n", gpath);
-               free(g);
-               return NULL;
+               if (ret != USBG_SUCCESS) {
+                       free(gad);
+                       *g = NULL;
+               }
+       } else {
+               ret = USBG_ERROR_NO_MEM;
        }
 
-       /* Should be empty but read the default */
-       usbg_read_string(g->path, g->name, "UDC", g->udc);
-
-       return g;
+       return ret;
 }
 
-
-
-usbg_gadget *usbg_create_gadget_vid_pid(usbg_state *s, char *name,
-               uint16_t idVendor, uint16_t idProduct)
+int usbg_create_gadget_vid_pid(usbg_state *s, char *name,
+               uint16_t idVendor, uint16_t idProduct, usbg_gadget **g)
 {
-       usbg_gadget *g;
+       int ret;
+       usbg_gadget *gad;
 
-       if (!s)
-               return NULL;
+       if (!s || !g)
+               return USBG_ERROR_INVALID_PARAM;
 
-       g = usbg_get_gadget(s, name);
-       if (g) {
+       gad = usbg_get_gadget(s, name);
+       if (gad) {
                ERROR("duplicate gadget name\n");
-               return NULL;
+               return USBG_ERROR_EXIST;
        }
 
-       g = usbg_create_empty_gadget(s, name);
+       ret = usbg_create_empty_gadget(s, name, g);
+       gad = *g;
 
        /* Check if gadget creation was successful and set attributes */
-       if (g) {
-               usbg_write_hex16(s->path, name, "idVendor", idVendor);
-               usbg_write_hex16(s->path, name, "idProduct", idProduct);
-
-               INSERT_TAILQ_STRING_ORDER(&s->gadgets, ghead, name, g, gnode);
+       if (ret == USBG_SUCCESS) {
+               ret = usbg_write_hex16(s->path, name, "idVendor", idVendor);
+               if (ret == USBG_SUCCESS) {
+                       ret = usbg_write_hex16(s->path, name, "idProduct", 
idProduct);
+                       if (ret == USBG_SUCCESS)
+                               INSERT_TAILQ_STRING_ORDER(&s->gadgets, ghead, 
name,
+                                               gad, gnode);
+                       else
+                               usbg_free_gadget(gad);
+               }
        }
 
-       return g;
+       return ret;
 }
 
-usbg_gadget *usbg_create_gadget(usbg_state *s, char *name,
-               usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs)
+int usbg_create_gadget(usbg_state *s, char *name,
+               usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs, 
usbg_gadget **g)
 {
-       usbg_gadget *g;
+       usbg_gadget *gad;
+       int ret;
 
-       if (!s)
-               return NULL;
+       if (!s || !g)
+                       return USBG_ERROR_INVALID_PARAM;
 
-       g = usbg_get_gadget(s, name);
-       if (g) {
+       gad = usbg_get_gadget(s, name);
+       if (gad) {
                ERROR("duplicate gadget name\n");
-               return NULL;
+               return USBG_ERROR_EXIST;
        }
 
-       g = usbg_create_empty_gadget(s, name);
+       ret = usbg_create_empty_gadget(s, name, g);
+       gad = *g;
 
        /* Check if gadget creation was successful and set attrs and strings */
-       if (g) {
+       if (ret == USBG_SUCCESS) {
                if (g_attrs)
-                       usbg_set_gadget_attrs(g, g_attrs);
+                       ret = usbg_set_gadget_attrs(gad, g_attrs);
 
                if (g_strs)
-                       usbg_set_gadget_strs(g, LANG_US_ENG, g_strs);
+                       ret = usbg_set_gadget_strs(gad, LANG_US_ENG, g_strs);
 
-               INSERT_TAILQ_STRING_ORDER(&s->gadgets, ghead, name, g, gnode);
+               if (ret == USBG_SUCCESS)
+                       INSERT_TAILQ_STRING_ORDER(&s->gadgets, ghead, name,
+                               gad, gnode);
+               else
+                       usbg_free_gadget(gad);
        }
-
-       return g;
+       return ret;
 }
 
 usbg_gadget_attrs *usbg_get_gadget_attrs(usbg_gadget *g,
@@ -942,19 +965,51 @@ int usbg_get_gadget_udc(usbg_gadget *g, char *buf, size_t 
len)
        return ret;
 }
 
-void usbg_set_gadget_attrs(usbg_gadget *g, usbg_gadget_attrs *g_attrs)
+int usbg_set_gadget_attrs(usbg_gadget *g, usbg_gadget_attrs *g_attrs)
 {
+       int ret;
        if (!g || !g_attrs)
-               return;
+               return USBG_ERROR_INVALID_PARAM;
+
+       ret = usbg_write_hex16(g->path, g->name, "bcdUSB", g_attrs->bcdUSB);
+       if (ret != USBG_SUCCESS)
+               goto out;
+
+       ret = usbg_write_hex8(g->path, g->name, "bDeviceClass",
+               g_attrs->bDeviceClass);
+       if (ret != USBG_SUCCESS)
+                       goto out;
+
+       ret = usbg_write_hex8(g->path, g->name, "bDeviceSubClass",
+               g_attrs->bDeviceSubClass);
+       if (ret != USBG_SUCCESS)
+                       goto out;
+
+       ret = usbg_write_hex8(g->path, g->name, "bDeviceProtocol",
+               g_attrs->bDeviceProtocol);
+       if (ret != USBG_SUCCESS)
+                       goto out;
 
-       usbg_write_hex16(g->path, g->name, "bcdUSB", g_attrs->bcdUSB);
-       usbg_write_hex8(g->path, g->name, "bDeviceClass", 
g_attrs->bDeviceClass);
-       usbg_write_hex8(g->path, g->name, "bDeviceSubClass", 
g_attrs->bDeviceSubClass);
-       usbg_write_hex8(g->path, g->name, "bDeviceProtocol", 
g_attrs->bDeviceProtocol);
-       usbg_write_hex8(g->path, g->name, "bMaxPacketSize0", 
g_attrs->bMaxPacketSize0);
-       usbg_write_hex16(g->path, g->name, "idVendor", g_attrs->idVendor);
-       usbg_write_hex16(g->path, g->name, "idProduct", g_attrs->idProduct);
-       usbg_write_hex16(g->path, g->name, "bcdDevice", g_attrs->bcdDevice);
+       ret = usbg_write_hex8(g->path, g->name, "bMaxPacketSize0",
+               g_attrs->bMaxPacketSize0);
+       if (ret != USBG_SUCCESS)
+                       goto out;
+
+       ret = usbg_write_hex16(g->path, g->name, "idVendor",
+               g_attrs->idVendor);
+       if (ret != USBG_SUCCESS)
+                       goto out;
+
+       ret = usbg_write_hex16(g->path, g->name, "idProduct",
+                g_attrs->idProduct);
+       if (ret != USBG_SUCCESS)
+                       goto out;
+
+       ret = usbg_write_hex16(g->path, g->name, "bcdDevice",
+               g_attrs->bcdDevice);
+
+out:
+       return ret;
 }
 
 void usbg_set_gadget_vendor_id(usbg_gadget *g, uint16_t idVendor)
@@ -1008,18 +1063,45 @@ usbg_gadget_strs *usbg_get_gadget_strs(usbg_gadget *g, 
int lang,
        return g_strs;
 }
 
-void usbg_set_gadget_strs(usbg_gadget *g, int lang,
+static int usbg_check_dir(char *path)
+{
+       int ret = USBG_SUCCESS;
+       DIR *dir;
+
+       /* Assume that user will always have read access to this directory */
+       dir = opendir(path);
+       if (dir)
+               closedir(dir);
+       else if (errno != ENOENT || mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO) != 0)
+               ret = usbg_translate_error(errno);
+
+       return ret;
+}
+
+int usbg_set_gadget_strs(usbg_gadget *g, int lang,
                usbg_gadget_strs *g_strs)
 {
        char path[USBG_MAX_PATH_LENGTH];
+       DIR *dir;
+       int ret = USBG_SUCCESS;
 
        sprintf(path, "%s/%s/%s/0x%x", g->path, g->name, STRINGS_DIR, lang);
 
-       mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO);
+       ret = usbg_check_dir(path);
+       if (ret == USBG_SUCCESS) {
+               ret = usbg_write_string(path, "", "serialnumber", 
g_strs->str_ser);
+               if (ret != USBG_SUCCESS)
+                       goto out;
 
-       usbg_write_string(path, "", "serialnumber", g_strs->str_ser);
-       usbg_write_string(path, "", "manufacturer", g_strs->str_mnf);
-       usbg_write_string(path, "", "product", g_strs->str_prd);
+               ret = usbg_write_string(path, "", "manufacturer", 
g_strs->str_mnf);
+               if (ret != USBG_SUCCESS)
+                       goto out;
+
+               ret = usbg_write_string(path, "", "product", g_strs->str_prd);
+       }
+
+out:
+       return ret;
 }
 
 void usbg_set_gadget_serial_number(usbg_gadget *g, int lang, char *serno)
-- 
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