USB: gadget: added a saner gadget downloader registration API

Preprocessor definitions and hardcoded implementation selection in
g_dnl core were replaced by a linker list made of (usb_function_name,
bind_callback) pairs.

Signed-off-by: Mateusz Zalega <m.zalega@samsung.com>
Acked-by: Lukasz Majewski <l.majewski@samsung.com>
Acked-by: Marek Vasut <marex@denx.de>
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index de75ff1..1b1e179 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -24,6 +24,7 @@
 #include <linux/usb/composite.h>
 
 #include <dfu.h>
+#include <g_dnl.h>
 #include "f_dfu.h"
 
 struct f_dfu {
@@ -817,3 +818,5 @@
 
 	return dfu_bind_config(c);
 }
+
+DECLARE_GADGET_BIND_CALLBACK(usb_dnl_dfu, dfu_add);
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 4fae5cd..6374bb9 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -255,6 +255,7 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/composite.h>
 #include <usb/lin_gadget_compat.h>
+#include <g_dnl.h>
 
 /*------------------------------------------------------------------------*/
 
@@ -2778,3 +2779,5 @@
 
 	return 0;
 }
+
+DECLARE_GADGET_BIND_CALLBACK(usb_dnl_ums, fsg_add);
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index ba47945..feef9e4 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -1004,3 +1004,5 @@
 	debug("%s:\n", __func__);
 	return thor_func_init(c);
 }
+
+DECLARE_GADGET_BIND_CALLBACK(usb_dnl_thor, thor_add);
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index 973d737..743bae5 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -41,7 +41,6 @@
 
 #define DRIVER_VERSION		"usb_dnl 2.0"
 
-static const char shortname[] = "usb_dnl_";
 static const char product[] = "USB download gadget";
 static char g_dnl_serial[MAX_STRING_SERIAL];
 static const char manufacturer[] = CONFIG_G_DNL_MANUFACTURER;
@@ -96,29 +95,36 @@
 	free(cdev->config);
 	cdev->config = NULL;
 	debug("%s: calling usb_gadget_disconnect for "
-			"controller '%s'\n", shortname, gadget->name);
+			"controller '%s'\n", __func__, gadget->name);
 	usb_gadget_disconnect(gadget);
 
 	return 0;
 }
 
+static inline struct g_dnl_bind_callback *g_dnl_bind_callback_first(void)
+{
+	return ll_entry_start(struct g_dnl_bind_callback,
+				g_dnl_bind_callbacks);
+}
+
+static inline struct g_dnl_bind_callback *g_dnl_bind_callback_end(void)
+{
+	return ll_entry_end(struct g_dnl_bind_callback,
+				g_dnl_bind_callbacks);
+}
+
 static int g_dnl_do_config(struct usb_configuration *c)
 {
 	const char *s = c->cdev->driver->name;
-	int ret = -1;
+	struct g_dnl_bind_callback *callback = g_dnl_bind_callback_first();
 
 	debug("%s: configuration: 0x%p composite dev: 0x%p\n",
 	      __func__, c, c->cdev);
 
-	printf("GADGET DRIVER: %s\n", s);
-	if (!strcmp(s, "usb_dnl_dfu"))
-		ret = dfu_add(c);
-	else if (!strcmp(s, "usb_dnl_ums"))
-		ret = fsg_add(c);
-	else if (!strcmp(s, "usb_dnl_thor"))
-		ret = thor_add(c);
-
-	return ret;
+	for (; callback != g_dnl_bind_callback_end(); callback++)
+		if (!strcmp(s, callback->usb_function_name))
+			return callback->fptr(c);
+	return -ENODEV;
 }
 
 static int g_dnl_config_register(struct usb_composite_dev *cdev)
@@ -208,12 +214,12 @@
 		device_desc.bcdDevice = cpu_to_le16(gcnum);
 	else {
 		debug("%s: controller '%s' not recognized\n",
-			shortname, gadget->name);
+			__func__, gadget->name);
 		device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
 	}
 
 	debug("%s: calling usb_gadget_connect for "
-			"controller '%s'\n", shortname, gadget->name);
+			"controller '%s'\n", __func__, gadget->name);
 	usb_gadget_connect(gadget);
 
 	return 0;
@@ -232,36 +238,22 @@
 	.unbind = g_dnl_unbind,
 };
 
-int g_dnl_register(const char *type)
+/*
+ * NOTICE:
+ * Registering via USB function name won't be necessary after rewriting
+ * g_dnl to support multiple USB functions.
+ */
+int g_dnl_register(const char *name)
 {
-	/* The largest function name is 4 */
-	static char name[sizeof(shortname) + 4];
-	int ret;
+	int ret = usb_composite_register(&g_dnl_driver);
 
-	if (!strcmp(type, "dfu")) {
-		strcpy(name, shortname);
-		strcat(name, type);
-	} else if (!strcmp(type, "ums")) {
-		strcpy(name, shortname);
-		strcat(name, type);
-	} else if (!strcmp(type, "thor")) {
-		strcpy(name, shortname);
-		strcat(name, type);
-	} else {
-		printf("%s: unknown command: %s\n", __func__, type);
-		return -EINVAL;
-	}
-
+	debug("%s: g_dnl_driver.name = %s\n", __func__, name);
 	g_dnl_driver.name = name;
 
-	debug("%s: g_dnl_driver.name: %s\n", __func__, g_dnl_driver.name);
-	ret = usb_composite_register(&g_dnl_driver);
-
 	if (ret) {
 		printf("%s: failed!, error: %d\n", __func__, ret);
 		return ret;
 	}
-
 	return 0;
 }