Patchwork [U-Boot,9/9] USB: gadget: added a saner gadget downloader registration API

login
register
mail settings
Submitter Mateusz Zalega
Date Jan. 9, 2014, 2:31 p.m.
Message ID <1389277919-15279-9-git-send-email-m.zalega@samsung.com>
Download mbox | patch
Permalink /patch/308828/
State Changes Requested
Delegated to: Minkyu Kang
Headers show

Comments

Mateusz Zalega - Jan. 9, 2014, 2:31 p.m.
Preprocessor definitions and hardcoded implementation selection in
g_dnl core were replaced by a linker list made of {usb_function_name,
bind_callback) pairs.

Change-Id: I4e0515e7fd61ff19793e9ac9a6c48b07c616c9dc
Signed-off-by: Mateusz Zalega <m.zalega@samsung.com>
Cc: Lukasz Majewski <l.majewski@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
---
 common/cmd_dfu.c                    |  3 +-
 common/cmd_thordown.c               |  3 +-
 common/cmd_usb_mass_storage.c       |  2 +-
 drivers/usb/gadget/f_dfu.c          | 11 ++++--
 drivers/usb/gadget/f_mass_storage.c |  6 +++
 drivers/usb/gadget/f_thor.c         |  5 +++
 drivers/usb/gadget/g_dnl.c          | 74 +++++++++++++++++--------------------
 include/dfu.h                       |  7 ----
 include/g_dnl.h                     | 11 ++++++
 include/thor.h                      |  8 ----
 include/usb_mass_storage.h          |  8 ----
 11 files changed, 66 insertions(+), 72 deletions(-)
Łukasz Majewski - Jan. 10, 2014, 8:23 a.m.
Hi Heiko,

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

Could you test those g_dnl related patches?

You would probably need to apply the whole series for testing.

Thanks in advance.

Regards,
Lukasz

