diff options
author | Krzysztof Opasiak <k.opasiak@samsung.com> | 2015-12-22 22:47:05 +0100 |
---|---|---|
committer | Krzysztof Opasiak <k.opasiak@samsung.com> | 2015-12-23 00:49:03 +0100 |
commit | 5fff0aefae56e94be4fbe8b9f9f77b7922a3b392 (patch) | |
tree | b367735b713cb14be129ebb579be736971465e52 /src | |
parent | b5288f38defd7714ff8bd2fe7982f3d0ffbe0c49 (diff) | |
download | libusbg-5fff0aefae56e94be4fbe8b9f9f77b7922a3b392.tar.gz libusbg-5fff0aefae56e94be4fbe8b9f9f77b7922a3b392.tar.bz2 libusbg-5fff0aefae56e94be4fbe8b9f9f77b7922a3b392.zip |
libusbgx: net: Add implementation of function specific API
Implement all function-specific functions from header file
Signed-off-by: Krzysztof Opasiak <k.opasiak@samsung.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/function/ether.c | 338 |
1 files changed, 196 insertions, 142 deletions
diff --git a/src/function/ether.c b/src/function/ether.c index a778aee..3bdda43 100644 --- a/src/function/ether.c +++ b/src/function/ether.c @@ -12,90 +12,99 @@ #include "usbg/usbg.h" #include "usbg/usbg_internal.h" +#include "usbg/function/net.h" #include <malloc.h> #ifdef HAS_LIBCONFIG #include <libconfig.h> #endif -struct usbg_f_ether { +struct usbg_f_net { struct usbg_function func; }; -GENERIC_ALLOC_INST(ether, struct usbg_f_ether, func); +#define NET_DEC_ATTR(_name) \ + { \ + .name = #_name, \ + .ro = false, \ + .offset = offsetof(struct usbg_f_net_attrs, _name), \ + .get = usbg_get_dec, \ + .set = usbg_set_dec, \ + .import = usbg_get_config_node_int, \ + .export = usbg_set_config_node_int, \ + } + +#define NET_RO_STRING_ATTR(_name) \ + { \ + .name = #_name, \ + .ro = true, \ + .offset = offsetof(struct usbg_f_net_attrs, _name), \ + .get = usbg_get_string, \ + .export = usbg_set_config_node_string, \ + } + +#define NET_ETHER_ADDR_ATTR(_name) \ + { \ + .name = #_name, \ + .ro = false, \ + .offset = offsetof(struct usbg_f_net_attrs, _name), \ + .get = usbg_get_ether_addr, \ + .set = usbg_set_ether_addr, \ + .import = usbg_get_config_node_ether_addr, \ + .export = usbg_set_config_node_ether_addr, \ + } -GENERIC_FREE_INST(ether, struct usbg_f_ether, func); +static struct { + const char *name; + bool ro; + size_t offset; + usbg_attr_get_func get; + usbg_attr_set_func set; + usbg_import_node_func import; + usbg_export_node_func export; +} net_attr[USBG_F_NET_ATTR_MAX] = { + [USBG_F_NET_DEV_ADDR] = NET_ETHER_ADDR_ATTR(dev_addr), + [USBG_F_NET_HOST_ADDR] = NET_ETHER_ADDR_ATTR(host_addr), + [USBG_F_NET_IFNAME] = NET_RO_STRING_ATTR(ifname), + [USBG_F_NET_QMULT] = NET_DEC_ATTR(qmult), +}; + +#undef NET_DEC_ATTR +#undef NET_STRING_ATTR + +GENERIC_ALLOC_INST(ether, struct usbg_f_net, func); + +GENERIC_FREE_INST(ether, struct usbg_f_net, func); static int ether_set_attrs(struct usbg_function *f, const usbg_function_attrs *f_attrs) { int ret = USBG_SUCCESS; - char addr_buf[USBG_MAX_STR_LENGTH]; const usbg_f_net_attrs *attrs = &f_attrs->attrs.net; - 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); - 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); - ret = usbg_write_string(f->path, f->name, "host_addr", addr); - if (ret != USBG_SUCCESS) - goto out; + if (f_attrs->header.attrs_type && + f_attrs->header.attrs_type != USBG_F_ATTRS_NET) + return USBG_ERROR_INVALID_PARAM; - ret = usbg_write_dec(f->path, f->name, "qmult", attrs->qmult); + /* ifname is read only so we accept only empty string for this param */ + if (attrs->ifname && attrs->ifname[0]) + return USBG_ERROR_INVALID_PARAM; -out: - return ret; + return usbg_f_net_set_attrs(usbg_to_net_function(f), + (struct usbg_f_net_attrs *)attrs); } static int ether_get_attrs(struct usbg_function *f, usbg_function_attrs *f_attrs) { - struct ether_addr *addr; - struct ether_addr addr_buf; - char str_addr[USBG_MAX_STR_LENGTH]; + int ret; usbg_f_net_attrs *attrs = &f_attrs->attrs.net; - int ret = USBG_ERROR_INVALID_PARAM; - - 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); - if (addr) { - attrs->dev_addr = *addr; - } else { - ret = USBG_ERROR_IO; - goto out; - } - - ret = usbg_read_string(f->path, f->name, "host_addr", str_addr); - if (ret != USBG_SUCCESS) - goto out; - addr = ether_aton_r(str_addr, &addr_buf); - if (addr) { - attrs->host_addr = *addr; - } else { - ret = USBG_ERROR_IO; - goto out; - } - - ret = usbg_read_dec(f->path, f->name, "qmult", &(attrs->qmult)); + ret = usbg_f_net_get_attrs(usbg_to_net_function(f), + (struct usbg_f_net_attrs *)attrs); if (ret != USBG_SUCCESS) goto out; - ret = usbg_read_string_alloc(f->path, f->name, "ifname", - &(attrs->ifname)); - f_attrs->header.attrs_type = USBG_F_ATTRS_NET; out: return ret; @@ -113,103 +122,52 @@ static void ether_cleanup_attrs(struct usbg_function *f, static int ether_libconfig_import(struct usbg_function *f, config_setting_t *root) { - config_setting_t *node; - int ret = USBG_SUCCESS; - int qmult; - struct ether_addr *addr; - struct ether_addr addr_buf; - const char *str; - -#define GET_OPTIONAL_ADDR(NAME) \ - do { \ - node = config_setting_get_member(root, #NAME); \ - if (node) { \ - str = config_setting_get_string(node); \ - if (!str) { \ - ret = USBG_ERROR_INVALID_TYPE; \ - goto out; \ - } \ - \ - addr = ether_aton_r(str, &addr_buf); \ - if (!addr) { \ - ret = USBG_ERROR_INVALID_VALUE; \ - goto out; \ - } \ - ret = usbg_set_net_##NAME(f, addr); \ - if (ret != USBG_SUCCESS) \ - goto out; \ - } \ - } while (0) - - GET_OPTIONAL_ADDR(host_addr); - GET_OPTIONAL_ADDR(dev_addr); - -#undef GET_OPTIONAL_ADDR - - node = config_setting_get_member(root, "qmult"); - if (node) { - if (!usbg_config_is_int(node)) { - ret = USBG_ERROR_INVALID_TYPE; - goto out; - } - qmult = config_setting_get_int(node); - ret = usbg_set_net_qmult(f, qmult); + struct usbg_f_net *nf = usbg_to_net_function(f); + union usbg_f_net_attr_val val; + int i; + int ret = 0; + + for (i = USBG_F_NET_ATTR_MIN; i < USBG_F_NET_ATTR_MAX; ++i) { + if (net_attr[i].ro) + continue; + + ret = net_attr[i].import(root, net_attr[i].name, &val); + /* node not found */ + if (ret == 0) + continue; + /* error */ + if (ret < 0) + break; + + ret = usbg_f_net_set_attr_val(nf, i, val); + if (ret) + break; } -out: return ret; } static int ether_libconfig_export(struct usbg_function *f, config_setting_t *root) { - config_setting_t *node; - char *addr; - char addr_buf[USBG_MAX_STR_LENGTH]; - int cfg_ret, usbg_ret; - usbg_function_attrs f_attrs; - usbg_f_net_attrs *attrs = &f_attrs.attrs.net; - int ret = USBG_ERROR_NO_MEM; - - usbg_ret = ether_get_attrs(f, &f_attrs); - if (usbg_ret != USBG_SUCCESS) { - ret = usbg_ret; - goto out; - } - - node = config_setting_add(root, "dev_addr", CONFIG_TYPE_STRING); - if (!node) - goto cleanup; - - addr = usbg_ether_ntoa_r(&attrs->dev_addr, addr_buf); - cfg_ret = config_setting_set_string(node, addr); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto cleanup; + struct usbg_f_net *nf = usbg_to_net_function(f); + union usbg_f_net_attr_val val; + int i; + int ret = 0; + + for (i = USBG_F_NET_ATTR_MIN; i < USBG_F_NET_ATTR_MAX; ++i) { + if (net_attr[i].ro) + continue; + + ret = usbg_f_net_get_attr_val(nf, i, &val); + if (ret) + break; + + ret = net_attr[i].export(root, net_attr[i].name, &val); + if (ret) + break; } - node = config_setting_add(root, "host_addr", CONFIG_TYPE_STRING); - if (!node) - goto cleanup; - - addr = usbg_ether_ntoa_r(&attrs->host_addr, addr_buf); - cfg_ret = config_setting_set_string(node, addr); - if (cfg_ret != CONFIG_TRUE) { - ret = USBG_ERROR_OTHER_ERROR; - goto cleanup; - } - - node = config_setting_add(root, "qmult", CONFIG_TYPE_INT); - if (!node) - goto cleanup; - - cfg_ret = config_setting_set_int(node, attrs->qmult); - ret = cfg_ret == CONFIG_TRUE ? 0 : USBG_ERROR_OTHER_ERROR; - - /* ifname is read only so we don't export it */ -cleanup: - ether_cleanup_attrs(f, &f_attrs); -out: return ret; } @@ -256,3 +214,99 @@ struct usbg_function_type usbg_f_type_rndis = { ETHER_FUNCTION_OPTS }; +/* API implementation */ + +usbg_f_net *usbg_to_net_function(usbg_function *f) +{ + return f->ops == &usbg_f_type_ecm + || f->ops == &usbg_f_type_subset + || f->ops == &usbg_f_type_ncm + || f->ops == &usbg_f_type_eem + || f->ops == &usbg_f_type_rndis ? + container_of(f, struct usbg_f_net, func) : NULL; +} + +usbg_function *usbg_from_net_function(usbg_f_net *nf) +{ + return &nf->func; +} + +int usbg_f_net_get_attrs(usbg_f_net *nf, + struct usbg_f_net_attrs *attrs) +{ + int i; + int ret = 0; + + for (i = USBG_F_NET_ATTR_MIN; i < USBG_F_NET_ATTR_MAX; ++i) { + ret = usbg_f_net_get_attr_val(nf, i, + (union usbg_f_net_attr_val *) + ((char *)attrs + + net_attr[i].offset)); + if (ret) + break; + } + + return ret; + +} + +int usbg_f_net_set_attrs(usbg_f_net *nf, + const struct usbg_f_net_attrs *attrs) +{ + int i; + int ret = 0; + + for (i = USBG_F_NET_ATTR_MIN; i < USBG_F_NET_ATTR_MAX; ++i) { + if (net_attr[i].ro) + continue; + + ret = usbg_f_net_set_attr_val(nf, i, + *(union usbg_f_net_attr_val *) + ((char *)attrs + + net_attr[i].offset)); + if (ret) + break; + } + + return ret; + +} + +int usbg_f_net_get_attr_val(usbg_f_net *nf, enum usbg_f_net_attr attr, + union usbg_f_net_attr_val *val) +{ + return net_attr[attr].get(nf->func.path, nf->func.name, + net_attr[attr].name, val); +} + +int usbg_f_net_set_attr_val(usbg_f_net *nf, enum usbg_f_net_attr attr, + union usbg_f_net_attr_val val) +{ + return net_attr[attr].ro ? + USBG_ERROR_INVALID_PARAM : + net_attr[attr].set(nf->func.path, nf->func.name, + net_attr[attr].name, &val); +} + +int usbg_f_net_get_ifname_s(usbg_f_net *nf, char *buf, int len) +{ + struct usbg_function *f; + int ret; + + if (!nf || !buf) + return USBG_ERROR_INVALID_PARAM; + + f = &nf->func; + /* + * TODO: + * Rework usbg_common to make this function consistent with doc. + * This below is only an ugly hack + */ + ret = usbg_read_string_limited(f->path, f->name, "ifname", buf, len); + if (ret) + goto out; + + ret = strlen(buf); +out: + return ret; +} |