aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/Kconfig29
-rw-r--r--drivers/usb/gadget/Makefile2
-rw-r--r--drivers/usb/gadget/composite.c8
-rw-r--r--drivers/usb/gadget/config.c39
-rw-r--r--drivers/usb/gadget/dummy_hcd.c170
-rw-r--r--drivers/usb/gadget/f_acm.c79
-rw-r--r--drivers/usb/gadget/f_ecm.c112
-rw-r--r--drivers/usb/gadget/f_eem.c51
-rw-r--r--drivers/usb/gadget/f_fs.c4
-rw-r--r--drivers/usb/gadget/f_hid.c30
-rw-r--r--drivers/usb/gadget/f_loopback.c28
-rw-r--r--drivers/usb/gadget/f_mass_storage.c63
-rw-r--r--drivers/usb/gadget/f_midi.c14
-rw-r--r--drivers/usb/gadget/f_ncm.c94
-rw-r--r--drivers/usb/gadget/f_obex.c42
-rw-r--r--drivers/usb/gadget/f_phonet.c21
-rw-r--r--drivers/usb/gadget/f_rndis.c94
-rw-r--r--drivers/usb/gadget/f_serial.c38
-rw-r--r--drivers/usb/gadget/f_sourcesink.c104
-rw-r--r--drivers/usb/gadget/f_subset.c75
-rw-r--r--drivers/usb/gadget/f_uac1.c23
-rw-r--r--drivers/usb/gadget/f_uac2.c220
-rw-r--r--drivers/usb/gadget/f_uvc.c138
-rw-r--r--drivers/usb/gadget/file_storage.c3656
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c2
-rw-r--r--drivers/usb/gadget/inode.c3
-rw-r--r--drivers/usb/gadget/lpc32xx_udc.c2
-rw-r--r--drivers/usb/gadget/net2280.c2
-rw-r--r--drivers/usb/gadget/printer.c12
-rw-r--r--drivers/usb/gadget/pxa27x_udc.h2
-rw-r--r--drivers/usb/gadget/storage_common.c165
-rw-r--r--drivers/usb/gadget/tcm_usb_gadget.c13
-rw-r--r--drivers/usb/gadget/u_ether.c3
-rw-r--r--drivers/usb/gadget/udc-core.c11
34 files changed, 622 insertions, 4727 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index e0ff51b8952..14625fd2cec 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -721,31 +721,6 @@ config USB_FUNCTIONFS_GENERIC
Include a configuration with the Function Filesystem alone with
no Ethernet interface.
-config USB_FILE_STORAGE
- tristate "File-backed Storage Gadget (DEPRECATED)"
- depends on BLOCK
- help
- The File-backed Storage Gadget acts as a USB Mass Storage
- disk drive. As its storage repository it can use a regular
- file or a block device (in much the same way as the "loop"
- device driver), specified as a module parameter.
-
- Say "y" to link the driver statically, or "m" to build a
- dynamically linked module called "g_file_storage".
-
- NOTE: This driver is deprecated. Its replacement is the
- Mass Storage Gadget.
-
-config USB_FILE_STORAGE_TEST
- bool "File-backed Storage Gadget testing version"
- depends on USB_FILE_STORAGE
- default n
- help
- Say "y" to generate the larger testing version of the
- File-backed Storage Gadget, useful for probing the
- behavior of USB Mass Storage hosts. Not needed for
- normal operation.
-
config USB_MASS_STORAGE
tristate "Mass Storage Gadget"
depends on BLOCK
@@ -756,8 +731,8 @@ config USB_MASS_STORAGE
device (in much the same way as the "loop" device driver),
specified as a module parameter or sysfs option.
- This driver is an updated replacement for the deprecated
- File-backed Storage Gadget (g_file_storage).
+ This driver is a replacement for now removed File-backed
+ Storage Gadget (g_file_storage).
Say "y" to link the driver statically, or "m" to build
a dynamically linked module called "g_mass_storage".
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 307be5fa824..8b4acfd92aa 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -44,7 +44,6 @@ g_ether-y := ether.o
g_serial-y := serial.o
g_midi-y := gmidi.o
gadgetfs-y := inode.o
-g_file_storage-y := file_storage.o
g_mass_storage-y := mass_storage.o
g_printer-y := printer.o
g_cdc-y := cdc2.o
@@ -62,7 +61,6 @@ obj-$(CONFIG_USB_AUDIO) += g_audio.o
obj-$(CONFIG_USB_ETH) += g_ether.o
obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
obj-$(CONFIG_USB_FUNCTIONFS) += g_ffs.o
-obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
obj-$(CONFIG_USB_MASS_STORAGE) += g_mass_storage.o
obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
obj-$(CONFIG_USB_G_PRINTER) += g_printer.o
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 957f973dd96..2a6bfe759c2 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -107,7 +107,7 @@ int config_ep_by_speed(struct usb_gadget *g,
}
/* else: fall through */
default:
- speed_desc = f->descriptors;
+ speed_desc = f->fs_descriptors;
}
/* find descriptors */
for_each_ep_desc(speed_desc, d_spd) {
@@ -200,7 +200,7 @@ int usb_add_function(struct usb_configuration *config,
* as full speed ... it's the function drivers that will need
* to avoid bulk and ISO transfers.
*/
- if (!config->fullspeed && function->descriptors)
+ if (!config->fullspeed && function->fs_descriptors)
config->fullspeed = true;
if (!config->highspeed && function->hs_descriptors)
config->highspeed = true;
@@ -363,7 +363,7 @@ static int config_buf(struct usb_configuration *config,
descriptors = f->hs_descriptors;
break;
default:
- descriptors = f->descriptors;
+ descriptors = f->fs_descriptors;
}
if (!descriptors)
@@ -620,7 +620,7 @@ static int set_config(struct usb_composite_dev *cdev,
descriptors = f->hs_descriptors;
break;
default:
- descriptors = f->descriptors;
+ descriptors = f->fs_descriptors;
}
for (; *descriptors; ++descriptors) {
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index e3a98929d34..34e12fc52c2 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -19,7 +19,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-
+#include <linux/usb/composite.h>
/**
* usb_descriptor_fillbuf - fill buffer with descriptors
@@ -158,3 +158,40 @@ usb_copy_descriptors(struct usb_descriptor_header **src)
return ret;
}
EXPORT_SYMBOL_GPL(usb_copy_descriptors);
+
+int usb_assign_descriptors(struct usb_function *f,
+ struct usb_descriptor_header **fs,
+ struct usb_descriptor_header **hs,
+ struct usb_descriptor_header **ss)
+{
+ struct usb_gadget *g = f->config->cdev->gadget;
+
+ if (fs) {
+ f->fs_descriptors = usb_copy_descriptors(fs);
+ if (!f->fs_descriptors)
+ goto err;
+ }
+ if (hs && gadget_is_dualspeed(g)) {
+ f->hs_descriptors = usb_copy_descriptors(hs);
+ if (!f->hs_descriptors)
+ goto err;
+ }
+ if (ss && gadget_is_superspeed(g)) {
+ f->ss_descriptors = usb_copy_descriptors(ss);
+ if (!f->ss_descriptors)
+ goto err;
+ }
+ return 0;
+err:
+ usb_free_all_descriptors(f);
+ return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(usb_assign_descriptors);
+
+void usb_free_all_descriptors(struct usb_function *f)
+{
+ usb_free_descriptors(f->fs_descriptors);
+ usb_free_descriptors(f->hs_descriptors);
+ usb_free_descriptors(f->ss_descriptors);
+}
+EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 0f7541be28f..95d584dbed1 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -63,16 +63,20 @@ MODULE_LICENSE("GPL");
struct dummy_hcd_module_parameters {
bool is_super_speed;
bool is_high_speed;
+ unsigned int num;
};
static struct dummy_hcd_module_parameters mod_data = {
.is_super_speed = false,
.is_high_speed = true,
+ .num = 1,
};
module_param_named(is_super_speed, mod_data.is_super_speed, bool, S_IRUGO);
MODULE_PARM_DESC(is_super_speed, "true to simulate SuperSpeed connection");
module_param_named(is_high_speed, mod_data.is_high_speed, bool, S_IRUGO);
MODULE_PARM_DESC(is_high_speed, "true to simulate HighSpeed connection");
+module_param_named(num, mod_data.num, uint, S_IRUGO);
+MODULE_PARM_DESC(num, "number of emulated controllers");
/*-------------------------------------------------------------------------*/
/* gadget side driver data structres */
@@ -238,8 +242,6 @@ static inline struct dummy *gadget_dev_to_dummy(struct device *dev)
return container_of(dev, struct dummy, gadget.dev);
}
-static struct dummy the_controller;
-
/*-------------------------------------------------------------------------*/
/* SLAVE/GADGET SIDE UTILITY ROUTINES */
@@ -973,9 +975,10 @@ static void init_dummy_udc_hw(struct dummy *dum)
static int dummy_udc_probe(struct platform_device *pdev)
{
- struct dummy *dum = &the_controller;
+ struct dummy *dum;
int rc;
+ dum = *((void **)dev_get_platdata(&pdev->dev));
dum->gadget.name = gadget_name;
dum->gadget.ops = &dummy_ops;
dum->gadget.max_speed = USB_SPEED_SUPER;
@@ -2398,10 +2401,13 @@ static int dummy_h_get_frame(struct usb_hcd *hcd)
static int dummy_setup(struct usb_hcd *hcd)
{
+ struct dummy *dum;
+
+ dum = *((void **)dev_get_platdata(hcd->self.controller));
hcd->self.sg_tablesize = ~0;
if (usb_hcd_is_primary_hcd(hcd)) {
- the_controller.hs_hcd = hcd_to_dummy_hcd(hcd);
- the_controller.hs_hcd->dum = &the_controller;
+ dum->hs_hcd = hcd_to_dummy_hcd(hcd);
+ dum->hs_hcd->dum = dum;
/*
* Mark the first roothub as being USB 2.0.
* The USB 3.0 roothub will be registered later by
@@ -2410,8 +2416,8 @@ static int dummy_setup(struct usb_hcd *hcd)
hcd->speed = HCD_USB2;
hcd->self.root_hub->speed = USB_SPEED_HIGH;
} else {
- the_controller.ss_hcd = hcd_to_dummy_hcd(hcd);
- the_controller.ss_hcd->dum = &the_controller;
+ dum->ss_hcd = hcd_to_dummy_hcd(hcd);
+ dum->ss_hcd->dum = dum;
hcd->speed = HCD_USB3;
hcd->self.root_hub->speed = USB_SPEED_SUPER;
}
@@ -2524,11 +2530,13 @@ static struct hc_driver dummy_hcd = {
static int dummy_hcd_probe(struct platform_device *pdev)
{
+ struct dummy *dum;
struct usb_hcd *hs_hcd;
struct usb_hcd *ss_hcd;
int retval;
dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
+ dum = *((void **)dev_get_platdata(&pdev->dev));
if (!mod_data.is_super_speed)
dummy_hcd.flags = HCD_USB2;
@@ -2561,7 +2569,7 @@ dealloc_usb2_hcd:
usb_remove_hcd(hs_hcd);
put_usb2_hcd:
usb_put_hcd(hs_hcd);
- the_controller.hs_hcd = the_controller.ss_hcd = NULL;
+ dum->hs_hcd = dum->ss_hcd = NULL;
return retval;
}
@@ -2579,8 +2587,8 @@ static int dummy_hcd_remove(struct platform_device *pdev)
usb_remove_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
usb_put_hcd(dummy_hcd_to_hcd(dum->hs_hcd));
- the_controller.hs_hcd = NULL;
- the_controller.ss_hcd = NULL;
+ dum->hs_hcd = NULL;
+ dum->ss_hcd = NULL;
return 0;
}
@@ -2627,13 +2635,15 @@ static struct platform_driver dummy_hcd_driver = {
};
/*-------------------------------------------------------------------------*/
-
-static struct platform_device *the_udc_pdev;
-static struct platform_device *the_hcd_pdev;
+#define MAX_NUM_UDC 2
+static struct platform_device *the_udc_pdev[MAX_NUM_UDC];
+static struct platform_device *the_hcd_pdev[MAX_NUM_UDC];
static int __init init(void)
{
int retval = -ENOMEM;
+ int i;
+ struct dummy *dum[MAX_NUM_UDC];
if (usb_disabled())
return -ENODEV;
@@ -2641,65 +2651,129 @@ static int __init init(void)
if (!mod_data.is_high_speed && mod_data.is_super_speed)
return -EINVAL;
- the_hcd_pdev = platform_device_alloc(driver_name, -1);
- if (!the_hcd_pdev)
- return retval;
- the_udc_pdev = platform_device_alloc(gadget_name, -1);
- if (!the_udc_pdev)
- goto err_alloc_udc;
+ if (mod_data.num < 1 || mod_data.num > MAX_NUM_UDC) {
+ pr_err("Number of emulated UDC must be in range of 1…%d\n",
+ MAX_NUM_UDC);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < mod_data.num; i++) {
+ the_hcd_pdev[i] = platform_device_alloc(driver_name, i);
+ if (!the_hcd_pdev[i]) {
+ i--;
+ while (i >= 0)
+ platform_device_put(the_hcd_pdev[i--]);
+ return retval;
+ }
+ }
+ for (i = 0; i < mod_data.num; i++) {
+ the_udc_pdev[i] = platform_device_alloc(gadget_name, i);
+ if (!the_udc_pdev[i]) {
+ i--;
+ while (i >= 0)
+ platform_device_put(the_udc_pdev[i--]);
+ goto err_alloc_udc;
+ }
+ }
+ for (i = 0; i < mod_data.num; i++) {
+ dum[i] = kzalloc(sizeof(struct dummy), GFP_KERNEL);
+ if (!dum[i])
+ goto err_add_pdata;
+ retval = platform_device_add_data(the_hcd_pdev[i], &dum[i],
+ sizeof(void *));
+ if (retval)
+ goto err_add_pdata;
+ retval = platform_device_add_data(the_udc_pdev[i], &dum[i],
+ sizeof(void *));
+ if (retval)
+ goto err_add_pdata;
+ }
retval = platform_driver_register(&dummy_hcd_driver);
if (retval < 0)
- goto err_register_hcd_driver;
+ goto err_add_pdata;
retval = platform_driver_register(&dummy_udc_driver);
if (retval < 0)
goto err_register_udc_driver;
- retval = platform_device_add(the_hcd_pdev);
- if (retval < 0)
- goto err_add_hcd;
- if (!the_controller.hs_hcd ||
- (!the_controller.ss_hcd && mod_data.is_super_speed)) {
- /*
- * The hcd was added successfully but its probe function failed
- * for some reason.
- */
- retval = -EINVAL;
- goto err_add_udc;
+ for (i = 0; i < mod_data.num; i++) {
+ retval = platform_device_add(the_hcd_pdev[i]);
+ if (retval < 0) {
+ i--;
+ while (i >= 0)
+ platform_device_del(the_hcd_pdev[i--]);
+ goto err_add_hcd;
+ }
}
- retval = platform_device_add(the_udc_pdev);
- if (retval < 0)
- goto err_add_udc;
- if (!platform_get_drvdata(the_udc_pdev)) {
- /*
- * The udc was added successfully but its probe function failed
- * for some reason.
- */
- retval = -EINVAL;
- goto err_probe_udc;
+ for (i = 0; i < mod_data.num; i++) {
+ if (!dum[i]->hs_hcd ||
+ (!dum[i]->ss_hcd && mod_data.is_super_speed)) {
+ /*
+ * The hcd was added successfully but its probe
+ * function failed for some reason.
+ */
+ retval = -EINVAL;
+ goto err_add_udc;
+ }
+ }
+
+ for (i = 0; i < mod_data.num; i++) {
+ retval = platform_device_add(the_udc_pdev[i]);
+ if (retval < 0) {
+ i--;
+ while (i >= 0)
+ platform_device_del(the_udc_pdev[i]);
+ goto err_add_udc;
+ }
+ }
+
+ for (i = 0; i < mod_data.num; i++) {
+ if (!platform_get_drvdata(the_udc_pdev[i])) {
+ /*
+ * The udc was added successfully but its probe
+ * function failed for some reason.
+ */
+ retval = -EINVAL;
+ goto err_probe_udc;
+ }
}
return retval;
err_probe_udc:
- platform_device_del(the_udc_pdev);
+ for (i = 0; i < mod_data.num; i++)
+ platform_device_del(the_udc_pdev[i]);
err_add_udc:
- platform_device_del(the_hcd_pdev);
+ for (i = 0; i < mod_data.num; i++)
+ platform_device_del(the_hcd_pdev[i]);
err_add_hcd:
platform_driver_unregister(&dummy_udc_driver);
err_register_udc_driver:
platform_driver_unregister(&dummy_hcd_driver);
-err_register_hcd_driver:
- platform_device_put(the_udc_pdev);
+err_add_pdata:
+ for (i = 0; i < mod_data.num; i++)
+ kfree(dum[i]);
+ for (i = 0; i < mod_data.num; i++)
+ platform_device_put(the_udc_pdev[i]);
err_alloc_udc:
- platform_device_put(the_hcd_pdev);
+ for (i = 0; i < mod_data.num; i++)
+ platform_device_put(the_hcd_pdev[i]);
return retval;
}
module_init(init);
static void __exit cleanup(void)
{
- platform_device_unregister(the_udc_pdev);
- platform_device_unregister(the_hcd_pdev);
+ int i;
+
+ for (i = 0; i < mod_data.num; i++) {
+ struct dummy *dum;
+
+ dum = *((void **)dev_get_platdata(&the_udc_pdev[i]->dev));
+
+ platform_device_unregister(the_udc_pdev[i]);
+ platform_device_unregister(the_hcd_pdev[i]);
+ kfree(dum);
+ }
platform_driver_unregister(&dummy_udc_driver);
platform_driver_unregister(&dummy_hcd_driver);
}
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index d672250a61f..549174466c2 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -87,7 +87,7 @@ static inline struct f_acm *port_to_acm(struct gserial *p)
/* notification endpoint uses smallish and infrequent fixed-size messages */
-#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
+#define GS_NOTIFY_INTERVAL_MS 32
#define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */
/* interface and class descriptors: */
@@ -167,7 +167,7 @@ static struct usb_endpoint_descriptor acm_fs_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
- .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
+ .bInterval = GS_NOTIFY_INTERVAL_MS,
};
static struct usb_endpoint_descriptor acm_fs_in_desc = {
@@ -199,14 +199,13 @@ static struct usb_descriptor_header *acm_fs_function[] = {
};
/* high speed support: */
-
static struct usb_endpoint_descriptor acm_hs_notify_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
- .bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
+ .bInterval = USB_MS_TO_HS_INTERVAL(GS_NOTIFY_INTERVAL_MS),
};
static struct usb_endpoint_descriptor acm_hs_in_desc = {
@@ -659,37 +658,22 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
acm->notify_req->complete = acm_cdc_notify_complete;
acm->notify_req->context = acm;
- /* copy descriptors */
- f->descriptors = usb_copy_descriptors(acm_fs_function);
- if (!f->descriptors)
- goto fail;
-
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- acm_hs_in_desc.bEndpointAddress =
- acm_fs_in_desc.bEndpointAddress;
- acm_hs_out_desc.bEndpointAddress =
- acm_fs_out_desc.bEndpointAddress;
- acm_hs_notify_desc.bEndpointAddress =
- acm_fs_notify_desc.bEndpointAddress;
-
- /* copy descriptors */
- f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
- }
- if (gadget_is_superspeed(c->cdev->gadget)) {
- acm_ss_in_desc.bEndpointAddress =
- acm_fs_in_desc.bEndpointAddress;
- acm_ss_out_desc.bEndpointAddress =
- acm_fs_out_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->ss_descriptors = usb_copy_descriptors(acm_ss_function);
- if (!f->ss_descriptors)
- goto fail;
- }
+ acm_hs_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress;
+ acm_hs_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress;
+ acm_hs_notify_desc.bEndpointAddress =
+ acm_fs_notify_desc.bEndpointAddress;
+
+ acm_ss_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress;
+ acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress;
+
+ status = usb_assign_descriptors(f, acm_fs_function, acm_hs_function,
+ acm_ss_function);
+ if (status)
+ goto fail;
DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
acm->port_num,
@@ -721,11 +705,8 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_acm *acm = func_to_acm(f);
- if (gadget_is_dualspeed(c->cdev->gadget))
- usb_free_descriptors(f->hs_descriptors);
- if (gadget_is_superspeed(c->cdev->gadget))
- usb_free_descriptors(f->ss_descriptors);
- usb_free_descriptors(f->descriptors);
+ acm_string_defs[0].id = 0;
+ usb_free_all_descriptors(f);
gs_free_req(acm->notify, acm->notify_req);
kfree(acm);
}
@@ -762,27 +743,15 @@ int acm_bind_config(struct usb_configuration *c, u8 port_num)
*/
/* maybe allocate device-global string IDs, and patch descriptors */
- if (acm_string_defs[ACM_CTRL_IDX].id == 0) {
- status = usb_string_id(c->cdev);
+ if (acm_string_defs[0].id == 0) {
+ status = usb_string_ids_tab(c->cdev, acm_string_defs);
if (status < 0)
return status;
- acm_string_defs[ACM_CTRL_IDX].id = status;
-
- acm_control_interface_desc.iInterface = status;
-
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- acm_string_defs[ACM_DATA_IDX].id = status;
-
- acm_data_interface_desc.iInterface = status;
-
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- acm_string_defs[ACM_IAD_IDX].id = status;
-
- acm_iad_descriptor.iFunction = status;
+ acm_control_interface_desc.iInterface =
+ acm_string_defs[ACM_CTRL_IDX].id;
+ acm_data_interface_desc.iInterface =
+ acm_string_defs[ACM_DATA_IDX].id;
+ acm_iad_descriptor.iFunction = acm_string_defs[ACM_IAD_IDX].id;
}
/* allocate and initialize one new instance */
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c
index 95bc94f8e57..83420a310fb 100644
--- a/drivers/usb/gadget/f_ecm.c
+++ b/drivers/usb/gadget/f_ecm.c
@@ -91,7 +91,7 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g)
* encapsulated commands (vendor-specific, using control-OUT).
*/
-#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
+#define ECM_STATUS_INTERVAL_MS 32
#define ECM_STATUS_BYTECOUNT 16 /* 8 byte header + data */
@@ -192,7 +192,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
- .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
+ .bInterval = ECM_STATUS_INTERVAL_MS,
};
static struct usb_endpoint_descriptor fs_ecm_in_desc = {
@@ -239,7 +239,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
- .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
+ .bInterval = USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
};
static struct usb_endpoint_descriptor hs_ecm_in_desc = {
@@ -288,7 +288,7 @@ static struct usb_endpoint_descriptor ss_ecm_notify_desc = {
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_INT,
.wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT),
- .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
+ .bInterval = USB_MS_TO_HS_INTERVAL(ECM_STATUS_INTERVAL_MS),
};
static struct usb_ss_ep_comp_descriptor ss_ecm_intr_comp_desc = {
@@ -330,6 +330,7 @@ static struct usb_ss_ep_comp_descriptor ss_ecm_bulk_comp_desc = {
static struct usb_descriptor_header *ecm_ss_function[] = {
/* CDC ECM control descriptors */
+ (struct usb_descriptor_header *) &ecm_iad_descriptor,
(struct usb_descriptor_header *) &ecm_control_intf,
(struct usb_descriptor_header *) &ecm_header_desc,
(struct usb_descriptor_header *) &ecm_union_desc,
@@ -353,7 +354,7 @@ static struct usb_descriptor_header *ecm_ss_function[] = {
static struct usb_string ecm_string_defs[] = {
[0].s = "CDC Ethernet Control Model (ECM)",
- [1].s = NULL /* DYNAMIC */,
+ [1].s = "",
[2].s = "CDC Ethernet Data",
[3].s = "CDC ECM",
{ } /* end of list */
@@ -742,42 +743,24 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
ecm->notify_req->context = ecm;
ecm->notify_req->complete = ecm_notify_complete;
- /* copy descriptors, and track endpoint copies */
- f->descriptors = usb_copy_descriptors(ecm_fs_function);
- if (!f->descriptors)
- goto fail;
-
/* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
- if (gadget_is_dualspeed(c->cdev->gadget)) {
- hs_ecm_in_desc.bEndpointAddress =
- fs_ecm_in_desc.bEndpointAddress;
- hs_ecm_out_desc.bEndpointAddress =
- fs_ecm_out_desc.bEndpointAddress;
- hs_ecm_notify_desc.bEndpointAddress =
- fs_ecm_notify_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->hs_descriptors = usb_copy_descriptors(ecm_hs_function);
- if (!f->hs_descriptors)
- goto fail;
- }
-
- if (gadget_is_superspeed(c->cdev->gadget)) {
- ss_ecm_in_desc.bEndpointAddress =
- fs_ecm_in_desc.bEndpointAddress;
- ss_ecm_out_desc.bEndpointAddress =
- fs_ecm_out_desc.bEndpointAddress;
- ss_ecm_notify_desc.bEndpointAddress =
- fs_ecm_notify_desc.bEndpointAddress;
-
- /* copy descriptors, and track endpoint copies */
- f->ss_descriptors = usb_copy_descriptors(ecm_ss_function);
- if (!f->ss_descriptors)
- goto fail;
- }
+ hs_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
+ hs_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
+ hs_ecm_notify_desc.bEndpointAddress =
+ fs_ecm_notify_desc.bEndpointAddress;
+
+ ss_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
+ ss_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
+ ss_ecm_notify_desc.bEndpointAddress =
+ fs_ecm_notify_desc.bEndpointAddress;
+
+ status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function,
+ ecm_ss_function);
+ if (status)
+ goto fail;
/* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code
@@ -795,11 +778,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- if (f->descriptors)
- usb_free_descriptors(f->descriptors);
- if (f->hs_descriptors)
- usb_free_descriptors(f->hs_descriptors);
-
if (ecm->notify_req) {
kfree(ecm->notify_req->buf);
usb_ep_free_request(ecm->notify, ecm->notify_req);
@@ -808,9 +786,9 @@ fail:
/* we might as well release our claims on endpoints */
if (ecm->notify)
ecm->notify->driver_data = NULL;
- if (ecm->port.out_ep->desc)
+ if (ecm->port.out_ep)
ecm->port.out_ep->driver_data = NULL;
- if (ecm->port.in_ep->desc)
+ if (ecm->port.in_ep)
ecm->port.in_ep->driver_data = NULL;
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -825,16 +803,11 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(c->cdev, "ecm unbind\n");
- if (gadget_is_superspeed(c->cdev->gadget))
- usb_free_descriptors(f->ss_descriptors);
- if (gadget_is_dualspeed(c->cdev->gadget))
- usb_free_descriptors(f->hs_descriptors);
- usb_free_descriptors(f->descriptors);
+ ecm_string_defs[0].id = 0;
+ usb_free_all_descriptors(f);
kfree(ecm->notify_req->buf);
usb_ep_free_request(ecm->notify, ecm->notify_req);
-
- ecm_string_defs[1].s = NULL;
kfree(ecm);
}
@@ -859,36 +832,15 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
return -EINVAL;
- /* maybe allocate device-global string IDs */
if (ecm_string_defs[0].id == 0) {
-
- /* control interface label */
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- ecm_string_defs[0].id = status;
- ecm_control_intf.iInterface = status;
-
- /* data interface label */
- status = usb_string_id(c->cdev);
- if (status < 0)
+ status = usb_string_ids_tab(c->cdev, ecm_string_defs);
+ if (status)
return status;
- ecm_string_defs[2].id = status;
- ecm_data_intf.iInterface = status;
- /* MAC address */
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- ecm_string_defs[1].id = status;
- ecm_desc.iMACAddress = status;
-
- /* IAD label */
- status = usb_string_id(c->cdev);
- if (status < 0)
- return status;
- ecm_string_defs[3].id = status;
- ecm_iad_descriptor.iFunction = status;
+ ecm_control_intf.iInterface = ecm_string_defs[0].id;
+ ecm_data_intf.iInterface = ecm_string_defs[2].id;
+ ecm_desc.iMACAddress = ecm_string_defs[1].id;
+ ecm_iad_descriptor.iFunction = ecm_string_defs[3].id;
}
/* allocate and initialize one new instance */
@@ -913,9 +865,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
ecm->port.func.disable = ecm_disable;
status = usb_add_function(c, &ecm->port.func);
- if (status) {
- ecm_string_defs[1].s = NULL;
+ if (status)
kfree(ecm);
- }
return status;
}
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c
index 1a7b2dd7d40..cf0ebee8556 100644
--- a/drivers/usb/gadget/f_eem.c
+++ b/drivers/usb/gadget/f_eem.c
@@ -274,38 +274,20 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
status = -ENOMEM;
- /* copy descriptors, and track endpoint copies */
- f->descriptors = usb_copy_descriptors(eem_fs_function);
- if (!f->descriptors)
- goto fail;
-