> 
> Change-Id: I4e0515e7fd61ff19793e9ac9a6c48b07c616c9dc
> Signed-off-by: Mateusz Zalega <m.zalega@samsung.com>
> Cc: Lukasz Majewski <l.majewski@samsung.com>
> Cc: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  common/cmd_dfu.c                    |  3 +-
>  common/cmd_thordown.c               |  3 +-
>  common/cmd_usb_mass_storage.c       |  2 +-
>  drivers/usb/gadget/f_dfu.c          | 11 ++++--
>  drivers/usb/gadget/f_mass_storage.c |  6 +++
>  drivers/usb/gadget/f_thor.c         |  5 +++
>  drivers/usb/gadget/g_dnl.c          | 74
> +++++++++++++++++--------------------
> include/dfu.h                       |  7 ----
> include/g_dnl.h                     | 11 ++++++
> include/thor.h                      |  8 ----
> include/usb_mass_storage.h          |  8 ---- 11 files changed, 66
> insertions(+), 72 deletions(-)
> 
> diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
> index 5547678..a03538d 100644
> --- a/common/cmd_dfu.c
> +++ b/common/cmd_dfu.c
> @@ -22,7 +22,6 @@ static int do_dfu(cmd_tbl_t *cmdtp, int flag, int
> argc, char * const argv[]) char *interface = argv[2];
>  	char *devstring = argv[3];
>  
> -	char *s = "dfu";
>  	int ret, i = 0;
>  
>  	ret = dfu_init_env_entities(interface,
> simple_strtoul(devstring, @@ -38,7 +37,7 @@ static int
> do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int
> controller_index = simple_strtoul(usb_controller, NULL, 0);
> board_usb_init(controller_index, USB_INIT_DEVICE); 
> -	g_dnl_register(s);
> +	g_dnl_register("usb_dnl_dfu");
>  	while (1) {
>  		if (dfu_reset())
>  			/*
> diff --git a/common/cmd_thordown.c b/common/cmd_thordown.c
> index c4b3511..2dd7509 100644
> --- a/common/cmd_thordown.c
> +++ b/common/cmd_thordown.c
> @@ -22,7 +22,6 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int
> argc, char * const argv[]) char *interface = argv[2];
>  	char *devstring = argv[3];
>  
> -	const char *s = "thor";
>  	int ret;
>  
>  	puts("TIZEN \"THOR\" Downloader\n");
> @@ -40,7 +39,7 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int
> argc, char * const argv[]) goto exit;
>  	}
>  
> -	g_dnl_register(s);
> +	g_dnl_register("usb_dnl_thor");
>  
>  	ret = thor_init();
>  	if (ret) {
> diff --git a/common/cmd_usb_mass_storage.c
> b/common/cmd_usb_mass_storage.c index 99487f4..c8e152c 100644
> --- a/common/cmd_usb_mass_storage.c
> +++ b/common/cmd_usb_mass_storage.c
> @@ -40,7 +40,7 @@ int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag,
>  		return CMD_RET_FAILURE;
>  	}
>  
> -	g_dnl_register("ums");
> +	g_dnl_register("usb_dnl_ums");
>  
>  	while (1) {
>  		usb_gadget_handle_interrupts();
> diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
> index a045864..cde1895 100644
> --- a/drivers/usb/gadget/f_dfu.c
> +++ b/drivers/usb/gadget/f_dfu.c
> @@ -18,12 +18,14 @@
>  #include <errno.h>
>  #include <common.h>
>  #include <malloc.h>
> +#include <linker_lists.h>
>  
>  #include <linux/usb/ch9.h>
>  #include <linux/usb/gadget.h>
>  #include <linux/usb/composite.h>
>  
>  #include <dfu.h>
> +#include <g_dnl.h>
>  #include "f_dfu.h"
>  
>  struct f_dfu {
> @@ -768,9 +770,7 @@ static int dfu_bind_config(struct
> usb_configuration *c) 
>  int dfu_add(struct usb_configuration *c)
>  {
> -	int id;
> -
> -	id = usb_string_id(c->cdev);
> +	int id = usb_string_id(c->cdev);
>  	if (id < 0)
>  		return id;
>  	strings_dfu_generic[0].id = id;
> @@ -781,3 +781,8 @@ int dfu_add(struct usb_configuration *c)
>  
>  	return dfu_bind_config(c);
>  }
> +
> +/* export dfu_add to g_dnl.o */
> +ll_entry_declare(struct g_dnl_bind_callback, dfu_bind_callback,
> +		g_dnl_bind_callbacks) = { .usb_function_name =
> "usb_dnl_dfu",
> +					  .fptr = dfu_add };
> diff --git a/drivers/usb/gadget/f_mass_storage.c
> b/drivers/usb/gadget/f_mass_storage.c index b1fe8bd..b7d03f2 100644
> --- a/drivers/usb/gadget/f_mass_storage.c
> +++ b/drivers/usb/gadget/f_mass_storage.c
> @@ -243,6 +243,7 @@
>  #include <config.h>
>  #include <malloc.h>
>  #include <common.h>
> +#include <linker_lists.h>
>  #include <usb.h>
>  
>  #include <linux/err.h>
> @@ -255,6 +256,7 @@
>  #include <linux/usb/gadget.h>
>  #include <linux/usb/composite.h>
>  #include <usb/lin_gadget_compat.h>
> +#include <g_dnl.h>
>  
>  /*------------------------------------------------------------------------*/
>  
> @@ -2778,3 +2780,7 @@ int fsg_init(struct ums *ums_dev)
>  
>  	return 0;
>  }
> +
> +ll_entry_declare(struct g_dnl_bind_callback, fsg_bind_callback,
> +		g_dnl_bind_callbacks) = { .usb_function_name =
> "usb_dnl_ums",
> +					  .fptr = fsg_add };
> diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
> index c4c9909..3f428c8 100644
> --- a/drivers/usb/gadget/f_thor.c
> +++ b/drivers/usb/gadget/f_thor.c
> @@ -17,6 +17,7 @@
>  
>  #include <errno.h>
>  #include <common.h>
> +#include <linker_lists.h>
>  #include <malloc.h>
>  #include <version.h>
>  #include <linux/usb/ch9.h>
> @@ -1001,3 +1002,7 @@ int thor_add(struct usb_configuration *c)
>  	debug("%s:\n", __func__);
>  	return thor_func_init(c);
>  }
> +
> +ll_entry_declare(struct g_dnl_bind_callback, thor_bind_callback,
> +		g_dnl_bind_callbacks) = { .usb_function_name =
> "usb_dnl_thor",
> +					  .fptr = thor_add };
> diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
> index dd95afe..00ace2c 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;
> @@ -95,30 +94,38 @@ static int g_dnl_unbind(struct usb_composite_dev
> *cdev) 
>  	free(cdev->config);
>  	cdev->config = NULL;
> -	debug("%s: calling usb_gadget_disconnect for "
> -			"controller '%s'\n", shortname,
> gadget->name);
> +	debug("%s: calling usb_gadget_disconnect for controller
> '%s'\n",
> +			__func__, gadget->name);
>  	usb_gadget_disconnect(gadget);
>  
>  	return 0;
>  }
>  
> +static inline struct g_dnl_bind_callback *
> g_dnl_first_bind_callback(void) +{
> +	return ll_entry_start(struct g_dnl_bind_callback,
> +				g_dnl_bind_callbacks);
> +}
> +
> +static inline struct g_dnl_bind_callback *
> g_dnl_last_bind_callback(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;
>  
>  	debug("%s: configuration: 0x%p composite dev: 0x%p\n",
> -	      __func__, c, c->cdev);
> -
> +			__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;
> +
> +	struct g_dnl_bind_callback *callback =
> g_dnl_first_bind_callback();
> +	for (; callback != g_dnl_last_bind_callback(); ++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)
> @@ -203,12 +210,12 @@ static int g_dnl_bind(struct usb_composite_dev
> *cdev) 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);
> +	debug("%s: calling usb_gadget_connect for controller '%s'\n",
> +			__func__, gadget->name);
>  	usb_gadget_connect(gadget);
>  
>  	return 0;
> @@ -227,36 +234,21 @@ static struct usb_composite_driver g_dnl_driver
> = { .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;
> -
> -	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);
> -
> +	int ret = usb_composite_register(&g_dnl_driver);
>  	if (ret) {
> -		printf("%s: failed!, error: %d\n", __func__, ret);
> +		debug("%s: failed!, error: %d\n", __func__, ret);
>  		return ret;
>  	}
> -
>  	return 0;
>  }
>  
> diff --git a/include/dfu.h b/include/dfu.h
> index f2e83db..6fd75d0 100644
> --- a/include/dfu.h
> +++ b/include/dfu.h
> @@ -164,12 +164,5 @@ static inline int dfu_fill_entity_ram(struct
> dfu_entity *dfu, char *s) }
>  #endif
>  
> -#ifdef CONFIG_DFU_FUNCTION
>  int dfu_add(struct usb_configuration *c);
> -#else
> -int dfu_add(struct usb_configuration *c)
> -{
> -	return 0;
> -}
> -#endif
>  #endif /* __DFU_ENTITY_H_ */
> diff --git a/include/g_dnl.h b/include/g_dnl.h
> index 8f813c2..4392f76 100644
> --- a/include/g_dnl.h
> +++ b/include/g_dnl.h
> @@ -10,6 +10,17 @@
>  
>  #include <linux/usb/ch9.h>
>  #include <linux/usb/gadget.h>
> +#include <linux/usb/composite.h>
> +
> +typedef int (*g_dnl_bind_callback_f)(struct usb_configuration *);
> +
> +/* used in Gadget downloader callback linker list */
> +struct g_dnl_bind_callback
> +{
> +	const char *usb_function_name;
> +	g_dnl_bind_callback_f fptr;
> +};
> +
>  int g_dnl_bind_fixup(struct usb_device_descriptor *, const char *);
>  int g_dnl_register(const char *s);
>  void g_dnl_unregister(void);
> diff --git a/include/thor.h b/include/thor.h
> index afeade4..5051be7 100644
> --- a/include/thor.h
> +++ b/include/thor.h
> @@ -15,13 +15,5 @@
>  
>  int thor_handle(void);
>  int thor_init(void);
> -
> -#ifdef CONFIG_THOR_FUNCTION
>  int thor_add(struct usb_configuration *c);
> -#else
> -int thor_add(struct usb_configuration *c)
> -{
> -	return 0;
> -}
> -#endif
>  #endif /* __THOR_H_ */
> diff --git a/include/usb_mass_storage.h b/include/usb_mass_storage.h
> index 9df3adc..6ee4f34 100644
> --- a/include/usb_mass_storage.h
> +++ b/include/usb_mass_storage.h
> @@ -37,13 +37,5 @@ int fsg_init(struct ums *);
>  void fsg_cleanup(void);
>  struct ums *ums_init(unsigned int);
>  int fsg_main_thread(void *);
> -
> -#ifdef CONFIG_USB_GADGET_MASS_STORAGE
>  int fsg_add(struct usb_configuration *c);
> -#else
> -int fsg_add(struct usb_configuration *c)
> -{
> -	return 0;
> -}
> -#endif
>  #endif /* __USB_MASS_STORAGE_H__ */
Heiko Schocher - Jan. 13, 2014, 7:07 a.m.
Hello Lukasz,

