Added Kconfig options for each function used by g_multi so that one can customize the gadget to a greater extend. Note that it will be wise to change vendor and product ID when customising the gadget. Signed-off-by: Michal Nazarewicz <m.nazarewicz@xxxxxxxxxxx> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx> --- Documentation/usb/gadget_multi.txt | 27 +++--- drivers/usb/gadget/Kconfig | 67 +++++++++----- drivers/usb/gadget/multi.c | 166 ++++++++++++++++-------------------- 3 files changed, 130 insertions(+), 130 deletions(-) diff --git a/Documentation/usb/gadget_multi.txt b/Documentation/usb/gadget_multi.txt index bd53a9f..65bccd8 100644 --- a/Documentation/usb/gadget_multi.txt +++ b/Documentation/usb/gadget_multi.txt @@ -2,20 +2,21 @@ * Overview -The Multifunction Composite Gadget (or g_multi) is a composite gadget -that makes extensive use of the composite framework to provide -a... multifunction gadget. +The Multifunction Composite Gadget (or g_multi) is a customisable +composite gadget that makes extensive use of the composite framework +to provide a... multifunction gadget. In it's standard configuration it provides a single USB configuration with RNDIS[1] (that is Ethernet), USB CDC[2] ACM (that is serial) and USB Mass Storage functions. -A CDC ECM (Ethernet) function may be turned on via a Kconfig option -and RNDIS can be turned off. If they are both enabled the gadget will -have two configurations -- one with RNDIS and another with CDC ECM[3]. +Each function can be disabled via a Kconfig option. There's also +a CDC ECM (Ethernet) function which can be turned on. If CDC ECM and +RNDIS are enabled the gadget will have two configurations -- one with +RNDIS and another with CDC ECM[3]. -Please not that if you use non-standard configuration (that is enable -CDC ECM) you may need to change vendor and/or product ID. +Please not that if you use non-standard configuration you may need to +change vendor and/or product ID. * Host drivers @@ -92,11 +93,11 @@ hesitate submitting it! **** Customising the gadget -If you intend to hack the g_multi gadget be advised that rearranging -functions will obviously change interface numbers for each of the -functionality. As an effect provided INFs won't work since they have -interface numbers hard-coded in them (it's not hard to change those -though). +If you intend to customise (via Kconfig) or hack the g_multi gadget be +advised that rearranging functions will obviously change interface +numbers for each of the functionality. As an effect provided INFs +won't work since they have interface numbers hard-coded in them (it's +not hard to change those though). This also means, that after experimenting with g_multi and changing provided functions one should change gadget's vendor and/or product ID diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index c97f021..8052643 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -861,43 +861,62 @@ config USB_G_NOKIA config USB_G_MULTI tristate "Multifunction Composite Gadget (EXPERIMENTAL)" - depends on BLOCK && NET - select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS + select USB_G_MULTI_ACM if !USB_G_MULTI_ANYTHING help - The Multifunction Composite Gadget provides Ethernet (RNDIS - and/or CDC Ethernet), mass storage and ACM serial link - interfaces. - - You will be asked to choose which of the two configurations is - to be available in the gadget. At least one configuration must - be chosen to make the gadget usable. Selecting more than one - configuration will prevent Windows from automatically detecting - the gadget as a composite gadget, so an INF file will be needed to - use the gadget. + The Multifunction Composite Gadget provides several different + configurations and functions. Which interfaces are provided can + be configured at build time. If you choose this gadget additional + options will appear. Say "y" to link the driver statically, or "m" to build a dynamically linked module called "g_multi". -config USB_G_MULTI_RNDIS - bool "RNDIS + CDC Serial + Storage configuration" +config USB_G_MULTI_ANYTHING + bool depends on USB_G_MULTI + +config USB_G_MULTI_RNDIS + bool "Include RNDIS function" + depends on USB_G_MULTI && NET + select USB_G_MULTI_ANYTHING default y help - This option enables a configuration with RNDIS, CDC Serial and - Mass Storage functions available in the Multifunction Composite - Gadget. This is the configuration dedicated for Windows since RNDIS - is Microsoft's protocol. + This option enables the RNDIS (Ethernet) function. It is + protocol dedicated for Windows since it's Microsoft's invention. + + If you select also CDC ECM function gadget will have two + configurations one with RNDIS and another with CDC ECM. + + If unsure, say "y". + +config USB_G_MULTI_ECM + bool "Include CDC ECM function" + depends on USB_G_MULTI && NET + select USB_G_MULTI_ANYTHING + help + This option enables the CDC ECM (Ethernet) function. + + If you select also RNDIS function gadget will have two + configurations one with RNDIS and another with CDC ECM. If unsure, say "y". -config USB_G_MULTI_CDC - bool "CDC Ethernet + CDC Serial + Storage configuration" +config USB_G_MULTI_ACM + bool "Include CDC ACM function" depends on USB_G_MULTI - default n + default y + help + This option enables the CDC ACM (serial) function. + + If unsure, say "y". + +config USB_G_MULTI_MSF + bool "Include mass storage function" + depends on USB_G_MULTI && BLOCK + select USB_G_MULTI_ANYTHING + default y help - This option enables a configuration with CDC Ethernet (ECM), CDC - Serial and Mass Storage functions available in the Multifunction - Composite Gadget. + This option enables the mass storage (or UMS) function. If unsure, say "y". diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index c7a5b58..6f6fd3e 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -57,19 +57,57 @@ MODULE_LICENSE("GPL"); #include "config.c" #include "epautoconf.c" -#include "f_mass_storage.c" +/* Mass storage */ +#ifdef CONFIG_USB_G_MULTI_MSF +# include "f_mass_storage.c" -#include "u_serial.c" -#include "f_acm.c" +static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; +FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); + +static struct fsg_common fsg_common; +#else +# define fsg_common_from_params(common, cdev, data) NULL +# define fsg_bind_config(cdev, conf, common) ((int)0) +# define fsg_common_put(common) do { } while (0) +#endif -#include "f_ecm.c" -#include "f_subset.c" -#ifdef USB_ETH_RNDIS +/* CDC ACM */ +#ifdef CONFIG_USB_G_MULTI_ACM +# include "u_serial.c" +# include "f_acm.c" +#else +# define gserial_setup(conf, ports) ((int)0) +# define gserial_cleanup() do { } while (0) +# define acm_bind_config(conf, ports) ((int)0) +#endif + +/* Ethernet */ +#ifdef CONFIG_USB_G_MULTI_ECM +# include "f_ecm.c" +# include "f_subset.c" +#endif + +#ifdef CONFIG_USB_G_MULTI_RNDIS # include "f_rndis.c" # include "rndis.c" #endif -#include "u_ether.c" +#if defined CONFIG_USB_G_MULTI_ECM || defined CONFIG_USB_G_MULTI_RNDIS +# include "u_ether.c" +static u8 hostaddr[ETH_ALEN]; +#else +# define gether_setup(cdev, hostaddr) ((int)0) +# define gether_cleanup() do { } while (0) +#endif + +#ifndef CONFIG_USB_G_MULTI_ECM +# define can_support_ecm(gadget) true +# define ecm_bind_config(conf, ethaddr) ((int)0) +#endif + +#ifndef CONFIG_USB_G_MULTI_RNDIS +# define rndis_bind_config(conf, ethaddr) ((int)0) +#endif /***************************** Device Descriptor ****************************/ @@ -78,19 +116,6 @@ MODULE_LICENSE("GPL"); #define MULTI_PRODUCT_NUM 0xa4ab /* XXX */ -enum { - __MULTI_NO_CONFIG, -#ifdef CONFIG_USB_G_MULTI_RNDIS - MULTI_RNDIS_CONFIG_NUM, -#endif -#ifdef CONFIG_USB_G_MULTI_CDC - MULTI_CDC_CONFIG_NUM, -#endif - __MULTI_NUM_CONFIGS_HELPER, - MULTI_NUM_CONFIGS = __MULTI_NUM_CONFIGS_HELPER - 1 -}; - - static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, @@ -104,7 +129,11 @@ static struct usb_device_descriptor device_desc = { /* Vendor and product id can be overridden by module parameters. */ .idVendor = cpu_to_le16(MULTI_VENDOR_NUM), .idProduct = cpu_to_le16(MULTI_PRODUCT_NUM), - .bNumConfigurations = MULTI_NUM_CONFIGS, +#if defined CONFIG_USB_G_MULTI_RNDIS && defined CONFIG_USB_G_MULTI_ECM + .bNumConfigurations = 2, +#else + .bNumConfigurations = 1, +#endif }; @@ -124,12 +153,6 @@ static const struct usb_descriptor_header *otg_desc[] = { enum { MULTI_STRING_MANUFACTURER_IDX, MULTI_STRING_PRODUCT_IDX, -#ifdef CONFIG_USB_G_MULTI_RNDIS - MULTI_STRING_RNDIS_CONFIG_IDX, -#endif -#ifdef CONFIG_USB_G_MULTI_CDC - MULTI_STRING_CDC_CONFIG_IDX, -#endif }; static char manufacturer[50]; @@ -137,12 +160,6 @@ static char manufacturer[50]; static struct usb_string strings_dev[] = { [MULTI_STRING_MANUFACTURER_IDX].s = manufacturer, [MULTI_STRING_PRODUCT_IDX].s = DRIVER_DESC, -#ifdef CONFIG_USB_G_MULTI_RNDIS - [MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS", -#endif -#ifdef CONFIG_USB_G_MULTI_CDC - [MULTI_STRING_CDC_CONFIG_IDX].s = "Multifunction with CDC ECM", -#endif { } /* end of list */ }; @@ -159,19 +176,8 @@ static struct usb_gadget_strings *dev_strings[] = { /****************************** Configurations ******************************/ -static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; -FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); -static struct fsg_common fsg_common; - -static u8 hostaddr[ETH_ALEN]; - - -/********** RNDIS **********/ - -#ifdef USB_ETH_RNDIS - -static __ref int rndis_do_config(struct usb_configuration *c) +static __ref int first_do_config(struct usb_configuration *c) { int ret; @@ -180,7 +186,11 @@ static __ref int rndis_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } +#ifdef CONFIG_USB_G_MULTI_RNDIS ret = rndis_bind_config(c, hostaddr); +#else + ret = ecm_bind_config(c, hostaddr); +#endif if (ret < 0) return ret; @@ -195,35 +205,17 @@ static __ref int rndis_do_config(struct usb_configuration *c) return 0; } -static int rndis_config_register(struct usb_composite_dev *cdev) -{ - static struct usb_configuration config = { - .bind = rndis_do_config, - .bConfigurationValue = MULTI_RNDIS_CONFIG_NUM, - .bmAttributes = USB_CONFIG_ATT_SELFPOWER, - }; - - config.label = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].s; - config.iConfiguration = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].id; - - return usb_add_config(cdev, &config); -} - -#else - -static int rndis_config_register(struct usb_composite_dev *cdev) -{ - return 0; -} - -#endif - +static struct usb_configuration first_config_driver = { + .label = "First Configuration", + .bind = first_do_config, + .bConfigurationValue = 1, + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, +}; -/********** CDC ECM **********/ -#ifdef CONFIG_USB_G_MULTI_CDC +#if defined CONFIG_USB_G_MULTI_RNDIS && defined CONFIG_USB_G_MULTI_ECM -static __ref int cdc_do_config(struct usb_configuration *c) +static __ref int second_do_config(struct usb_configuration *c) { int ret; @@ -247,26 +239,12 @@ static __ref int cdc_do_config(struct usb_configuration *c) return 0; } -static int cdc_config_register(struct usb_composite_dev *cdev) -{ - static struct usb_configuration config = { - .bind = cdc_do_config, - .bConfigurationValue = MULTI_CDC_CONFIG_NUM, - .bmAttributes = USB_CONFIG_ATT_SELFPOWER, - }; - - config.label = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].s; - config.iConfiguration = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].id; - - return usb_add_config(cdev, &config); -} - -#else - -static int cdc_config_register(struct usb_composite_dev *cdev) -{ - return 0; -} +static struct usb_configuration second_config_driver = { + .label = "Second Configuration", + .bind = second_do_config, + .bConfigurationValue = 2, + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, +}; #endif @@ -331,13 +309,15 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) strings_dev[MULTI_STRING_PRODUCT_IDX].id; /* register configurations */ - status = rndis_config_register(cdev); + status = usb_add_config(cdev, &first_config_driver); if (unlikely(status < 0)) goto fail2; - status = cdc_config_register(cdev); +#if defined CONFIG_USB_G_MULTI_RNDIS && defined CONFIG_USB_G_MULTI_ECM + status = usb_add_config(cdev, &second_config_driver); if (unlikely(status < 0)) goto fail2; +#endif /* we're done */ dev_info(&gadget->dev, DRIVER_DESC "\n"); -- 1.7.1 -- 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