diff options
author | taeyoung <ty317.kim@samsung.com> | 2016-09-23 20:23:57 +0900 |
---|---|---|
committer | taeyoung <ty317.kim@samsung.com> | 2016-09-23 20:24:32 +0900 |
commit | 9ddeb24a02bff238a8c34688bd3e31e2a391c6f4 (patch) | |
tree | 6bce16ed577e3c1d432fa8aa154375fdc4753176 /src/usbg.c | |
parent | af80c789ed18bffe59ff815f0fddabbda56b9442 (diff) | |
download | libusbg-9ddeb24a02bff238a8c34688bd3e31e2a391c6f4.tar.gz libusbg-9ddeb24a02bff238a8c34688bd3e31e2a391c6f4.tar.bz2 libusbg-9ddeb24a02bff238a8c34688bd3e31e2a391c6f4.zip |
Revert "Imported Upstream version 0.0.1"
This reverts commit af80c789ed18bffe59ff815f0fddabbda56b9442.
Change-Id: I21d25ee142e12b9111664bd7ce3b2b190a56bb88
Diffstat (limited to 'src/usbg.c')
-rw-r--r-- | src/usbg.c | 1984 |
1 files changed, 329 insertions, 1655 deletions
@@ -16,7 +16,7 @@ #include <dirent.h> #include <errno.h> - +#include <usbg/usbg.h> #include <netinet/ether.h> #include <stdio.h> #include <stdlib.h> @@ -26,13 +26,68 @@ #include <sys/stat.h> #include <unistd.h> #include <ctype.h> -#include <stdbool.h> -#include "usbg/usbg_internal.h" + +#define STRINGS_DIR "strings" +#define CONFIGS_DIR "configs" +#define FUNCTIONS_DIR "functions" /** * @file usbg.c + * @todo Handle buffer overflows */ +struct usbg_state +{ + char *path; + + TAILQ_HEAD(ghead, usbg_gadget) gadgets; +}; + +struct usbg_gadget +{ + char *name; + char *path; + char udc[USBG_MAX_STR_LENGTH]; + + TAILQ_ENTRY(usbg_gadget) gnode; + TAILQ_HEAD(chead, usbg_config) configs; + TAILQ_HEAD(fhead, usbg_function) functions; + usbg_state *parent; +}; + +struct usbg_config +{ + TAILQ_ENTRY(usbg_config) cnode; + TAILQ_HEAD(bhead, usbg_binding) bindings; + usbg_gadget *parent; + + char *name; + char *path; + char *label; + int id; +}; + +struct usbg_function +{ + TAILQ_ENTRY(usbg_function) fnode; + usbg_gadget *parent; + + char *name; + char *path; + char *instance; + + usbg_function_type type; +}; + +struct usbg_binding +{ + TAILQ_ENTRY(usbg_binding) bnode; + usbg_config *parent; + usbg_function *target; + + char *name; + char *path; +}; /** * @var function_names @@ -49,38 +104,39 @@ const char *function_names[] = "eem", "rndis", "phonet", - "ffs", - "mass_storage", - "midi", - "Loopback", -}; - -ARRAY_SIZE_SENTINEL(function_names, USBG_FUNCTION_TYPE_MAX); - -const char *gadget_attr_names[] = -{ - "bcdUSB", - "bDeviceClass", - "bDeviceSubClass", - "bDeviceProtocol", - "bMaxPacketSize0", - "idVendor", - "idProduct", - "bcdDevice" -}; - -ARRAY_SIZE_SENTINEL(gadget_attr_names, USBG_GADGET_ATTR_MAX); - -const char *gadget_str_names[] = -{ - "product", - "manufacturer", - "serialnumber", }; -ARRAY_SIZE_SENTINEL(gadget_str_names, USBG_GADGET_STR_MAX); - -int usbg_translate_error(int error) +#define ERROR(msg, ...) do {\ + fprintf(stderr, "%s() "msg" \n", \ + __func__, ##__VA_ARGS__);\ + fflush(stderr);\ + } while (0) + +#define ERRORNO(msg, ...) do {\ + fprintf(stderr, "%s() %s: "msg" \n", \ + __func__, strerror(errno), ##__VA_ARGS__);\ + fflush(stderr);\ + } while (0) + +/* Insert in string order */ +#define INSERT_TAILQ_STRING_ORDER(HeadPtr, HeadType, NameField, ToInsert, NodeField) \ + do { \ + if (TAILQ_EMPTY((HeadPtr)) || \ + (strcmp((ToInsert)->NameField, TAILQ_FIRST((HeadPtr))->NameField) < 0)) \ + TAILQ_INSERT_HEAD((HeadPtr), (ToInsert), NodeField); \ + else if (strcmp((ToInsert)->NameField, TAILQ_LAST((HeadPtr), HeadType)->NameField) > 0) \ + TAILQ_INSERT_TAIL((HeadPtr), (ToInsert), NodeField); \ + else { \ + typeof(ToInsert) _cur; \ + TAILQ_FOREACH(_cur, (HeadPtr), NodeField) { \ + if (strcmp((ToInsert)->NameField, _cur->NameField) > 0) \ + continue; \ + TAILQ_INSERT_BEFORE(_cur, (ToInsert), NodeField); \ + } \ + } \ + } while (0) + +static int usbg_translate_error(int error) { int ret; @@ -90,14 +146,12 @@ int usbg_translate_error(int error) break; case EACCES: case EROFS: - case EPERM: ret = USBG_ERROR_NO_ACCESS; break; case ENOENT: case ENOTDIR: ret = USBG_ERROR_NOT_FOUND; break; - case ERANGE: case EINVAL: case USBG_ERROR_INVALID_PARAM: ret = USBG_ERROR_INVALID_PARAM; @@ -114,9 +168,6 @@ int usbg_translate_error(int error) case EBUSY: ret = USBG_ERROR_BUSY; break; - case ENOTEMPTY: - ret = USBG_ERROR_NOT_EMPTY; - break; default: ret = USBG_ERROR_OTHER_ERROR; } @@ -162,21 +213,6 @@ const char *usbg_error_name(usbg_error e) case USBG_ERROR_PATH_TOO_LONG: ret = "USBG_ERROR_PATH_TOO_LONG"; break; - case USBG_ERROR_INVALID_FORMAT: - ret = "USBG_ERROR_INVALID_FORMAT"; - break; - case USBG_ERROR_MISSING_TAG: - ret = "USBG_ERROR_MISSING_TAG"; - break; - case USBG_ERROR_INVALID_TYPE: - ret = "USBG_ERROR_INVALID_TYPE"; - break; - case USBG_ERROR_INVALID_VALUE: - ret = "USBG_ERROR_INVALID_VALUE"; - break; - case USBG_ERROR_NOT_EMPTY: - ret = "USBG_ERROR_NOT_EMPTY"; - break; case USBG_ERROR_OTHER_ERROR: ret = "USBG_ERROR_OTHER_ERROR"; break; @@ -223,21 +259,6 @@ const char *usbg_strerror(usbg_error e) case USBG_ERROR_PATH_TOO_LONG: ret = "Created path was too long to process it."; break; - case USBG_ERROR_INVALID_FORMAT: - ret = "Given file has incompatible format."; - break; - case USBG_ERROR_MISSING_TAG: - ret = "One of mandatory tags is missing."; - break; - case USBG_ERROR_INVALID_TYPE: - ret = "One of attributes has incompatible type."; - break; - case USBG_ERROR_INVALID_VALUE: - ret = "Incorrect value provided as attribute."; - break; - case USBG_ERROR_NOT_EMPTY: - ret = "Entity is not empty."; - break; case USBG_ERROR_OTHER_ERROR: ret = "Other error"; break; @@ -246,112 +267,30 @@ const char *usbg_strerror(usbg_error e) return ret; } -int usbg_lookup_function_attrs_type(int f_type) -{ - int ret; - - switch (f_type) { - case F_SERIAL: - case F_ACM: - case F_OBEX: - ret = USBG_F_ATTRS_SERIAL; - break; - case F_ECM: - case F_SUBSET: - case F_NCM: - case F_EEM: - case F_RNDIS: - ret = USBG_F_ATTRS_NET; - break; - case F_PHONET: - ret = USBG_F_ATTRS_PHONET; - break; - case F_FFS: - ret = USBG_F_ATTRS_FFS; - break; - case F_MASS_STORAGE: - ret = USBG_F_ATTRS_MS; - break; - case F_MIDI: - ret = USBG_F_ATTRS_MIDI; - break; - case F_LOOPBACK: - ret = USBG_F_ATTRS_LOOPBACK; - break; - default: - ret = USBG_ERROR_NOT_SUPPORTED; - } - - return ret; -} - -int usbg_lookup_function_type(const char *name) +static int usbg_lookup_function_type(char *name) { - int i = USBG_FUNCTION_TYPE_MIN; + int i = 0; + int max = sizeof(function_names)/sizeof(char *); if (!name) - return USBG_ERROR_INVALID_PARAM; + return -1; do { if (!strcmp(name, function_names[i])) - return i; - i++; - } while (i != USBG_FUNCTION_TYPE_MAX); - - return USBG_ERROR_NOT_FOUND; -} - -const char *usbg_get_function_type_str(usbg_function_type type) -{ - return type >= USBG_FUNCTION_TYPE_MIN && - type < USBG_FUNCTION_TYPE_MAX ? - function_names[type] : NULL; -} - -int usbg_lookup_gadget_attr(const char *name) -{ - int i = USBG_GADGET_ATTR_MIN; - - if (!name) - return USBG_ERROR_INVALID_PARAM; - - do { - if (!strcmp(name, gadget_attr_names[i])) - return i; - i++; - } while (i != USBG_GADGET_ATTR_MAX); - - return USBG_ERROR_NOT_FOUND; -} - -int usbg_lookup_gadget_str(const char *name) -{ - int i = USBG_GADGET_STR_MIN; - - if (!name) - return USBG_ERROR_INVALID_PARAM; - - do { - if (!strcmp(name, gadget_str_names[i])) - return i; + break; i++; - } while (i != USBG_GADGET_STR_MAX); + } while (i != max); - return USBG_ERROR_NOT_FOUND; -} + if (i == max) + i = -1; -const char *usbg_get_gadget_attr_str(usbg_gadget_attr attr) -{ - return attr >= USBG_GADGET_ATTR_MIN && - attr < USBG_GADGET_ATTR_MAX ? - gadget_attr_names[attr] : NULL; + return i; } -const char *usbg_get_gadget_str_name(usbg_gadget_str str) +const const char *usbg_get_function_type_str(usbg_function_type type) { - return str >= USBG_GADGET_STR_MIN && - str < USBG_GADGET_STR_MAX ? - gadget_str_names[str] : NULL; + return type > 0 && type < sizeof(function_names)/sizeof(char *) ? + function_names[type] : NULL; } static usbg_error usbg_split_function_instance_type(const char *full_name, @@ -429,46 +368,45 @@ static int bindings_select(const struct dirent *dent) return 0; } -static int usbg_read_buf(const char *path, const char *name, const char *file, - char *buf) +static int file_select(const struct dirent *dent) +{ + if ((strcmp(dent->d_name, ".") == 0) || (strcmp(dent->d_name, "..") == 0)) + return 0; + else + return 1; +} + +static int usbg_read_buf(char *path, char *name, char *file, char *buf) { char p[USBG_MAX_PATH_LENGTH]; FILE *fp; - char *ret_ptr; int nmb; int ret = USBG_SUCCESS; nmb = snprintf(p, sizeof(p), "%s/%s/%s", path, name, file); - if (nmb >= sizeof(p)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - fp = fopen(p, "r"); - if (!fp) { - /* Set error correctly */ - ret = usbg_translate_error(errno); - goto out; - } + if (nmb < sizeof(p)) { + fp = fopen(p, "r"); + if (fp) { + /* Successfully opened */ + if (!fgets(buf, USBG_MAX_STR_LENGTH, fp)) { + ERROR("read error"); + ret = USBG_ERROR_IO; + } - ret_ptr = fgets(buf, USBG_MAX_STR_LENGTH, fp); - if (!ret_ptr) { - /* File is empty */ - if (feof(fp)) - buf[0] = '\0'; - /* Error occurred */ - else - ret = USBG_ERROR_IO; + fclose(fp); + } else { + /* Set error correctly */ + ret = usbg_translate_error(errno); + } + } else { + ret = USBG_ERROR_PATH_TOO_LONG; } - fclose(fp); - -out: return ret; } -static int usbg_read_int(const char *path, const char *name, const char *file, - int base, int *dest) +static int usbg_read_int(char *path, char *name, char *file, int base, + int *dest) { char buf[USBG_MAX_STR_LENGTH]; char *pos; @@ -487,23 +425,7 @@ static int usbg_read_int(const char *path, const char *name, const char *file, #define usbg_read_dec(p, n, f, d) usbg_read_int(p, n, f, 10, d) #define usbg_read_hex(p, n, f, d) usbg_read_int(p, n, f, 16, d) -static int usbg_read_bool(const char *path, const char *name, const char *file, - bool *dest) -{ - int buf; - int ret; - - ret = usbg_read_dec(path, name, file, &buf); - if (ret != USBG_SUCCESS) - goto out; - - *dest = !!buf; -out: - return ret; -} - -static int usbg_read_string(const char *path, const char *name, - const char *file, char *buf) +static int usbg_read_string(char *path, char *name, char *file, char *buf) { char *p = NULL; int ret; @@ -521,30 +443,7 @@ static int usbg_read_string(const char *path, const char *name, return ret; } -static int usbg_read_string_alloc(const char *path, const char *name, - const char *file, const char **dest) -{ - char buf[USBG_MAX_FILE_SIZE]; - char *new_buf = NULL; - int ret = USBG_SUCCESS; - - ret = usbg_read_string(path, name, file, buf); - if (ret != USBG_SUCCESS) - goto out; - - new_buf = strdup(buf); - if (!new_buf) { - ret = USBG_ERROR_NO_MEM; - goto out; - } - - *dest = new_buf; -out: - return ret; -} - -static int usbg_write_buf(const char *path, const char *name, const char *file, - const char *buf) +static int usbg_write_buf(char *path, char *name, char *file, char *buf) { char p[USBG_MAX_PATH_LENGTH]; FILE *fp; @@ -574,8 +473,8 @@ static int usbg_write_buf(const char *path, const char *name, const char *file, return ret; } -static int usbg_write_int(const char *path, const char *name, const char *file, - int value, const char *str) +static int usbg_write_int(char *path, char *name, char *file, int value, + char *str) { char buf[USBG_MAX_STR_LENGTH]; int nmb; @@ -587,13 +486,11 @@ static int usbg_write_int(const char *path, const char *name, const char *file, } #define usbg_write_dec(p, n, f, v) usbg_write_int(p, n, f, v, "%d\n") -#define usbg_write_hex(p, n, f, v) usbg_write_int(p, n, f, v, "0x%x\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") -#define usbg_write_bool(p, n, f, v) usbg_write_dec(p, n, f, !!v) -static inline int usbg_write_string(const char *path, const char *name, - const char *file, const char *buf) +static inline int usbg_write_string(char *path, char *name, char *file, + char *buf) { return usbg_write_buf(path, name, file, buf); } @@ -609,7 +506,6 @@ static inline void usbg_free_function(usbg_function *f) { free(f->path); free(f->name); - free(f->label); free(f); } @@ -631,12 +527,6 @@ static void usbg_free_gadget(usbg_gadget *g) { usbg_config *c; usbg_function *f; - - if (g->last_failed_import) { - config_destroy(g->last_failed_import); - free(g->last_failed_import); - } - while (!TAILQ_EMPTY(&g->configs)) { c = TAILQ_FIRST(&g->configs); TAILQ_REMOVE(&g->configs, c, cnode); @@ -652,41 +542,20 @@ 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); - } - free(s->path); - free(s->configfs_path); free(s); } -static usbg_gadget *usbg_allocate_gadget(const char *path, const char *name, +static usbg_gadget *usbg_allocate_gadget(char *path, char *name, usbg_state *parent) { usbg_gadget *g; @@ -695,11 +564,9 @@ static usbg_gadget *usbg_allocate_gadget(const char *path, const char *name, if (g) { TAILQ_INIT(&g->functions); TAILQ_INIT(&g->configs); - g->last_failed_import = NULL; g->name = strdup(name); g->path = strdup(path); g->parent = parent; - g->udc = NULL; if (!(g->name) || !(g->path)) { free(g->name); @@ -748,8 +615,6 @@ out: return c; } -static int usbg_rm_ms_function(usbg_function *f, int opts); - static usbg_function *usbg_allocate_function(const char *path, usbg_function_type type, const char *instance, usbg_gadget *parent) { @@ -761,7 +626,6 @@ static usbg_function *usbg_allocate_function(const char *path, if (!f) goto out; - f->label = NULL; type_name = usbg_get_function_type_str(type); if (!type_name) { free(f); @@ -780,16 +644,6 @@ static usbg_function *usbg_allocate_function(const char *path, f->parent = parent; f->type = type; - /* only composed functions (with subdirs) require this callback */ - switch (usbg_lookup_function_attrs_type(type)) { - case USBG_F_ATTRS_MS: - f->rm_callback = usbg_rm_ms_function; - break; - default: - f->rm_callback = NULL; - break; - } - if (!(f->path)) { free(f->name); free(f->path); @@ -801,7 +655,7 @@ out: return f; } -static usbg_binding *usbg_allocate_binding(const char *path, const char *name, +static usbg_binding *usbg_allocate_binding(char *path, char *name, usbg_config *parent) { usbg_binding *b; @@ -823,108 +677,20 @@ 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; - int nmb; - char buf[USBG_MAX_PATH_LENGTH]; - - nmb = snprintf(buf, sizeof(buf), "%s/%s", path, name); - if (nmb < sizeof(buf)) { - nmb = unlink(buf); - if (nmb != 0) - ret = usbg_translate_error(errno); - } else { - ret = USBG_ERROR_PATH_TOO_LONG; - } - - return ret; -} - -static int usbg_rm_dir(const char *path, const char *name) -{ - int ret = USBG_SUCCESS; - int nmb; - char buf[USBG_MAX_PATH_LENGTH]; - - nmb = snprintf(buf, sizeof(buf), "%s/%s", path, name); - if (nmb < sizeof(buf)) { - nmb = rmdir(buf); - if (nmb != 0) - ret = usbg_translate_error(errno); - } else { - ret = USBG_ERROR_PATH_TOO_LONG; - } - - return ret; -} - -static int usbg_rm_all_dirs(const char *path) -{ - int ret = USBG_SUCCESS; - int n, i; - struct dirent **dent; - - n = scandir(path, &dent, file_select, alphasort); - if (n >= 0) { - for (i = 0; i < n; ++i) { - if (ret == USBG_SUCCESS) - ret = usbg_rm_dir(path, dent[i]->d_name); - - free(dent[i]); - } - free(dent); - } else { - ret = usbg_translate_error(errno); - } - - return ret; -} - -char *usbg_ether_ntoa_r(const struct ether_addr *addr, char *buf) -{ - sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", - addr->ether_addr_octet[0], addr->ether_addr_octet[1], - addr->ether_addr_octet[2], addr->ether_addr_octet[3], - addr->ether_addr_octet[4], addr->ether_addr_octet[5]); - return buf; -} - static int usbg_parse_function_net_attrs(usbg_function *f, - usbg_f_net_attrs *f_net_attrs) + usbg_function_attrs *f_attrs) { struct ether_addr *addr; - struct ether_addr addr_buf; - char str_addr[USBG_MAX_STR_LENGTH]; + char str_addr[40]; int ret; ret = usbg_read_string(f->path, f->name, "dev_addr", str_addr); if (ret != USBG_SUCCESS) goto out; - addr = ether_aton_r(str_addr, &addr_buf); + addr = ether_aton(str_addr); if (addr) { - f_net_attrs->dev_addr = *addr; + f_attrs->net.dev_addr = *addr; } else { ret = USBG_ERROR_IO; goto out; @@ -934,215 +700,19 @@ static int usbg_parse_function_net_attrs(usbg_function *f, if (ret != USBG_SUCCESS) goto out; - addr = ether_aton_r(str_addr, &addr_buf); + addr = ether_aton(str_addr); if (addr) { - f_net_attrs->host_addr = *addr; + f_attrs->net.host_addr = *addr; } else { ret = USBG_ERROR_IO; goto out; } - ret = usbg_read_dec(f->path, f->name, "qmult", &(f_net_attrs->qmult)); + ret = usbg_read_string(f->path, f->name, "ifname", f_attrs->net.ifname); if (ret != USBG_SUCCESS) goto out; - ret = usbg_read_string_alloc(f->path, f->name, "ifname", - &(f_net_attrs->ifname)); -out: - return ret; -} - -static int usbg_parse_function_ms_lun_attrs(const char *path, const char *lun, - usbg_f_ms_lun_attrs *lun_attrs) -{ - int ret; - - memset(lun_attrs, 0, sizeof(*lun_attrs)); - - ret = sscanf(lun, "lun.%d", &lun_attrs->id); - if (ret != 1) - goto out; - - ret = usbg_read_bool(path, lun, "cdrom", &(lun_attrs->cdrom)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_bool(path, lun, "ro", &(lun_attrs->ro)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_bool(path, lun, "nofua", &(lun_attrs->nofua)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_bool(path, lun, "removable", &(lun_attrs->removable)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_string_alloc(path, lun, "file", - &(lun_attrs->filename)); - -out: - return ret; -} - -static inline int lun_select(const struct dirent *dent) -{ - int ret; - int id; - - ret = file_select(dent); - if (!ret) - goto out; - - ret = sscanf(dent->d_name, "lun.%d", &id); -out: - return ret; -} - -static inline int lun_sort(const struct dirent **d1, const struct dirent **d2) -{ - int ret; - int id1, id2; - - ret = sscanf((*d1)->d_name, "lun.%d", &id1); - if (ret != 1) - goto err; - - ret = sscanf((*d2)->d_name, "lun.%d", &id2); - if (ret != 1) - goto err; - - if (id1 < id2) - ret = 1; - - return id1 < id2 ? -1 : id1 > id2; -err: - /* - * This should not happened because dentries has been - * already checked by lun_select function. This - * error procedure is just in case. - */ - return -1; -} - -static int usbg_parse_function_ms_attrs(usbg_function *f, - usbg_f_ms_attrs *f_ms_attrs) -{ - int ret; - int nmb; - int i = 0; - char fpath[USBG_MAX_PATH_LENGTH]; - usbg_f_ms_lun_attrs *lun_attrs; - usbg_f_ms_lun_attrs **luns; - struct dirent **dent; - - ret = usbg_read_bool(f->path, f->name, "stall", - &(f_ms_attrs->stall)); - if (ret != USBG_SUCCESS) - goto out; - - - nmb = snprintf(fpath, sizeof(fpath), "%s/%s/", - f->path, f->name); - if (nmb >= sizeof(fpath)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - nmb = scandir(fpath, &dent, lun_select, lun_sort); - if (nmb < 0) { - ret = usbg_translate_error(errno); - goto out; - } - - luns = calloc(nmb + 1, sizeof(*luns)); - if (!luns) { - ret = USBG_ERROR_NO_MEM; - goto err; - } - - f_ms_attrs->luns = luns; - f_ms_attrs->nluns = nmb; - - for (i = 0; i < nmb; i++) { - lun_attrs = malloc(sizeof(*lun_attrs)); - if (!lun_attrs) { - ret = USBG_ERROR_NO_MEM; - goto err; - } - - ret = usbg_parse_function_ms_lun_attrs(fpath, dent[i]->d_name, - lun_attrs); - if (ret != USBG_SUCCESS) { - free(lun_attrs); - goto err; - } - - luns[i] = lun_attrs; - free(dent[i]); - } - free(dent); - - return USBG_SUCCESS; - -err: - while (i < nmb) { - free(dent[i]); - ++i; - } - free(dent); - - usbg_cleanup_function_attrs( - container_of((usbg_f_attrs *)f_ms_attrs, - usbg_function_attrs, attrs)); -out: - return ret; -} - -static int usbg_parse_function_midi_attrs(usbg_function *f, - usbg_f_midi_attrs *attrs) -{ - int ret; - - ret = usbg_read_dec(f->path, f->name, "index", &(attrs->index)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_string_alloc(f->path, f->name, "id", &(attrs->id)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_dec(f->path, f->name, "in_ports", (int*)&(attrs->in_ports)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_dec(f->path, f->name, "out_ports", (int*)&(attrs->out_ports)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_dec(f->path, f->name, "buflen", (int*)&(attrs->buflen)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_dec(f->path, f->name, "qlen", (int*)&(attrs->qlen)); - if (ret != USBG_SUCCESS) - goto out; - -out: - return ret; -} - -static int usbg_parse_function_loopback_attrs(usbg_function *f, - usbg_f_loopback_attrs *attrs) -{ - int ret; - - ret = usbg_read_dec(f->path, f->name, "buflen", (int *)&(attrs->buflen)); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_read_dec(f->path, f->name, "qlen", (int *)&(attrs->qlen)); + ret = usbg_read_dec(f->path, f->name, "qmult", &(f_attrs->net.qmult)); out: return ret; @@ -1152,70 +722,34 @@ static int usbg_parse_function_attrs(usbg_function *f, usbg_function_attrs *f_attrs) { int ret; - int attrs_type; - - attrs_type = usbg_lookup_function_attrs_type(f->type); - if (attrs_type < 0) { - ret = attrs_type; - goto out; - } - switch (attrs_type) { - case USBG_F_ATTRS_SERIAL: - f_attrs->header.attrs_type = USBG_F_ATTRS_SERIAL; + switch (f->type) { + case F_SERIAL: + case F_ACM: + case F_OBEX: ret = usbg_read_dec(f->path, f->name, "port_num", - &(f_attrs->attrs.serial.port_num)); - break; - - case USBG_F_ATTRS_NET: - f_attrs->header.attrs_type = USBG_F_ATTRS_NET; - ret = usbg_parse_function_net_attrs(f, &(f_attrs->attrs.net)); + &(f_attrs->serial.port_num)); break; - - case USBG_F_ATTRS_PHONET: - f_attrs->header.attrs_type = USBG_F_ATTRS_PHONET; - ret = usbg_read_string_alloc(f->path, f->name, "ifname", - &(f_attrs->attrs.phonet.ifname)); - break; - - case USBG_F_ATTRS_FFS: - { - usbg_f_ffs_attrs *ffs_attrs = &(f_attrs->attrs.ffs); - - f_attrs->header.attrs_type = USBG_F_ATTRS_FFS; - ffs_attrs->dev_name = strdup(f->instance); - if (!ffs_attrs->dev_name) - ret = USBG_ERROR_NO_MEM; - else - ret = USBG_SUCCESS; - break; - } - - case USBG_F_ATTRS_MS: - f_attrs->header.attrs_type = USBG_F_ATTRS_MS; - ret = usbg_parse_function_ms_attrs(f, &(f_attrs->attrs.ms)); - break; - - case USBG_F_ATTRS_MIDI: - f_attrs->header.attrs_type = USBG_F_ATTRS_MIDI; - ret = usbg_parse_function_midi_attrs(f, &(f_attrs->attrs.midi)); + case F_ECM: + case F_SUBSET: + case F_NCM: + case F_EEM: + case F_RNDIS: + ret = usbg_parse_function_net_attrs(f, f_attrs); break; - - case USBG_F_ATTRS_LOOPBACK: - f_attrs->header.attrs_type = USBG_F_ATTRS_LOOPBACK; - ret = usbg_parse_function_loopback_attrs(f, &(f_attrs->attrs.loopback)); + case F_PHONET: + ret = usbg_read_string(f->path, f->name, "ifname", + f_attrs->phonet.ifname); break; - default: ERROR("Unsupported function type\n"); ret = USBG_ERROR_NOT_SUPPORTED; - break; } -out: + return ret; } -static int usbg_parse_functions(const char *path, usbg_gadget *g) +static int usbg_parse_functions(char *path, usbg_gadget *g) { usbg_function *f; int i, n; @@ -1260,7 +794,7 @@ out: return ret; } -static int usbg_parse_config_attrs(const char *path, const char *name, +static int usbg_parse_config_attrs(char *path, char *name, usbg_config_attrs *c_attrs) { int buf, ret; @@ -1277,7 +811,7 @@ static int usbg_parse_config_attrs(const char *path, const char *name, return ret; } -static int usbg_parse_config_strs(const char *path, const char *name, +static int usbg_parse_config_strs(char *path, char *name, int lang, usbg_config_strs *c_strs) { DIR *dir; @@ -1304,7 +838,8 @@ static int usbg_parse_config_strs(const char *path, const char *name, return ret; } -static int usbg_parse_config_binding(usbg_config *c, char *bpath, int path_size) +static int usbg_parse_config_binding(usbg_config *c, char *bpath, + int path_size) { int nmb; int ret; @@ -1315,7 +850,7 @@ static int usbg_parse_config_binding(usbg_config *c, char *bpath, int path_size) usbg_function *f; usbg_binding *b; - nmb = readlink(bpath, target, sizeof(target) - 1 ); + nmb = readlink(bpath, target, sizeof(target)); if (nmb < 0) { ret = usbg_translate_error(errno); goto out; @@ -1418,7 +953,7 @@ out: return ret; } -static int usbg_parse_configs(const char *path, usbg_gadget *g) +static int usbg_parse_configs(char *path, usbg_gadget *g) { int i, n; int ret = USBG_SUCCESS; @@ -1450,7 +985,7 @@ out: return ret; } -static int usbg_parse_gadget_attrs(const char *path, const char *name, +static int usbg_parse_gadget_attrs(char *path, char *name, usbg_gadget_attrs *g_attrs) { int buf, ret; @@ -1463,6 +998,12 @@ static int usbg_parse_gadget_attrs(const char *path, const char *name, else goto out; + ret = usbg_read_hex(path, name, "bcdDevice", &buf); + if (ret == USBG_SUCCESS) + g_attrs->bcdDevice = (uint16_t) buf; + else + goto out; + ret = usbg_read_hex(path, name, "bDeviceClass", &buf); if (ret == USBG_SUCCESS) g_attrs->bDeviceClass = (uint8_t)buf; @@ -1499,17 +1040,11 @@ static int usbg_parse_gadget_attrs(const char *path, const char *name, else goto out; - ret = usbg_read_hex(path, name, "bcdDevice", &buf); - if (ret == USBG_SUCCESS) - g_attrs->bcdDevice = (uint16_t) buf; - else - goto out; - out: return ret; } -static int usbg_parse_gadget_strs(const char *path, const char *name, int lang, +static int usbg_parse_gadget_strs(char *path, char *name, int lang, usbg_gadget_strs *g_strs) { int ret; @@ -1550,17 +1085,12 @@ out: static inline int usbg_parse_gadget(usbg_gadget *g) { int ret; - char buf[USBG_MAX_STR_LENGTH]; /* UDC bound to, if any */ - ret = usbg_read_string(g->path, g->name, "UDC", buf); + ret = usbg_read_string(g->path, g->name, "UDC", g->udc); if (ret != USBG_SUCCESS) goto out; - g->udc = usbg_get_udc(g->parent, buf); - if (g->udc) - g->udc->gadget = g; - ret = usbg_parse_functions(g->path, g); if (ret != USBG_SUCCESS) goto out; @@ -1570,7 +1100,7 @@ out: return ret; } -static int usbg_parse_gadgets(const char *path, usbg_state *s) +static int usbg_parse_gadgets(char *path, usbg_state *s) { usbg_gadget *g; int i, n; @@ -1605,86 +1135,18 @@ static int usbg_parse_gadgets(const char *path, usbg_state *s) return ret; } -static int usbg_parse_udcs(usbg_state *s) +static int usbg_init_state(char *path, 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 usbg_state *usbg_allocate_state(const char *configfs_path, char *path) -{ - usbg_state *s; - - s = malloc(sizeof(*s)); - if (!s) - goto err; - - s->configfs_path = strdup(configfs_path); - if (!s->configfs_path) - goto cpath_failed; /* State takes the ownership of path and should free it */ s->path = path; - s->last_failed_import = NULL; TAILQ_INIT(&s->gadgets); - TAILQ_INIT(&s->udcs); - - return s; -cpath_failed: - free(s); -err: - return NULL; -} - -static int usbg_parse_state(usbg_state *s) -{ - int ret = USBG_SUCCESS; - - /* - * USBG_ERROR_NOT_FOUND is returned if we are running on machine where - * there is no udc support in kernel (no /sys/class/udc dir). - * This check allows to run library on such machine or if we don't - * have rights to read this directory. - * User will be able to finish init function and manage gadgets but - * wont be able to bind it as there is no UDC. - */ - ret = usbg_parse_udcs(s); - if (ret != USBG_SUCCESS && ret != USBG_ERROR_NOT_FOUND && - ret != USBG_ERROR_NO_ACCESS) { - ERROR("Unable to parse udcs"); - goto out; - } - - ret = usbg_parse_gadgets(s->path, s); + ret = usbg_parse_gadgets(path, s); if (ret != USBG_SUCCESS) - ERROR("unable to parse %s\n", s->path); + ERRORNO("unable to parse %s\n", path); -out: return ret; } @@ -1692,14 +1154,13 @@ out: * User API */ -int usbg_init(const char *configfs_path, usbg_state **state) +int usbg_init(char *configfs_path, usbg_state **state) { int ret = USBG_SUCCESS; DIR *dir; char *path; - usbg_state *s; - ret = asprintf(&path, "%s/" GADGETS_DIR, configfs_path); + ret = asprintf(&path, "%s/usb_gadget", configfs_path); if (ret < 0) return USBG_ERROR_NO_MEM; else @@ -1707,33 +1168,21 @@ int usbg_init(const char *configfs_path, usbg_state **state) /* Check if directory exist */ dir = opendir(path); - if (!dir) { + if (dir) { + closedir(dir); + *state = malloc(sizeof(usbg_state)); + ret = *state ? usbg_init_state(path, *state) + : USBG_ERROR_NO_MEM; + if (*state && ret != USBG_SUCCESS) { + ERRORNO("couldn't init gadget state\n"); + usbg_free_state(*state); + } + } else { ERRORNO("couldn't init gadget state\n"); ret = usbg_translate_error(errno); - goto err; + free(path); } - closedir(dir); - s = usbg_allocate_state(configfs_path, path); - if (!s) { - ret = USBG_ERROR_NO_MEM; - goto err; - } - - ret = usbg_parse_state(s); - if (ret != USBG_SUCCESS) { - ERROR("couldn't init gadget state\n"); - usbg_free_state(s); - goto out; - } - - *state = s; - - return ret; - -err: - free(path); -out: return ret; } @@ -1742,25 +1191,20 @@ void usbg_cleanup(usbg_state *s) usbg_free_state(s); } -const char *usbg_get_configfs_path(usbg_state *s) -{ - return s ? s->configfs_path : NULL; -} - size_t usbg_get_configfs_path_len(usbg_state *s) { - return s ? strlen(s->configfs_path) : USBG_ERROR_INVALID_PARAM; + return s ? strlen(s->path) : USBG_ERROR_INVALID_PARAM; } -int usbg_cpy_configfs_path(usbg_state *s, char *buf, size_t len) +int usbg_get_configfs_path(usbg_state *s, char *buf, size_t len) { - if (!s || !buf || len == 0) - return USBG_ERROR_INVALID_PARAM; - - buf[--len] = '\0'; - strncpy(buf, s->configfs_path, len); + int ret = USBG_SUCCESS; + if (s && buf) + strncpy(buf, s->path, len); + else + ret = USBG_ERROR_INVALID_PARAM; - return USBG_SUCCESS; + return ret; } usbg_gadget *usbg_get_gadget(usbg_state *s, const char *name) @@ -1797,17 +1241,6 @@ 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; @@ -1830,259 +1263,10 @@ usbg_binding *usbg_get_link_binding(usbg_config *c, usbg_function *f) return NULL; } -int usbg_rm_binding(usbg_binding *b) -{ - int ret = USBG_SUCCESS; - usbg_config *c; - - if (!b) - return USBG_ERROR_INVALID_PARAM; - - c = b->parent; - - ret = ubsg_rm_file(b->path, b->name); - if (ret == USBG_SUCCESS) { - TAILQ_REMOVE(&(c->bindings), b, bnode); - usbg_free_binding(b); - } - - return ret; -} - -int usbg_rm_config(usbg_config *c, int opts) -{ - int ret = USBG_ERROR_INVALID_PARAM; - usbg_gadget *g; - - if (!c) - return ret; - - g = c->parent; - - if (opts & USBG_RM_RECURSE) { - /* Recursive flag was given - * so remove all bindings and strings */ - char spath[USBG_MAX_PATH_LENGTH]; - int nmb; - usbg_binding *b; - - while (!TAILQ_EMPTY(&c->bindings)) { - b = TAILQ_FIRST(&c->bindings); - ret = usbg_rm_binding(b); - if (ret != USBG_SUCCESS) - goto out; - } - - nmb = snprintf(spath, sizeof(spath), "%s/%s/%s", c->path, - c->name, STRINGS_DIR); - if (nmb >= sizeof(spath)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - ret = usbg_rm_all_dirs(spath); - if (ret != USBG_SUCCESS) - goto out; - } - - ret = usbg_rm_dir(c->path, c->name); - if (ret == USBG_SUCCESS) { - TAILQ_REMOVE(&(g->configs), c, cnode); - usbg_free_config(c); - } - -out: - return ret; -} - -static int usbg_rm_ms_function(usbg_function *f, int opts) -{ - int ret; - int nmb; - int i; - char lpath[USBG_MAX_PATH_LENGTH]; - struct dirent **dent; - - ret = snprintf(lpath, sizeof(lpath), "%s/%s/", f->path, f->name); - if (ret >= sizeof(lpath)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - nmb = scandir(lpath, &dent, lun_select, lun_sort); - if (nmb < 0) { - ret = usbg_translate_error(errno); - goto out; - } - - for (i = nmb - 1; i > 0; --i) { - ret = usbg_rm_dir(lpath, dent[i]->d_name); - free(dent[i]); - if (ret) - goto err_free_dent_loop; - } - free(dent[0]); - free(dent); - - return USBG_SUCCESS; - -err_free_dent_loop: - while (--i >= 0) - free(dent[i]); - free(dent[i]); -out: - return ret; -} - -int usbg_rm_function(usbg_function *f, int opts) -{ - int ret = USBG_ERROR_INVALID_PARAM; - usbg_gadget *g; - - if (!f) - return ret; - - g = f->parent; - - if (opts & USBG_RM_RECURSE) { - /* Recursive flag was given - * so remove all bindings to this function */ - usbg_config *c; - usbg_binding *b; - - TAILQ_FOREACH(c, &g->configs, cnode) { - b = TAILQ_FIRST(&c->bindings); - while (b != NULL) { - if (b->target == f) { - usbg_binding *b_next = TAILQ_NEXT(b, bnode); - ret = usbg_rm_binding(b); - if (ret != USBG_SUCCESS) - return ret; - - b = b_next; - } else { - b = TAILQ_NEXT(b, bnode); - } - } /* while */ - } /* TAILQ_FOREACH */ - } - - if (f->rm_callback) { - ret = f->rm_callback(f, opts); - if (ret != USBG_SUCCESS) - goto out; - } - - ret = usbg_rm_dir(f->path, f->name); - if (ret == USBG_SUCCESS) { - TAILQ_REMOVE(&(g->functions), f, fnode); - usbg_free_function(f); - } - -out: - return ret; -} - -int usbg_rm_gadget(usbg_gadget *g, int opts) -{ - int ret = USBG_ERROR_INVALID_PARAM; - usbg_state *s; - if (!g) - goto out; - - s = g->parent; - - if (opts & USBG_RM_RECURSE) { - /* Recursive flag was given - * so remove all configs and functions - * using recursive flags */ - usbg_config *c; - usbg_function *f; - int nmb; - char spath[USBG_MAX_PATH_LENGTH]; - - while (!TAILQ_EMPTY(&g->configs)) { - c = TAILQ_FIRST(&g->configs); - ret = usbg_rm_config(c, opts); - if (ret != USBG_SUCCESS) - goto out; - } - - while (!TAILQ_EMPTY(&g->functions)) { - f = TAILQ_FIRST(&g->functions); - ret = usbg_rm_function(f, opts); - if (ret != USBG_SUCCESS) - goto out; - } - - nmb = snprintf(spath, sizeof(spath), "%s/%s/%s", g->path, - g->name, STRINGS_DIR); - if (nmb >= sizeof(spath)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - ret = usbg_rm_all_dirs(spath); - if (ret != USBG_SUCCESS) - goto out; - } - - ret = usbg_rm_dir(g->path, g->name); - if (ret == USBG_SUCCESS) { - TAILQ_REMOVE(&(s->gadgets), g, gnode); - usbg_free_gadget(g); - } - -out: - return ret; -} - -int usbg_rm_config_strs(usbg_config *c, int lang) -{ - int ret = USBG_SUCCESS; - int nmb; - char path[USBG_MAX_PATH_LENGTH]; - - if (!c) - return USBG_ERROR_INVALID_PARAM; - - nmb = snprintf(path, sizeof(path), "%s/%s/%s/0x%x", c->path, c->name, - STRINGS_DIR, lang); - if (nmb < sizeof(path)) - ret = usbg_rm_dir(path, ""); - else - ret = USBG_ERROR_PATH_TOO_LONG; - - return ret; -} - -int usbg_rm_gadget_strs(usbg_gadget *g, int lang) -{ - int ret = USBG_SUCCESS; - int nmb; - char path[USBG_MAX_PATH_LENGTH]; - - if (!g) - return USBG_ERROR_INVALID_PARAM; - - nmb = snprintf(path, sizeof(path), "%s/%s/%s/0x%x", g->path, g->name, - STRINGS_DIR, lang); - if (nmb < sizeof(path)) - ret = usbg_rm_dir(path, ""); - else - ret = USBG_ERROR_PATH_TOO_LONG; - - return ret; -} - - -static int usbg_create_empty_gadget(usbg_state *s, const char *name, - usbg_gadget **g) +static int usbg_create_empty_gadget(usbg_state *s, char *name, usbg_gadget **g) { char gpath[USBG_MAX_PATH_LENGTH]; - char buf[USBG_MAX_STR_LENGTH]; int nmb; - usbg_gadget *gad; int ret = USBG_SUCCESS; nmb = snprintf(gpath, sizeof(gpath), "%s/%s", s->path, name); @@ -2092,39 +1276,33 @@ static int usbg_create_empty_gadget(usbg_state *s, const char *name, } *g = usbg_allocate_gadget(s->path, name, s); - if (!*g) { - ret = USBG_ERROR_NO_MEM; - goto out; - } - - gad = *g; /* alias only */ + if (*g) { + usbg_gadget *gad = *g; /* alias only */ + + 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) { - /* Should be empty but read the default */ - ret = usbg_read_string(gad->path, gad->name, - "UDC", buf); if (ret != USBG_SUCCESS) { - rmdir(gpath); - } else { - gad->udc = usbg_get_udc(s, buf); - if (gad->udc) - gad->udc->gadget = gad; + usbg_free_gadget(*g); + *g = NULL; } } else { - ret = usbg_translate_error(errno); - } - - if (ret != USBG_SUCCESS) { - usbg_free_gadget(*g); - *g = NULL; + ret = USBG_ERROR_NO_MEM; } out: return ret; } -int usbg_create_gadget_vid_pid(usbg_state *s, const char *name, +int usbg_create_gadget_vid_pid(usbg_state *s, char *name, uint16_t idVendor, uint16_t idProduct, usbg_gadget **g) { int ret; @@ -2158,9 +1336,8 @@ int usbg_create_gadget_vid_pid(usbg_state *s, const char *name, return ret; } -int usbg_create_gadget(usbg_state *s, const char *name, - const usbg_gadget_attrs *g_attrs, const usbg_gadget_strs *g_strs, - usbg_gadget **g) +int usbg_create_gadget(usbg_state *s, char *name, + usbg_gadget_attrs *g_attrs, usbg_gadget_strs *g_strs, usbg_gadget **g) { usbg_gadget *gad; int ret; @@ -2200,147 +1377,39 @@ int usbg_get_gadget_attrs(usbg_gadget *g, usbg_gadget_attrs *g_attrs) : USBG_ERROR_INVALID_PARAM; } -const char *usbg_get_gadget_name(usbg_gadget *g) -{ - return g ? g->name : NULL; -} - size_t usbg_get_gadget_name_len(usbg_gadget *g) { return g ? strlen(g->name) : USBG_ERROR_INVALID_PARAM; } -int usbg_cpy_gadget_name(usbg_gadget *g, char *buf, size_t len) -{ - if (!g || !buf || len == 0) - return USBG_ERROR_INVALID_PARAM; - - buf[--len] = '\0'; - strncpy(buf, g->name, len); - - return USBG_SUCCESS; -} - -const char *usbg_get_udc_name(usbg_udc *u) -{ - return u ? u->name : NULL; -} - -size_t usbg_get_udc_name_len(usbg_udc *u) -{ - return u ? strlen(u->name) : USBG_ERROR_INVALID_PARAM; -} - -int usbg_cpy_udc_name(usbg_udc *u, char *buf, size_t len) -{ - if (!u || !buf || len == 0) - return USBG_ERROR_INVALID_PARAM; - - buf[--len] = '\0'; - strncpy(buf, u->name, len); - - return USBG_SUCCESS; -} - -int usbg_set_gadget_attr(usbg_gadget *g, usbg_gadget_attr attr, int val) -{ - const char *attr_name; - int ret = USBG_ERROR_INVALID_PARAM; - - if (!g) - goto out; - - attr_name = usbg_get_gadget_attr_str(attr); - if (!attr_name) - goto out; - - ret = usbg_write_hex(g->path, g->name, attr_name, val); - -out: - return ret; -} - -int usbg_get_gadget_attr(usbg_gadget *g, usbg_gadget_attr attr) +int usbg_get_gadget_name(usbg_gadget *g, char *buf, size_t len) { - const char *attr_name; - int ret = USBG_ERROR_INVALID_PARAM; - - if (!g) - goto out; - - attr_name = usbg_get_gadget_attr_str(attr); - if (!attr_name) - goto out; - - usbg_read_hex(g->path, g->name, attr_name, &ret); + int ret = USBG_SUCCESS; + if (g && buf) + strncpy(buf, g->name, len); + else + ret = USBG_ERROR_INVALID_PARAM; -out: return ret; } -usbg_udc *usbg_get_gadget_udc(usbg_gadget *g) +size_t usbg_get_gadget_udc_len(usbg_gadget *g) { - usbg_udc *u = NULL; - - if (!g) - goto out; - /* - * if gadget was enabled we have to check if kernel - * didn't modify the UDC file due to some errors. - * For example some FFS daemon could just get - * a segmentation fault or sth - */ - if (g->udc) { - char buf[USBG_MAX_STR_LENGTH]; - int ret; - - ret = usbg_read_string(g->path, g->name, "UDC", buf); - if (ret != USBG_SUCCESS) - goto out; - - if (!strcmp(g->udc->name, buf)) { - /* Gadget is still assigned to this UDC */ - u = g->udc; - } else { - /* Kernel decided to detach this gadget */ - g->udc->gadget = NULL; - g->udc = NULL; - } - } - -out: - return u; + return g ? strlen(g->udc) : USBG_ERROR_INVALID_PARAM; } -usbg_gadget *usbg_get_udc_gadget(usbg_udc *u) +int usbg_get_gadget_udc(usbg_gadget *g, char *buf, size_t len) { - usbg_gadget *g = NULL; - - if (!u) - goto out; - /* - * if gadget was enabled on this UDC we have to check if kernel - * didn't modify this due to some errors. - * For example some FFS daemon could just get a segmentation fault - * what causes detach of gadget - */ - if (u->gadget) { - usbg_udc *u_checked; - - u_checked = usbg_get_gadget_udc(u->gadget); - if (u_checked) { - g = u->gadget; - } else { - u->gadget->udc = NULL; - u->gadget = NULL; - } - } + int ret = USBG_SUCCESS; + if (g && buf) + strncpy(buf, g->udc, len); + else + ret = USBG_ERROR_INVALID_PARAM; -out: - return g; + return ret; } -int usbg_set_gadget_attrs(usbg_gadget *g, const usbg_gadget_attrs *g_attrs) +int usbg_set_gadget_attrs(usbg_gadget *g, usbg_gadget_attrs *g_attrs) { int ret; if (!g || !g_attrs) @@ -2442,7 +1511,7 @@ int usbg_get_gadget_strs(usbg_gadget *g, int lang, g_strs) : USBG_ERROR_INVALID_PARAM; } -static int usbg_check_dir(const char *path) +static int usbg_check_dir(char *path) { int ret = USBG_SUCCESS; DIR *dir; @@ -2457,40 +1526,8 @@ static int usbg_check_dir(const char *path) return ret; } -int usbg_set_gadget_str(usbg_gadget *g, usbg_gadget_str str, int lang, - const char *val) -{ - const char *str_name; - int ret = USBG_ERROR_INVALID_PARAM; - char path[USBG_MAX_PATH_LENGTH]; - int nmb; - - if (!g) - goto out; - - str_name = usbg_get_gadget_str_name(str); - if (!str_name) - goto out; - - nmb = snprintf(path, sizeof(path), "%s/%s/%s/0x%x", g->path, g->name, - STRINGS_DIR, lang); - if (nmb >= sizeof(path)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - ret = usbg_check_dir(path); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_string(path, "", str_name, val); - -out: - return ret; -} - int usbg_set_gadget_strs(usbg_gadget *g, int lang, - const usbg_gadget_strs *g_strs) + usbg_gadget_strs *g_strs) { char path[USBG_MAX_PATH_LENGTH]; int nmb; @@ -2523,7 +1560,7 @@ out: return ret; } -int usbg_set_gadget_serial_number(usbg_gadget *g, int lang, const char *serno) +int usbg_set_gadget_serial_number(usbg_gadget *g, int lang, char *serno) { int ret = USBG_ERROR_INVALID_PARAM; @@ -2544,7 +1581,7 @@ int usbg_set_gadget_serial_number(usbg_gadget *g, int lang, const char *serno) return ret; } -int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, const char *mnf) +int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, char *mnf) { int ret = USBG_ERROR_INVALID_PARAM; @@ -2565,7 +1602,7 @@ int usbg_set_gadget_manufacturer(usbg_gadget *g, int lang, const char *mnf) return ret; } -int usbg_set_gadget_product(usbg_gadget *g, int lang, const char *prd) +int usbg_set_gadget_product(usbg_gadget *g, int lang, char *prd) { int ret = USBG_ERROR_INVALID_PARAM; @@ -2587,36 +1624,16 @@ int usbg_set_gadget_product(usbg_gadget *g, int lang, const char *prd) } int usbg_create_function(usbg_gadget *g, usbg_function_type type, - const char *instance, const usbg_function_attrs *f_attrs, - usbg_function **f) + char *instance, usbg_function_attrs *f_attrs, usbg_function **f) { char fpath[USBG_MAX_PATH_LENGTH]; usbg_function *func; int ret = USBG_ERROR_INVALID_PARAM; int n, free_space; - if (!g || !f) + if (!g || !f || !instance) return ret; - /* if attrs type is set, check if it has correct type */ - if (f_attrs && f_attrs->header.attrs_type) { - int attrs_type; - attrs_type = usbg_lookup_function_attrs_type(type); - if (attrs_type < 0 || attrs_type != f_attrs->header.attrs_type) - return ret; - } - - if (!instance) { - /* If someone creates ffs function and doesn't pass instance name - this means that device name from attrs should be used */ - if (type == F_FFS && f_attrs && f_attrs->attrs.ffs.dev_name) { - instance = f_attrs->attrs.ffs.dev_name; - f_attrs = NULL; - } else { - return ret; - } - } - func = usbg_get_function(g, type, instance); if (func) { ERROR("duplicate function name\n"); @@ -2634,9 +1651,8 @@ int usbg_create_function(usbg_gadget *g, usbg_function_type type, *f = usbg_allocate_function(fpath, type, instance, g); func = *f; if (!func) { - ERROR("allocating function\n"); + ERRORNO("allocating function\n"); ret = USBG_ERROR_NO_MEM; - goto out; } free_space = sizeof(fpath) - n; @@ -2664,11 +1680,10 @@ out: } int usbg_create_config(usbg_gadget *g, int id, const char *label, - const usbg_config_attrs *c_attrs, const usbg_config_strs *c_strs, - usbg_config **c) + usbg_config_attrs *c_attrs, usbg_config_strs *c_strs, usbg_config **c) { char cpath[USBG_MAX_PATH_LENGTH]; - usbg_config *conf = NULL; + usbg_config *conf; int ret = USBG_ERROR_INVALID_PARAM; int n, free_space; @@ -2695,7 +1710,7 @@ int usbg_create_config(usbg_gadget *g, int id, const char *label, *c = usbg_allocate_config(cpath, label, id, g); conf = *c; if (!conf) { - ERROR("allocating configuration\n"); + ERRORNO("allocating configuration\n"); ret = USBG_ERROR_NO_MEM; goto out; } @@ -2703,10 +1718,8 @@ int usbg_create_config(usbg_gadget *g, int id, const char *label, free_space = sizeof(cpath) - n; /* Append string at the end of previous one */ n = snprintf(&(cpath[n]), free_space, "/%s", (*c)->name); - if (n >= free_space) { + if (n < free_space) { ret = USBG_ERROR_PATH_TOO_LONG; - usbg_free_config(conf); - goto out; } ret = mkdir(cpath, S_IRWXU | S_IRWXG | S_IRWXO); @@ -2732,25 +1745,20 @@ out: return ret; } -const char *usbg_get_config_label(usbg_config *c) -{ - return c ? c->label : NULL; -} - size_t usbg_get_config_label_len(usbg_config *c) { return c ? strlen(c->label) : USBG_ERROR_INVALID_PARAM; } -int usbg_cpy_config_label(usbg_config *c, char *buf, size_t len) +int usbg_get_config_label(usbg_config *c, char *buf, size_t len) { - if (!c || !buf || len == 0) - return USBG_ERROR_INVALID_PARAM; - - buf[--len] = '\0'; - strncpy(buf, c->label, len); + int ret = USBG_SUCCESS; + if (c && buf) + strncpy(buf, c->label, len); + else + ret = USBG_ERROR_INVALID_PARAM; - return USBG_SUCCESS; + return ret; } int usbg_get_config_id(usbg_config *c) @@ -2758,32 +1766,27 @@ int usbg_get_config_id(usbg_config *c) return c ? c->id : USBG_ERROR_INVALID_PARAM; } -const char *usbg_get_function_instance(usbg_function *f) -{ - return f ? f->instance : NULL; -} - size_t usbg_get_function_instance_len(usbg_function *f) { return f ? strlen(f->instance) : USBG_ERROR_INVALID_PARAM; } -int usbg_cpy_function_instance(usbg_function *f, char *buf, size_t len) +int usbg_get_function_instance(usbg_function *f, char *buf, size_t len) { - if (!f || !buf || len == 0) - return USBG_ERROR_INVALID_PARAM; - - buf[--len] = '\0'; - strncpy(buf, f->instance, len); + int ret = USBG_SUCCESS; + if (f && buf) + strncpy(buf, f->instance, len); + else + ret = USBG_ERROR_INVALID_PARAM; - return USBG_SUCCESS; + return ret; } -int usbg_set_config_attrs(usbg_config *c, const usbg_config_attrs *c_attrs) +int usbg_set_config_attrs(usbg_config *c, usbg_config_attrs *c_attrs) { int ret = USBG_ERROR_INVALID_PARAM; - if (c && c_attrs) { + if (c && !c_attrs) { ret = usbg_write_dec(c->path, c->name, "MaxPower", c_attrs->bMaxPower); if (ret == USBG_SUCCESS) ret = usbg_write_hex8(c->path, c->name, "bmAttributes", @@ -2819,12 +1822,12 @@ int usbg_get_config_strs(usbg_config *c, int lang, usbg_config_strs *c_strs) } int usbg_set_config_strs(usbg_config *c, int lang, - const usbg_config_strs *c_strs) + usbg_config_strs *c_strs) { return usbg_set_config_string(c, lang, c_strs->configuration); } -int usbg_set_config_string(usbg_config *c, int lang, const char *str) +int usbg_set_config_string(usbg_config *c, int lang, char *str) { int ret = USBG_ERROR_INVALID_PARAM; @@ -2845,7 +1848,7 @@ int usbg_set_config_string(usbg_config *c, int lang, const char *str) return ret; } -int usbg_add_config_function(usbg_config *c, const char *name, usbg_function *f) +int usbg_add_config_function(usbg_config *c, char *name, usbg_function *f) { char bpath[USBG_MAX_PATH_LENGTH]; char fpath[USBG_MAX_PATH_LENGTH]; @@ -2858,9 +1861,6 @@ int usbg_add_config_function(usbg_config *c, const char *name, usbg_function *f) goto out; } - if (!name) - name = f->name; - b = usbg_get_binding(c, name); if (b) { ERROR("duplicate binding name\n"); @@ -2925,50 +1925,65 @@ usbg_function *usbg_get_binding_target(usbg_binding *b) return b ? b->target : NULL; } -const char *usbg_get_binding_name(usbg_binding *b) +size_t usbg_get_binding_name_len(usbg_binding *b) { - return b ? b->name : NULL; + return b ? strlen(b->name) : USBG_ERROR_INVALID_PARAM; } -size_t usbg_get_binding_name_len(usbg_binding *b) +int usbg_get_binding_name(usbg_binding *b, char *buf, size_t len) { - return b ? strlen(b->name) : USBG_ERROR_INVALID_PARAM; + int ret = USBG_SUCCESS; + if (b && buf) + strncpy(buf, b->name, len); + else + ret = USBG_ERROR_INVALID_PARAM; + + return ret; } -int usbg_cpy_binding_name(usbg_binding *b, char *buf, size_t len) +int usbg_get_udcs(struct dirent ***udc_list) { - if (!b || !buf || len == 0) - return USBG_ERROR_INVALID_PARAM; + int ret = USBG_ERROR_INVALID_PARAM; - buf[--len] = '\0'; - strncpy(buf, b->name, len); + if (udc_list) { + ret = scandir("/sys/class/udc", udc_list, file_select, alphasort); + if (ret < 0) + ret = usbg_translate_error(errno); + } - return USBG_SUCCESS; + return ret; } -int usbg_enable_gadget(usbg_gadget *g, usbg_udc *udc) +int usbg_enable_gadget(usbg_gadget *g, char *udc) { + char gudc[USBG_MAX_STR_LENGTH]; + struct dirent **udc_list; + int i; int ret = USBG_ERROR_INVALID_PARAM; if (!g) return ret; if (!udc) { - udc = usbg_get_first_udc(g->parent); - if (!udc) + ret = usbg_get_udcs(&udc_list); + if (ret >= 0) { + /* Look for default one - first in string order */ + strcpy(gudc, udc_list[0]->d_name); + udc = gudc; + + /** Free the memory */ + for (i = 0; i < ret; ++i) + free(udc_list[i]); + free(udc_list); + } else { return ret; + } } - ret = usbg_write_string(g->path, g->name, "UDC", udc->name); - if (ret == USBG_SUCCESS) { - /* If gadget has been detached and we didn't noticed - * it we have to clean up now. - */ - if (g->udc) - g->udc->gadget = NULL; - g->udc = udc; - udc->gadget = g; - } + ret = usbg_write_string(g->path, g->name, "UDC", udc); + + if (ret == USBG_SUCCESS) + strcpy(g->udc, udc); return ret; } @@ -2977,14 +1992,9 @@ int usbg_disable_gadget(usbg_gadget *g) { int ret = USBG_ERROR_INVALID_PARAM; - if (!g) - return ret; - - ret = usbg_write_string(g->path, g->name, "UDC", "\n"); - if (ret == USBG_SUCCESS) { - if (g->udc) - g->udc->gadget = NULL; - g->udc = NULL; + if (g) { + strcpy(g->udc, ""); + ret = usbg_write_string(g->path, g->name, "UDC", ""); } return ret; @@ -3005,380 +2015,57 @@ int usbg_get_function_attrs(usbg_function *f, usbg_function_attrs *f_attrs) : USBG_ERROR_INVALID_PARAM; } -static void usbg_cleanup_function_ms_lun_attrs(usbg_f_ms_lun_attrs *lun_attrs) -{ - if (!lun_attrs) - return; - - free((char*)lun_attrs->filename); - lun_attrs->id = -1; -} - -void usbg_cleanup_function_attrs(usbg_function_attrs *f_attrs) -{ - usbg_f_attrs *attrs; - - if (!f_attrs) - return; - - attrs = &f_attrs->attrs; - - switch (f_attrs->header.attrs_type) { - case USBG_F_ATTRS_SERIAL: - break; - - case USBG_F_ATTRS_NET: - free((char*)attrs->net.ifname); - attrs->net.ifname = NULL; - break; - - case USBG_F_ATTRS_PHONET: - free((char*)attrs->phonet.ifname); - attrs->phonet.ifname = NULL; - break; - - case USBG_F_ATTRS_FFS: - free((char*)attrs->ffs.dev_name); - attrs->ffs.dev_name = NULL; - break; - - case USBG_F_ATTRS_MS: - { - int i; - usbg_f_ms_attrs *ms_attrs = &attrs->ms; - - if (!ms_attrs->luns) - goto ms_break; - - for (i = 0; i < ms_attrs->nluns; ++i) { - if (!ms_attrs->luns[i]) - continue; - - usbg_cleanup_function_ms_lun_attrs(ms_attrs->luns[i]); - free(ms_attrs->luns[i]); - } - free(ms_attrs->luns); - ms_attrs->luns = NULL; - ms_attrs->nluns = -1; - ms_break: - break; - } - - case USBG_F_ATTRS_MIDI: - free((char*)attrs->midi.id); - attrs->midi.id = NULL; - break; - - case USBG_F_ATTRS_LOOPBACK: - break; - - default: - ERROR("Unsupported attrs type\n"); - break; - } -} - -int usbg_set_function_net_attrs(usbg_function *f, const usbg_f_net_attrs *attrs) +int usbg_set_function_net_attrs(usbg_function *f, usbg_f_net_attrs *attrs) { int ret = USBG_SUCCESS; - char addr_buf[USBG_MAX_STR_LENGTH]; char *addr; - /* ifname is read only so we accept only empty string for this param */ - if (attrs->ifname && attrs->ifname[0]) { - ret = USBG_ERROR_INVALID_PARAM; - goto out; - } - - addr = usbg_ether_ntoa_r(&attrs->dev_addr, addr_buf); + addr = ether_ntoa(&attrs->dev_addr); ret = usbg_write_string(f->path, f->name, "dev_addr", addr); if (ret != USBG_SUCCESS) goto out; - addr = usbg_ether_ntoa_r(&attrs->host_addr, addr_buf); + addr = ether_ntoa(&attrs->host_addr); ret = usbg_write_string(f->path, f->name, "host_addr", addr); if (ret != USBG_SUCCESS) goto out; - ret = usbg_write_dec(f->path, f->name, "qmult", attrs->qmult); - -out: - return ret; -} - -static int usbg_set_f_ms_lun_attrs(const char *path, const char *lun, - usbg_f_ms_lun_attrs *lun_attrs) -{ - int ret; - - ret = usbg_write_bool(path, lun, "cdrom", lun_attrs->cdrom); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_bool(path, lun, "ro", lun_attrs->ro); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_bool(path, lun, "nofua", lun_attrs->nofua); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_bool(path, lun, "removable", lun_attrs->removable); + ret = usbg_write_string(f->path, f->name, "ifname", attrs->ifname); if (ret != USBG_SUCCESS) goto out; - ret = usbg_write_string(path, lun, "file", - lun_attrs->filename); - -out: - return ret; -} - -static int usbg_set_function_ms_attrs(usbg_function *f, - const usbg_f_ms_attrs *f_attrs) -{ - int ret; - int i, nmb; - int space_left; - char *new_lun_mask; - char lpath[USBG_MAX_PATH_LENGTH]; - char *lpath_end; - DIR *dir; - struct dirent **dent; - - ret = usbg_write_bool(f->path, f->name, "stall", f_attrs->stall); - if (ret != USBG_SUCCESS) - goto out; - - /* lun0 cannot be removed */ - if (!f_attrs->luns || f_attrs->nluns <= 0) - goto out; - - ret = snprintf(lpath, sizeof(lpath), "%s/%s/", f->path, f->name); - if (ret >= sizeof(lpath)) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto out; - } - - lpath_end = lpath + strlen(lpath); - space_left = sizeof(lpath) - (lpath_end - lpath); - - new_lun_mask = calloc(f_attrs->nluns, sizeof (char)); - if (!new_lun_mask) { - ret = USBG_ERROR_NO_MEM; - goto out; - } - - for (i = 0; i < f_attrs->nluns; ++i) { - usbg_f_ms_lun_attrs *lun = f_attrs->luns[i]; - - /* - * id may be left unset in lun attrs but - * if it is set it has to be equal to position - * in lun array - */ - if (lun && lun->id >= 0 && lun->id != i) { - ret = USBG_ERROR_INVALID_PARAM; - goto err_lun_loop; - } - - ret = snprintf(lpath_end, space_left, "/lun.%d/", i); - if (ret >= space_left) { - ret = USBG_ERROR_PATH_TOO_LONG; - goto err_lun_loop; - } - - /* - * Check if dir exist and create it if needed - */ - dir = opendir(lpath); - if (dir) { - closedir(dir); - } else if (errno != ENOENT) { - ret = usbg_translate_error(errno); - goto err_lun_loop; - } else { - ret = mkdir(lpath, S_IRWXU|S_IRWXG|S_IRWXO); - if (!ret) { - /* - * If we have created a new directory in - * this function let's mark it so we can - * cleanup in case of error - */ - new_lun_mask[i] = 1; - } else { - ret = usbg_translate_error(errno); - goto err_lun_loop; - } - } - - /* if attributes has not been provided just go to next one */ - if (!lun) - continue; - - ret = usbg_set_f_ms_lun_attrs(lpath, "", lun); - if (ret != USBG_SUCCESS) - goto err_lun_loop; - } - - /* Check if function has more luns and remove them */ - *lpath_end = '\0'; - i = 0; - nmb = scandir(lpath, &dent, lun_select, lun_sort); - if (nmb < 0) { - ret = usbg_translate_error(errno); - goto err_lun_loop; - } - - for (i = 0; i < f_attrs->nluns; ++i) - free(dent[i]); - - for (; i < nmb; ++i) { - ret = usbg_rm_dir(lpath, dent[i]->d_name); - free(dent[i]); - /* There is no good way to recover form this */ - if (ret != USBG_SUCCESS) - goto err_rm_loop; - } - free(dent); - free(new_lun_mask); - - return USBG_SUCCESS; - -err_rm_loop: - while (++i < nmb) - free(dent[i]); - free(dent); - - i = f_attrs->nluns; -err_lun_loop: - /* array is null terminated so we may access lun[nluns] */ - for (; i >= 0; --i) { - if (!new_lun_mask[i]) - continue; - - ret = snprintf(lpath_end, space_left, "/lun.%d/", i); - if (ret >= space_left) { - /* - * This should not happen because if we were - * able to create this directory we should be - * also able to remove it. - */ - continue; - } - rmdir(lpath); - } - free(new_lun_mask); - -out: - return ret; -} - -int usbg_set_function_midi_attrs(usbg_function *f, - const usbg_f_midi_attrs *attrs) -{ - int ret; - - ret = usbg_write_dec(f->path, f->name, "index", attrs->index); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_string(f->path, f->name, "id", attrs->id); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_dec(f->path, f->name, "in_ports", attrs->in_ports); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_dec(f->path, f->name, "out_ports", attrs->out_ports); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_dec(f->path, f->name, "buflen", attrs->buflen); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_dec(f->path, f->name, "qlen", attrs->qlen); - -out: - return ret; -} - -int usbg_set_function_loopback_attrs(usbg_function *f, - const usbg_f_loopback_attrs *attrs) -{ - int ret; - - ret = usbg_write_dec(f->path, f->name, "buflen", attrs->buflen); - if (ret != USBG_SUCCESS) - goto out; - - ret = usbg_write_dec(f->path, f->name, "qlen", attrs->qlen); + ret = usbg_write_dec(f->path, f->name, "qmult", attrs->qmult); out: return ret; } -int usbg_set_function_attrs(usbg_function *f, - const usbg_function_attrs *f_attrs) +int usbg_set_function_attrs(usbg_function *f, usbg_function_attrs *f_attrs) { int ret = USBG_ERROR_INVALID_PARAM; - int attrs_type; if (!f || !f_attrs) - return ret; - - attrs_type = usbg_lookup_function_attrs_type(f->type); - if (attrs_type < 0) - return ret; - - /* if attrs type is set, check if it has correct type */ - if (f_attrs->header.attrs_type && attrs_type != f_attrs->header.attrs_type) - return ret; - - switch (attrs_type) { - case USBG_F_ATTRS_SERIAL: - /* port_num attribute is read only so we accept only 0 - * and do nothing with it */ - ret = f_attrs->attrs.serial.port_num ? USBG_ERROR_INVALID_PARAM - : USBG_SUCCESS; - break; - - case USBG_F_ATTRS_NET: - ret = usbg_set_function_net_attrs(f, &f_attrs->attrs.net); - break; - - case USBG_F_ATTRS_PHONET: - /* ifname attribute is read only - * so we accept only empty string */ - ret = f_attrs->attrs.phonet.ifname && f_attrs->attrs.phonet.ifname[0] ? - USBG_ERROR_INVALID_PARAM : USBG_SUCCESS; - break; - - case USBG_F_ATTRS_FFS: - /* dev_name is a virtual attribute so allow only to use empty - * empty string which means nop */ - ret = f_attrs->attrs.ffs.dev_name && f_attrs->attrs.ffs.dev_name[0] ? - USBG_ERROR_INVALID_PARAM : USBG_SUCCESS; - break; + return USBG_ERROR_INVALID_PARAM; - case USBG_F_ATTRS_MS: - ret = usbg_set_function_ms_attrs(f, &f_attrs->attrs.ms); + switch (f->type) { + case F_SERIAL: + case F_ACM: + case F_OBEX: + ret = usbg_write_dec(f->path, f->name, "port_num", f_attrs->serial.port_num); break; - - case USBG_F_ATTRS_MIDI: - ret = usbg_set_function_midi_attrs(f, &f_attrs->attrs.midi); + case F_ECM: + case F_SUBSET: + case F_NCM: + case F_EEM: + case F_RNDIS: + ret = usbg_set_function_net_attrs(f, &f_attrs->net); break; - - case USBG_F_ATTRS_LOOPBACK: - ret = usbg_set_function_loopback_attrs(f, &f_attrs->attrs.loopback); + case F_PHONET: + ret = usbg_write_string(f->path, f->name, "ifname", f_attrs->phonet.ifname); break; - default: ERROR("Unsupported function type\n"); ret = USBG_ERROR_NOT_SUPPORTED; - break; } return ret; @@ -3389,8 +2076,7 @@ int usbg_set_net_dev_addr(usbg_function *f, struct ether_addr *dev_addr) int ret = USBG_SUCCESS; if (f && dev_addr) { - char str_buf[USBG_MAX_STR_LENGTH]; - char *str_addr = usbg_ether_ntoa_r(dev_addr, str_buf); + char *str_addr = ether_ntoa(dev_addr); ret = usbg_write_string(f->path, f->name, "dev_addr", str_addr); } else { ret = USBG_ERROR_INVALID_PARAM; @@ -3404,8 +2090,7 @@ int usbg_set_net_host_addr(usbg_function *f, struct ether_addr *host_addr) int ret = USBG_SUCCESS; if (f && host_addr) { - char str_buf[USBG_MAX_STR_LENGTH]; - char *str_addr = usbg_ether_ntoa_r(host_addr, str_buf); + char *str_addr = ether_ntoa(host_addr); ret = usbg_write_string(f->path, f->name, "host_addr", str_addr); } else { ret = USBG_ERROR_INVALID_PARAM; @@ -3440,11 +2125,6 @@ usbg_binding *usbg_get_first_binding(usbg_config *c) return c ? TAILQ_FIRST(&c->bindings) : NULL; } -usbg_udc *usbg_get_first_udc(usbg_state *s) -{ - return s ? TAILQ_FIRST(&s->udcs) : NULL; -} - usbg_gadget *usbg_get_next_gadget(usbg_gadget *g) { return g ? TAILQ_NEXT(g, gnode) : NULL; @@ -3464,9 +2144,3 @@ usbg_binding *usbg_get_next_binding(usbg_binding *b) { return b ? TAILQ_NEXT(b, bnode) : NULL; } - -usbg_udc *usbg_get_next_udc(usbg_udc *u) -{ - return u ? TAILQ_NEXT(u, unode) : NULL; -} - |