Signed-off-by: Andrzej Pietrasiewicz <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
---
drivers/usb/gadget/Kconfig | 1 +
drivers/usb/gadget/multi.c | 41 +++++++++++++++++++++++++++++++++++------
2 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index fd0451a..aebdc14 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -948,6 +948,7 @@ config USB_G_MULTI
select USB_U_RNDIS
select USB_F_ACM
select USB_F_MASS_STORAGE
+ select USB_F_ECM
help
The Multifunction Composite Gadget provides Ethernet (RNDIS
and/or CDC Ethernet), mass storage and ACM serial link
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index c52ec0f..2371084 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -43,8 +43,7 @@ MODULE_LICENSE("GPL");
*/
#include "f_mass_storage.h"
-#define USB_FECM_INCLUDED
-#include "f_ecm.c"
+#include "u_ecm.h"
#include "f_subset.c"
#ifdef USB_ETH_RNDIS
# include "f_rndis.c"
@@ -141,6 +140,8 @@ static struct eth_dev *the_dev;
static struct usb_function_instance *fi_fsg;
+static struct usb_function_instance *fi_ecm;
+
/********** RNDIS **********/
#ifdef USB_ETH_RNDIS
@@ -217,9 +218,11 @@ static int rndis_config_register(struct usb_composite_dev
*cdev)
#ifdef CONFIG_USB_G_MULTI_CDC
static struct usb_function *f_acm_multi;
static struct usb_function *f_fsg_multi;
+static struct usb_function *f_ecm_multi;
static __init int cdc_do_config(struct usb_configuration *c)
{
+ struct f_ecm_opts *ecm_opts;
int ret;
if (gadget_is_otg(c->cdev->gadget)) {
@@ -227,9 +230,17 @@ static __init int cdc_do_config(struct usb_configuration
*c)
c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
- ret = ecm_bind_config(c, hostaddr, the_dev);
- if (ret < 0)
- return ret;
+ ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
+ ecm_opts->ethaddr = hostaddr;
+ ecm_opts->dev = the_dev;
+
+ f_ecm_multi = usb_get_function(fi_ecm);
+ if (IS_ERR(f_ecm_multi))
+ return PTR_ERR(f_ecm_multi);
+
+ ret = usb_add_function(c, f_ecm_multi);
+ if (ret)
+ goto err_func_ecm;
/* implicit port_num is zero */
f_acm_multi = usb_get_function(fi_acm);
@@ -258,6 +269,9 @@ err_fsg:
err_conf:
usb_put_function(f_acm_multi);
err_func_acm:
+ usb_remove_function(c, f_ecm_multi);
+err_func_ecm:
+ usb_put_function(f_ecm_multi);
return ret;
}
@@ -304,6 +318,12 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
if (IS_ERR(the_dev))
return PTR_ERR(the_dev);
+ fi_ecm = usb_get_function_instance("ecm");
+ if (IS_ERR(fi_ecm)) {
+ status = PTR_ERR(fi_ecm);
+ goto fail;
+ }
+
/* set up serial link layer */
fi_acm = usb_get_function_instance("acm");
if (IS_ERR(fi_acm)) {
@@ -338,7 +358,7 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
status = cdc_config_register(cdev);
if (unlikely(status < 0))
- goto fail3;
+ goto fail4;
usb_composite_overwrite_options(cdev, &coverwrite);
/* we're done */
@@ -348,6 +368,11 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
/* error recovery */
+fail4:
+#ifdef USB_ETH_RNDIS
+ usb_put_function(f_acm_rndis);
+ usb_put_function(f_fsg_rndis);
+#endif
fail3:
fsg_common_put(fsg_common);
fail2:
@@ -355,6 +380,8 @@ fail2:
fail1:
usb_put_function_instance(fi_acm);
fail0:
+ usb_put_function_instance(fi_ecm);
+fail:
gether_cleanup(the_dev);
return status;
}
@@ -364,6 +391,7 @@ static int __exit multi_unbind(struct usb_composite_dev
*cdev)
#ifdef CONFIG_USB_G_MULTI_CDC
usb_put_function(f_acm_multi);
usb_put_function(f_fsg_multi);
+ usb_put_function(f_ecm_multi);
#endif
#ifdef USB_ETH_RNDIS
usb_put_function(f_acm_rndis);
@@ -371,6 +399,7 @@ static int __exit multi_unbind(struct usb_composite_dev
*cdev)
#endif
usb_put_function_instance(fi_acm);
usb_put_function_instance(fi_fsg);
+ usb_put_function_instance(fi_ecm);
gether_cleanup(the_dev);
return 0;
}
--
1.7.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html