Functions related to gadget creation should return error codes instead of pointer. Signed-off-by: Krzysztof Opasiak <k.opasiak@xxxxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html