summaryrefslogtreecommitdiff
path: root/src/usbg.c
diff options
context:
space:
mode:
authortaeyoung <ty317.kim@samsung.com>2016-09-23 20:23:57 +0900
committertaeyoung <ty317.kim@samsung.com>2016-09-23 20:24:32 +0900
commit9ddeb24a02bff238a8c34688bd3e31e2a391c6f4 (patch)
tree6bce16ed577e3c1d432fa8aa154375fdc4753176 /src/usbg.c
parentaf80c789ed18bffe59ff815f0fddabbda56b9442 (diff)
downloadlibusbg-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.c1984
1 files changed, 329 insertions, 1655 deletions
diff --git a/src/usbg.c b/src/usbg.c
index b9c53e8..d73943c 100644
--- a/src/usbg.c
+++ b/src/usbg.c
@@ -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;
-}
-