Am 10.01.2014 09:23, schrieb Lukasz Majewski:
> Hi Heiko,
>
>> Preprocessor definitions and hardcoded implementation selection in
>> g_dnl core were replaced by a linker list made of {usb_function_name,
>> bind_callback) pairs.
>
> Could you test those g_dnl related patches?
>
> You would probably need to apply the whole series for testing.

I applied the hole series on current top of tree and tried dfu
download for the rootfs nand mtd partition on the siemens dxr2
board. Test looks good, so:

Tested-by: Heiko Schocher<hs@denx.de>

bye,
Heiko
Łukasz Majewski - Jan. 13, 2014, 10:16 a.m.
Hi Mateusz,

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


Tested-by: Lukasz Majewski <l.majewski@samsung.com>

Tested at: Exynos4210 - TRATS.

Acked-by: Lukasz Majewski <l.majewski@samsung.com>

> 
> Change-Id: I4e0515e7fd61ff19793e9ac9a6c48b07c616c9dc
> Signed-off-by: Mateusz Zalega <m.zalega@samsung.com>
> Cc: Lukasz Majewski <l.majewski@samsung.com>
> Cc: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  common/cmd_dfu.c                    |  3 +-
>  common/cmd_thordown.c               |  3 +-
>  common/cmd_usb_mass_storage.c       |  2 +-
>  drivers/usb/gadget/f_dfu.c          | 11 ++++--
>  drivers/usb/gadget/f_mass_storage.c |  6 +++
>  drivers/usb/gadget/f_thor.c         |  5 +++
>  drivers/usb/gadget/g_dnl.c          | 74
> +++++++++++++++++--------------------
> include/dfu.h                       |  7 ----
> include/g_dnl.h                     | 11 ++++++
> include/thor.h                      |  8 ----
> include/usb_mass_storage.h          |  8 ---- 11 files changed, 66
> insertions(+), 72 deletions(-)
> 
> diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
> index 5547678..a03538d 100644
> --- a/common/cmd_dfu.c
> +++ b/common/cmd_dfu.c
> @@ -22,7 +22,6 @@ static int do_dfu(cmd_tbl_t *cmdtp, int flag, int
> argc, char * const argv[]) char *interface = argv[2];
>  	char *devstring = argv[3];
>  
> -	char *s = "dfu";
>  	int ret, i = 0;
>  
>  	ret = dfu_init_env_entities(interface,
> simple_strtoul(devstring, @@ -38,7 +37,7 @@ static int
> do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int
> controller_index = simple_strtoul(usb_controller, NULL, 0);
> board_usb_init(controller_index, USB_INIT_DEVICE); 
> -	g_dnl_register(s);
> +	g_dnl_register("usb_dnl_dfu");
>  	while (1) {
>  		if (dfu_reset())
>  			/*
> diff --git a/common/cmd_thordown.c b/common/cmd_thordown.c
> index c4b3511..2dd7509 100644
> --- a/common/cmd_thordown.c
> +++ b/common/cmd_thordown.c
> @@ -22,7 +22,6 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int
> argc, char * const argv[]) char *interface = argv[2];
>  	char *devstring = argv[3];
>  
> -	const char *s = "thor";
>  	int ret;
>  
>  	puts("TIZEN \"THOR\" Downloader\n");
> @@ -40,7 +39,7 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int
> argc, char * const argv[]) goto exit;
>  	}
>  
> -	g_dnl_register(s);
> +	g_dnl_register("usb_dnl_thor");
>  
>  	ret = thor_init();
>  	if (ret) {
> diff --git a/common/cmd_usb_mass_storage.c
> b/common/cmd_usb_mass_storage.c index 99487f4..c8e152c 100644
> --- a/common/cmd_usb_mass_storage.c
> +++ b/common/cmd_usb_mass_storage.c
> @@ -40,7 +40,7 @@ int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag,
>  		return CMD_RET_FAILURE;
>  	}
>  
> -	g_dnl_register("ums");
> +	g_dnl_register("usb_dnl_ums");
>  
>  	while (1) {
>  		usb_gadget_handle_interrupts();
> diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
> index a045864..cde1895 100644
> --- a/drivers/usb/gadget/f_dfu.c
> +++ b/drivers/usb/gadget/f_dfu.c
> @@ -18,12 +18,14 @@
>  #include <errno.h>
>  #include <common.h>
>  #include <malloc.h>
> +#include <linker_lists.h>
>  
>  #include <linux/usb/ch9.h>
>  #include <linux/usb/gadget.h>
>  #include <linux/usb/composite.h>
>  
>  #include <dfu.h>
> +#include <g_dnl.h>
>  #include "f_dfu.h"
>  
>  struct f_dfu {
> @@ -768,9 +770,7 @@ static int dfu_bind_config(struct
> usb_configuration *c) 
>  int dfu_add(struct usb_configuration *c)
>  {
> -	int id;
> -
> -	id = usb_string_id(c->cdev);
> +	int id = usb_string_id(c->cdev);
>  	if (id < 0)
>  		return id;
>  	strings_dfu_generic[0].id = id;
> @@ -781,3 +781,8 @@ int dfu_add(struct usb_configuration *c)
>  
>  	return dfu_bind_config(c);
>  }
> +
> +/* export dfu_add to g_dnl.o */
> +ll_entry_declare(struct g_dnl_bind_callback, dfu_bind_callback,
> +		g_dnl_bind_callbacks) = { .usb_function_name =
> "usb_dnl_dfu",
> +					  .fptr = dfu_add };
> diff --git a/drivers/usb/gadget/f_mass_storage.c
> b/drivers/usb/gadget/f_mass_storage.c index b1fe8bd..b7d03f2 100644
> --- a/drivers/usb/gadget/f_mass_storage.c
> +++ b/drivers/usb/gadget/f_mass_storage.c
> @@ -243,6 +243,7 @@
>  #include <config.h>
>  #include <malloc.h>
>  #include <common.h>
> +#include <linker_lists.h>
>  #include <usb.h>
>  
>  #include <linux/err.h>
> @@ -255,6 +256,7 @@
>  #include <linux/usb/gadget.h>
>  #include <linux/usb/composite.h>
>  #include <usb/lin_gadget_compat.h>
> +#include <g_dnl.h>
>  
>  /*------------------------------------------------------------------------*/
>  
> @@ -2778,3 +2780,7 @@ int fsg_init(struct ums *ums_dev)
>  
>  	return 0;
>  }
> +
> +ll_entry_declare(struct g_dnl_bind_callback, fsg_bind_callback,
> +		g_dnl_bind_callbacks) = { .usb_function_name =
> "usb_dnl_ums",
> +					  .fptr = fsg_add };
> diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
> index c4c9909..3f428c8 100644
> --- a/drivers/usb/gadget/f_thor.c
> +++ b/drivers/usb/gadget/f_thor.c
> @@ -17,6 +17,7 @@
>  
>  #include <errno.h>
>  #include <common.h>
> +#include <linker_lists.h>
>  #include <malloc.h>
>  #include <version.h>
>  #include <linux/usb/ch9.h>
> @@ -1001,3 +1002,7 @@ int thor_add(struct usb_configuration *c)
>  	debug("%s:\n", __func__);
>  	return thor_func_init(c);
>  }
> +
> +ll_entry_declare(struct g_dnl_bind_callback, thor_bind_callback,
> +		g_dnl_bind_callbacks) = { .usb_function_name =
> "usb_dnl_thor",
> +					  .fptr = thor_add };
> diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
> index dd95afe..00ace2c 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;
> @@ -95,30 +94,38 @@ static int g_dnl_unbind(struct usb_composite_dev
> *cdev) 
>  	free(cdev->config);
>  	cdev->config = NULL;
> -	debug("%s: calling usb_gadget_disconnect for "
> -			"controller '%s'\n", shortname,
> gadget->name);
> +	debug("%s: calling usb_gadget_disconnect for controller
> '%s'\n",
> +			__func__, gadget->name);
>  	usb_gadget_disconnect(gadget);
>  
>  	return 0;
>  }
>  
> +static inline struct g_dnl_bind_callback *
> g_dnl_first_bind_callback(void) +{
> +	return ll_entry_start(struct g_dnl_bind_callback,
> +				g_dnl_bind_callbacks);
> +}
> +
> +static inline struct g_dnl_bind_callback *
> g_dnl_last_bind_callback(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;
>  
>  	debug("%s: configuration: 0x%p composite dev: 0x%p\n",
> -	      __func__, c, c->cdev);
> -
> +			__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;
> +
> +	struct g_dnl_bind_callback *callback =
> g_dnl_first_bind_callback();
> +	for (; callback != g_dnl_last_bind_callback(); ++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)
> @@ -203,12 +210,12 @@ static int g_dnl_bind(struct usb_composite_dev
> *cdev) 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);
> +	debug("%s: calling usb_gadget_connect for controller '%s'\n",
> +			__func__, gadget->name);
>  	usb_gadget_connect(gadget);
>  
>  	return 0;
> @@ -227,36 +234,21 @@ static struct usb_composite_driver g_dnl_driver
> = { .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;
> -
> -	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);
> -
> +	int ret = usb_composite_register(&g_dnl_driver);
>  	if (ret) {
> -		printf("%s: failed!, error: %d\n", __func__, ret);
> +		debug("%s: failed!, error: %d\n", __func__, ret);
>  		return ret;
>  	}
> -
>  	return 0;
>  }
>  
> diff --git a/include/dfu.h b/include/dfu.h
> index f2e83db..6fd75d0 100644
> --- a/include/dfu.h
> +++ b/include/dfu.h
> @@ -164,12 +164,5 @@ static inline int dfu_fill_entity_ram(struct
> dfu_entity *dfu, char *s) }
>  #endif
>  
> -#ifdef CONFIG_DFU_FUNCTION
>  int dfu_add(struct usb_configuration *c);
> -#else
> -int dfu_add(struct usb_configuration *c)
> -{
> -	return 0;
> -}
> -#endif
>  #endif /* __DFU_ENTITY_H_ */
> diff --git a/include/g_dnl.h b/include/g_dnl.h
> index 8f813c2..4392f76 100644
> --- a/include/g_dnl.h
> +++ b/include/g_dnl.h
> @@ -10,6 +10,17 @@
>  
>  #include <linux/usb/ch9.h>
>  #include <linux/usb/gadget.h>
> +#include <linux/usb/composite.h>
> +
> +typedef int (*g_dnl_bind_callback_f)(struct usb_configuration *);
> +
> +/* used in Gadget downloader callback linker list */
> +struct g_dnl_bind_callback
> +{
> +	const char *usb_function_name;
> +	g_dnl_bind_callback_f fptr;
> +};
> +
>  int g_dnl_bind_fixup(struct usb_device_descriptor *, const char *);
>  int g_dnl_register(const char *s);
>  void g_dnl_unregister(void);
> diff --git a/include/thor.h b/include/thor.h
> index afeade4..5051be7 100644
> --- a/include/thor.h
> +++ b/include/thor.h
> @@ -15,13 +15,5 @@
>  
>  int thor_handle(void);
>  int thor_init(void);
> -
> -#ifdef CONFIG_THOR_FUNCTION
>  int thor_add(struct usb_configuration *c);
> -#else
> -int thor_add(struct usb_configuration *c)
> -{
> -	return 0;
> -}
> -#endif
>  #endif /* __THOR_H_ */
> diff --git a/include/usb_mass_storage.h b/include/usb_mass_storage.h
> index 9df3adc..6ee4f34 100644
> --- a/include/usb_mass_storage.h
> +++ b/include/usb_mass_storage.h
> @@ -37,13 +37,5 @@ int fsg_init(struct ums *);
>  void fsg_cleanup(void);
>  struct ums *ums_init(unsigned int);
>  int fsg_main_thread(void *);
> -
> -#ifdef CONFIG_USB_GADGET_MASS_STORAGE
>  int fsg_add(struct usb_configuration *c);
> -#else
> -int fsg_add(struct usb_configuration *c)
> -{
> -	return 0;
> -}
> -#endif
>  #endif /* __USB_MASS_STORAGE_H__ */

Patch

diff --git a/common/cmd_dfu.c b/common/cmd_dfu.c
index 5547678..a03538d 100644
--- a/common/cmd_dfu.c
+++ b/common/cmd_dfu.c
@@ -22,7 +22,6 @@  static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	char *interface = argv[2];
 	char *devstring = argv[3];
 
-	char *s = "dfu";
 	int ret, i = 0;
 
 	ret = dfu_init_env_entities(interface, simple_strtoul(devstring,
@@ -38,7 +37,7 @@  static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	int controller_index = simple_strtoul(usb_controller, NULL, 0);
 	board_usb_init(controller_index, USB_INIT_DEVICE);
 
-	g_dnl_register(s);
+	g_dnl_register("usb_dnl_dfu");
 	while (1) {
 		if (dfu_reset())
 			/*
diff --git a/common/cmd_thordown.c b/common/cmd_thordown.c
index c4b3511..2dd7509 100644
--- a/common/cmd_thordown.c
+++ b/common/cmd_thordown.c
@@ -22,7 +22,6 @@  int do_thor_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	char *interface = argv[2];
 	char *devstring = argv[3];
 
-	const char *s = "thor";
 	int ret;
 
 	puts("TIZEN \"THOR\" Downloader\n");
@@ -40,7 +39,7 @@  int do_thor_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		goto exit;
 	}
 
-	g_dnl_register(s);
+	g_dnl_register("usb_dnl_thor");
 
 	ret = thor_init();
 	if (ret) {
diff --git a/common/cmd_usb_mass_storage.c b/common/cmd_usb_mass_storage.c
index 99487f4..c8e152c 100644
--- a/common/cmd_usb_mass_storage.c
+++ b/common/cmd_usb_mass_storage.c
@@ -40,7 +40,7 @@  int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag,
 		return CMD_RET_FAILURE;
 	}
 
-	g_dnl_register("ums");
+	g_dnl_register("usb_dnl_ums");
 
 	while (1) {
 		usb_gadget_handle_interrupts();
diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c
index a045864..cde1895 100644
--- a/drivers/usb/gadget/f_dfu.c
+++ b/drivers/usb/gadget/f_dfu.c
@@ -18,12 +18,14 @@ 
 #include <errno.h>
 #include <common.h>
 #include <malloc.h>
+#include <linker_lists.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/composite.h>
 
 #include <dfu.h>
+#include <g_dnl.h>
 #include "f_dfu.h"
 
 struct f_dfu {
@@ -768,9 +770,7 @@  static int dfu_bind_config(struct usb_configuration *c)
 
 int dfu_add(struct usb_configuration *c)
 {
-	int id;
-
-	id = usb_string_id(c->cdev);
+	int id = usb_string_id(c->cdev);
 	if (id < 0)
 		return id;
 	strings_dfu_generic[0].id = id;
@@ -781,3 +781,8 @@  int dfu_add(struct usb_configuration *c)
 
 	return dfu_bind_config(c);
 }
+
+/* export dfu_add to g_dnl.o */
+ll_entry_declare(struct g_dnl_bind_callback, dfu_bind_callback,
+		g_dnl_bind_callbacks) = { .usb_function_name = "usb_dnl_dfu",
+					  .fptr = dfu_add };
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index b1fe8bd..b7d03f2 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -243,6 +243,7 @@ 
 #include <config.h>
 #include <malloc.h>
 #include <common.h>
+#include <linker_lists.h>
 #include <usb.h>
 
 #include <linux/err.h>
@@ -255,6 +256,7 @@ 
 #include <linux/usb/gadget.h>
 #include <linux/usb/composite.h>
 #include <usb/lin_gadget_compat.h>
+#include <g_dnl.h>
 
 /*------------------------------------------------------------------------*/
 
@@ -2778,3 +2780,7 @@  int fsg_init(struct ums *ums_dev)
 
 	return 0;
 }
+
+ll_entry_declare(struct g_dnl_bind_callback, fsg_bind_callback,
+		g_dnl_bind_callbacks) = { .usb_function_name = "usb_dnl_ums",
+					  .fptr = fsg_add };
diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c
index c4c9909..3f428c8 100644
--- a/drivers/usb/gadget/f_thor.c
+++ b/drivers/usb/gadget/f_thor.c
@@ -17,6 +17,7 @@ 
 
 #include <errno.h>
 #include <common.h>
+#include <linker_lists.h>
 #include <malloc.h>
 #include <version.h>
 #include <linux/usb/ch9.h>
@@ -1001,3 +1002,7 @@  int thor_add(struct usb_configuration *c)
 	debug("%s:\n", __func__);
 	return thor_func_init(c);
 }
+
+ll_entry_declare(struct g_dnl_bind_callback, thor_bind_callback,
+		g_dnl_bind_callbacks) = { .usb_function_name = "usb_dnl_thor",
+					  .fptr = thor_add };
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index dd95afe..00ace2c 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;
@@ -95,30 +94,38 @@  static int g_dnl_unbind(struct usb_composite_dev *cdev)
 
 	free(cdev->config);
 	cdev->config = NULL;
-	debug("%s: calling usb_gadget_disconnect for "
-			"controller '%s'\n", shortname, gadget->name);
+	debug("%s: calling usb_gadget_disconnect for controller '%s'\n",
+			__func__, gadget->name);
 	usb_gadget_disconnect(gadget);
 
 	return 0;
 }
 
+static inline struct g_dnl_bind_callback * g_dnl_first_bind_callback(void)
+{
+	return ll_entry_start(struct g_dnl_bind_callback,
+				g_dnl_bind_callbacks);
+}
+
+static inline struct g_dnl_bind_callback * g_dnl_last_bind_callback(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;
 
 	debug("%s: configuration: 0x%p composite dev: 0x%p\n",
-	      __func__, c, c->cdev);
-
+			__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;
+
+	struct g_dnl_bind_callback *callback = g_dnl_first_bind_callback();
+	for (; callback != g_dnl_last_bind_callback(); ++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)
@@ -203,12 +210,12 @@  static int g_dnl_bind(struct usb_composite_dev *cdev)
 		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);
+	debug("%s: calling usb_gadget_connect for controller '%s'\n",
+			__func__, gadget->name);
 	usb_gadget_connect(gadget);
 
 	return 0;
@@ -227,36 +234,21 @@  static struct usb_composite_driver g_dnl_driver = {
 	.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;
-
-	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);
-
+	int ret = usb_composite_register(&g_dnl_driver);
 	if (ret) {
-		printf("%s: failed!, error: %d\n", __func__, ret);
+		debug("%s: failed!, error: %d\n", __func__, ret);
 		return ret;
 	}
-
 	return 0;
 }
 
diff --git a/include/dfu.h b/include/dfu.h
index f2e83db..6fd75d0 100644
--- a/include/dfu.h
+++ b/include/dfu.h
@@ -164,12 +164,5 @@  static inline int dfu_fill_entity_ram(struct dfu_entity *dfu, char *s)
 }
 #endif
 
-#ifdef CONFIG_DFU_FUNCTION
 int dfu_add(struct usb_configuration *c);
-#else
-int dfu_add(struct usb_configuration *c)
-{
-	return 0;
-}
-#endif
 #endif /* __DFU_ENTITY_H_ */
diff --git a/include/g_dnl.h b/include/g_dnl.h
index 8f813c2..4392f76 100644
--- a/include/g_dnl.h
+++ b/include/g_dnl.h
@@ -10,6 +10,17 @@ 
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
+#include <linux/usb/composite.h>
+
+typedef int (*g_dnl_bind_callback_f)(struct usb_configuration *);
+
+/* used in Gadget downloader callback linker list */
+struct g_dnl_bind_callback
+{
+	const char *usb_function_name;
+	g_dnl_bind_callback_f fptr;
+};
+
 int g_dnl_bind_fixup(struct usb_device_descriptor *, const char *);
 int g_dnl_register(const char *s);
 void g_dnl_unregister(void);
diff --git a/include/thor.h b/include/thor.h
index afeade4..5051be7 100644
--- a/include/thor.h
+++ b/include/thor.h
@@ -15,13 +15,5 @@ 
 
 int thor_handle(void);
 int thor_init(void);
-
-#ifdef CONFIG_THOR_FUNCTION
 int thor_add(struct usb_configuration *c);
-#else
-int thor_add(struct usb_configuration *c)
-{
-	return 0;
-}
-#endif
 #endif /* __THOR_H_ */
diff --git a/include/usb_mass_storage.h b/include/usb_mass_storage.h
index 9df3adc..6ee4f34 100644
--- a/include/usb_mass_storage.h
+++ b/include/usb_mass_storage.h
@@ -37,13 +37,5 @@  int fsg_init(struct ums *);
 void fsg_cleanup(void);
 struct ums *ums_init(unsigned int);
 int fsg_main_thread(void *);
-
-#ifdef CONFIG_USB_GADGET_MASS_STORAGE
 int fsg_add(struct usb_configuration *c);
-#else
-int fsg_add(struct usb_configuration *c)
-{
-	return 0;
-}
-#endif
 #endif /* __USB_MASS_STORAGE_H__ */