[PATCH v2 10/16] libusbg: Add import function functionality

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Functions can be exported to file using usbg_export_function().
This commit adds complementary API function usbg_import_function()
which allows to import function from file to configfs.

Signed-off-by: Krzysztof Opasiak <k.opasiak@xxxxxxxxxxx>
---
 include/usbg/usbg.h |   13 ++++
 src/usbg.c          |  188 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 201 insertions(+)

diff --git a/include/usbg/usbg.h b/include/usbg/usbg.h
index 3d3cba0..5e75208 100644
--- a/include/usbg/usbg.h
+++ b/include/usbg/usbg.h
@@ -927,6 +927,19 @@ extern int usbg_export_config(usbg_config *c, FILE *stream);
 extern int usbg_export_gadget(usbg_gadget *g, FILE *stream);
 
 /**
+
+/**
+ * @brief Imports usb function from file and adds it to given gadget
+ * @param g Gadget where function should be placed
+ * @param stream from which function should be imported
+ * @param instance name which shuld be used for new function
+ * @param f place for pointer to imported function
+ * if NULL this param will be ignored.
+ * @return 0 on success, usbg_error otherwise
+ */
+extern int usbg_import_function(usbg_gadget *g, FILE *stream,
+				const char *instance, usbg_function **f);
+
  * @}
  */
 #endif /* __USBG_H__ */
diff --git a/src/usbg.c b/src/usbg.c
index 929f1c7..a6c9fdf 100644
--- a/src/usbg.c
+++ b/src/usbg.c
@@ -3255,3 +3255,191 @@ out:
 	config_destroy(&cfg);
 	return ret;
 }
+
+#define usbg_config_is_int(node) (config_setting_type(node) == CONFIG_TYPE_INT)
+#define usbg_config_is_string(node) \
+	(config_setting_type(node) == CONFIG_TYPE_STRING)
+
+static void usbg_set_failed_import(config_t **to_set, config_t *failed)
+{
+	if (*to_set != NULL) {
+		config_destroy(*to_set);
+		free(*to_set);
+	}
+
+	*to_set = failed;
+}
+
+static int usbg_import_f_net_attrs(config_setting_t *root, usbg_function *f)
+{
+	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);
+	}
+
+out:
+	return ret;
+}
+
+static int usbg_import_function_attrs(config_setting_t *root, usbg_function *f)
+{
+	int ret = USBG_SUCCESS;
+
+	switch (f->type) {
+	case F_SERIAL:
+	case F_ACM:
+	case F_OBEX:
+		/* Don't import port_num because it is read only */
+		break;
+	case F_ECM:
+	case F_SUBSET:
+	case F_NCM:
+	case F_EEM:
+	case F_RNDIS:
+		ret = usbg_import_f_net_attrs(root, f);
+		break;
+	case F_PHONET:
+		/* Don't import ifname because it is read only */
+		break;
+	case F_FFS:
+		/* We don't need to export ffs attributes
+		 * due to instance name export */
+		break;
+	default:
+		ERROR("Unsupported function type\n");
+		ret = USBG_ERROR_NOT_SUPPORTED;
+	}
+
+	return ret;
+}
+
+static int usbg_import_function_run(usbg_gadget *g, config_setting_t *root,
+				    const char *instance, usbg_function **f)
+{
+	config_setting_t *node;
+	const char *type_str;
+	int usbg_ret;
+	int function_type;
+	int ret = USBG_ERROR_MISSING_TAG;
+
+	/* function type is mandatory */
+	node = config_setting_get_member(root, USBG_TYPE_TAG);
+	if (!node)
+		goto out;
+
+	type_str = config_setting_get_string(node);
+	if (!type_str) {
+		ret = USBG_ERROR_INVALID_TYPE;
+		goto out;
+	}
+
+	/* Check if this type is supported */
+	function_type = usbg_lookup_function_type(type_str);
+	if (function_type < 0) {
+		ret = USBG_ERROR_NOT_SUPPORTED;
+		goto out;
+	}
+
+	/* All data collected, let's get to work and create this function */
+	ret = usbg_create_function(g, (usbg_function_type)function_type,
+				   instance, NULL, f);
+
+	if (ret != USBG_SUCCESS)
+		goto out;
+
+	/* Attrs are optional */
+	node = config_setting_get_member(root, USBG_ATTRS_TAG);
+	if (node) {
+		usbg_ret = usbg_import_function_attrs(node, *f);
+		if (usbg_ret != USBG_SUCCESS) {
+			ret = usbg_ret;
+			goto out;
+		}
+	}
+out:
+	return ret;
+}
+
+int usbg_import_function(usbg_gadget *g, FILE *stream, const char *instance,
+			 usbg_function **f)
+{
+	config_t *cfg;
+	config_setting_t *root;
+	usbg_function *newf;
+	int ret, cfg_ret;
+
+	if (!g || !stream || !instance)
+		return USBG_ERROR_INVALID_PARAM;
+
+	cfg = malloc(sizeof(*cfg));
+	if (!cfg)
+		return USBG_ERROR_NO_MEM;
+
+	config_init(cfg);
+
+	cfg_ret = config_read(cfg, stream);
+	if (cfg_ret != CONFIG_TRUE) {
+		usbg_set_failed_import(&g->last_failed_import, cfg);
+		ret = USBG_ERROR_INVALID_FORMAT;
+		goto out;
+	}
+
+	/* Allways successful */
+	root = config_root_setting(cfg);
+
+	ret = usbg_import_function_run(g, root, instance, &newf);
+	if (ret != USBG_SUCCESS) {
+		usbg_set_failed_import(&g->last_failed_import, cfg);
+		goto out;
+	}
+
+	if (f)
+		*f = newf;
+
+	config_destroy(cfg);
+	free(cfg);
+	/* Clean last error */
+	usbg_set_failed_import(&g->last_failed_import, NULL);
+out:
+	return ret;
+
+}
+
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux