summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/legacy
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-08-14 16:41:11 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-08-14 16:41:11 -0700
commita3fbedf98fe9909cb2e406e2018ec437d64806f6 (patch)
tree701e2060053a2e9ac3052d6aec8a5334061fa123 /drivers/usb/gadget/legacy
parente6bbe1d05353a29628a4ca72d88bac0bdcec5f38 (diff)
parent2f3cc24f07b8bfe8302a46ceb1ed58cde62cbd09 (diff)
Merge tag 'usb-for-v4.3' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
Felipe writes: usb: patches for v4.3 merge window New support for Allwinne SoC on the MUSB driver has been added to the list of glue layers. MUSB also got support for building all DMA engines in one binary; this will be great for distros. DWC3 now has no trace of dev_dbg()/dev_vdbg() usage. We will rely solely on tracing to debug DWC3. There was also a fix for memory corruption with EP0 when maxpacket size transfers are > 512 bytes. Robert's EP capabilities flags is making EP selection a lot simpler. UDCs are now required to set these flags up when adding endpoints to the framework. Other than these, we have the usual set of miscelaneous cleanups and minor fixes. Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/legacy')
-rw-r--r--drivers/usb/gadget/legacy/Kconfig2
-rw-r--r--drivers/usb/gadget/legacy/acm_ms.c41
-rw-r--r--drivers/usb/gadget/legacy/audio.c41
-rw-r--r--drivers/usb/gadget/legacy/cdc2.c35
-rw-r--r--drivers/usb/gadget/legacy/dbgp.c10
-rw-r--r--drivers/usb/gadget/legacy/ether.c36
-rw-r--r--drivers/usb/gadget/legacy/g_ffs.c32
-rw-r--r--drivers/usb/gadget/legacy/gmidi.c8
-rw-r--r--drivers/usb/gadget/legacy/hid.c37
-rw-r--r--drivers/usb/gadget/legacy/mass_storage.c41
-rw-r--r--drivers/usb/gadget/legacy/multi.c43
-rw-r--r--drivers/usb/gadget/legacy/ncm.c34
-rw-r--r--drivers/usb/gadget/legacy/nokia.c105
-rw-r--r--drivers/usb/gadget/legacy/printer.c51
-rw-r--r--drivers/usb/gadget/legacy/serial.c38
-rw-r--r--drivers/usb/gadget/legacy/zero.c41
16 files changed, 356 insertions, 239 deletions
diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig
index d5a7102de696..4d682ad7bf23 100644
--- a/drivers/usb/gadget/legacy/Kconfig
+++ b/drivers/usb/gadget/legacy/Kconfig
@@ -339,6 +339,7 @@ config USB_CDC_COMPOSITE
config USB_G_NOKIA
tristate "Nokia composite gadget"
depends on PHONET
+ depends on BLOCK
select USB_LIBCOMPOSITE
select USB_U_SERIAL
select USB_U_ETHER
@@ -346,6 +347,7 @@ config USB_G_NOKIA
select USB_F_OBEX
select USB_F_PHONET
select USB_F_ECM
+ select USB_F_MASS_STORAGE
help
The Nokia composite gadget provides support for acm, obex
and phonet in only one composite gadget driver.
diff --git a/drivers/usb/gadget/legacy/acm_ms.c b/drivers/usb/gadget/legacy/acm_ms.c
index 1194b09ae746..4b158e2d1e57 100644
--- a/drivers/usb/gadget/legacy/acm_ms.c
+++ b/drivers/usb/gadget/legacy/acm_ms.c
@@ -58,21 +58,7 @@ static struct usb_device_descriptor device_desc = {
/*.bNumConfigurations = DYNAMIC*/
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /*
- * REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@@ -200,10 +186,6 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
if (status)
goto fail;
- status = fsg_common_set_nluns(opts->common, config.nluns);
- if (status)
- goto fail_set_nluns;
-
status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
if (status)
goto fail_set_cdev;
@@ -225,10 +207,21 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail_string_ids;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register our configuration */
status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config);
if (status < 0)
- goto fail_string_ids;
+ goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@@ -236,11 +229,12 @@ static int acm_ms_bind(struct usb_composite_dev *cdev)
return 0;
/* error recovery */
+fail_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail_string_ids:
fsg_common_remove_luns(opts->common);
fail_set_cdev:
- fsg_common_free_luns(opts->common);
-fail_set_nluns:
fsg_common_free_buffers(opts->common);
fail:
usb_put_function_instance(fi_msg);
@@ -255,6 +249,9 @@ static int acm_ms_unbind(struct usb_composite_dev *cdev)
usb_put_function_instance(fi_msg);
usb_put_function(f_acm);
usb_put_function_instance(f_acm_inst);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/audio.c b/drivers/usb/gadget/legacy/audio.c
index f289caf18a45..685cf3b4b78f 100644
--- a/drivers/usb/gadget/legacy/audio.c
+++ b/drivers/usb/gadget/legacy/audio.c
@@ -15,7 +15,6 @@
#include <linux/module.h>
#include <linux/usb/composite.h>
-#include "gadget_chips.h"
#define DRIVER_DESC "Linux USB Audio Gadget"
#define DRIVER_VERSION "Feb 2, 2012"
@@ -124,7 +123,7 @@ static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x200),
+ .bcdUSB = cpu_to_le16(0x200),
#ifdef CONFIG_GADGET_UAC1
.bDeviceClass = USB_CLASS_PER_INTERFACE,
@@ -141,8 +140,8 @@ static struct usb_device_descriptor device_desc = {
* we support. (As does bNumConfigurations.) These values can
* also be overridden by module parameters.
*/
- .idVendor = __constant_cpu_to_le16(AUDIO_VENDOR_NUM),
- .idProduct = __constant_cpu_to_le16(AUDIO_PRODUCT_NUM),
+ .idVendor = cpu_to_le16(AUDIO_VENDOR_NUM),
+ .idProduct = cpu_to_le16(AUDIO_PRODUCT_NUM),
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
@@ -150,20 +149,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/*-------------------------------------------------------------------------*/
@@ -259,14 +245,28 @@ static int audio_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc)
+ goto fail;
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
status = usb_add_config(cdev, &audio_config_driver, audio_do_config);
if (status < 0)
- goto fail;
+ goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
INFO(cdev, "%s, version: %s\n", DRIVER_DESC, DRIVER_VERSION);
return 0;
+fail_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail:
#ifndef CONFIG_GADGET_UAC1
usb_put_function_instance(fi_uac2);
@@ -289,6 +289,9 @@ static int audio_unbind(struct usb_composite_dev *cdev)
if (!IS_ERR_OR_NULL(fi_uac2))
usb_put_function_instance(fi_uac2);
#endif
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/cdc2.c b/drivers/usb/gadget/legacy/cdc2.c
index afd3e37921a7..ecd8c8d62f2e 100644
--- a/drivers/usb/gadget/legacy/cdc2.c
+++ b/drivers/usb/gadget/legacy/cdc2.c
@@ -60,21 +60,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
-
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@@ -193,10 +179,21 @@ static int cdc_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail1;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register our configuration */
status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config);
if (status < 0)
- goto fail1;
+ goto fail2;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@@ -204,6 +201,9 @@ static int cdc_bind(struct usb_composite_dev *cdev)
return 0;
+fail2:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail1:
usb_put_function_instance(fi_serial);
fail:
@@ -219,6 +219,9 @@ static int cdc_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_ecm);
if (!IS_ERR_OR_NULL(fi_ecm))
usb_put_function_instance(fi_ecm);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c
index 204b10b1a7e7..5231a32aef55 100644
--- a/drivers/usb/gadget/legacy/dbgp.c
+++ b/drivers/usb/gadget/legacy/dbgp.c
@@ -35,10 +35,10 @@ static struct dbgp {
static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
+ .bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_VENDOR_SPEC,
- .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID),
- .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID),
+ .idVendor = cpu_to_le16(DRIVER_VENDOR_ID),
+ .idProduct = cpu_to_le16(DRIVER_PRODUCT_ID),
.bNumConfigurations = 1,
};
@@ -251,7 +251,7 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget)
dbgp.i_ep->driver_data = gadget;
i_desc.wMaxPacketSize =
- __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
+ cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
dbgp.o_ep = usb_ep_autoconfig(gadget, &o_desc);
if (!dbgp.o_ep) {
@@ -262,7 +262,7 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget)
dbgp.o_ep->driver_data = gadget;
o_desc.wMaxPacketSize =
- __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
+ cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
dbg_desc.bDebugInEndpoint = i_desc.bEndpointAddress;
dbg_desc.bDebugOutEndpoint = o_desc.bEndpointAddress;
diff --git a/drivers/usb/gadget/legacy/ether.c b/drivers/usb/gadget/legacy/ether.c
index a3323dca218f..31e9160223e9 100644
--- a/drivers/usb/gadget/legacy/ether.c
+++ b/drivers/usb/gadget/legacy/ether.c
@@ -171,20 +171,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
static struct usb_string strings_dev[] = {
[USB_GADGET_MANUFACTURER_IDX].s = "",
@@ -416,17 +403,28 @@ static int eth_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail1;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register our configuration(s); RNDIS first, if it's used */
if (has_rndis()) {
status = usb_add_config(cdev, &rndis_config_driver,
rndis_do_config);
if (status < 0)
- goto fail1;
+ goto fail2;
}
status = usb_add_config(cdev, &eth_config_driver, eth_do_config);
if (status < 0)
- goto fail1;
+ goto fail2;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@@ -434,6 +432,9 @@ static int eth_bind(struct usb_composite_dev *cdev)
return 0;
+fail2:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail1:
if (has_rndis())
usb_put_function_instance(fi_rndis);
@@ -463,6 +464,9 @@ static int eth_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_geth);
usb_put_function_instance(fi_geth);
}
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/g_ffs.c b/drivers/usb/gadget/legacy/g_ffs.c
index e821931c965c..320a81b2baa6 100644
--- a/drivers/usb/gadget/legacy/g_ffs.c
+++ b/drivers/usb/gadget/legacy/g_ffs.c
@@ -88,21 +88,7 @@ MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
module_param_array_named(functions, func_names, charp, &func_num, 0);
MODULE_PARM_DESC(functions, "USB Functions list");
-static const struct usb_descriptor_header *gfs_otg_desc[] = {
- (const struct usb_descriptor_header *)
- &(const struct usb_otg_descriptor) {
- .bLength = sizeof(struct usb_otg_descriptor),
- .bDescriptorType = USB_DT_OTG,
-
- /*
- * REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
- },
-
- NULL
-};
+static const struct usb_descriptor_header *gfs_otg_desc[2];
/* String IDs are assigned dynamically */
static struct usb_string gfs_strings[] = {
@@ -412,6 +398,17 @@ static int gfs_bind(struct usb_composite_dev *cdev)
goto error_rndis;
gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(cdev->gadget) && !gfs_otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc)
+ goto error_rndis;
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ gfs_otg_desc[0] = usb_desc;
+ gfs_otg_desc[1] = NULL;
+ }
+
for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
struct gfs_configuration *c = gfs_configurations + i;
int sid = USB_GADGET_FIRST_AVAIL_IDX + i;
@@ -432,6 +429,8 @@ static int gfs_bind(struct usb_composite_dev *cdev)
/* TODO */
error_unbind:
+ kfree(gfs_otg_desc[0]);
+ gfs_otg_desc[0] = NULL;
error_rndis:
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
usb_put_function_instance(fi_rndis);
@@ -473,6 +472,9 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
for (i = 0; i < N_CONF * func_num; ++i)
usb_put_function(*(f_ffs[0] + i));
+ kfree(gfs_otg_desc[0]);
+ gfs_otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/gmidi.c b/drivers/usb/gadget/legacy/gmidi.c
index da19c486b61e..8a18348ae86e 100644
--- a/drivers/usb/gadget/legacy/gmidi.c
+++ b/drivers/usb/gadget/legacy/gmidi.c
@@ -35,8 +35,6 @@
#include <linux/usb/audio.h>
#include <linux/usb/midi.h>
-#include "gadget_chips.h"
-
#include "u_midi.h"
/*-------------------------------------------------------------------------*/
@@ -88,10 +86,10 @@ MODULE_PARM_DESC(out_ports, "Number of MIDI output ports");
static struct usb_device_descriptor device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
+ .bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
- .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
- .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
+ .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM),
+ .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM),
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
.bNumConfigurations = 1,
diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c
index 2baa572686c6..7e5d2c48476e 100644
--- a/drivers/usb/gadget/legacy/hid.c
+++ b/drivers/usb/gadget/legacy/hid.c
@@ -19,7 +19,6 @@
#include <linux/usb/composite.h>
#include <linux/usb/g_hid.h>
-#include "gadget_chips.h"
#define DRIVER_DESC "HID Gadget"
#define DRIVER_VERSION "2010/03/16"
@@ -68,21 +67,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
-
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@@ -186,16 +171,30 @@ static int hid_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto put;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register our configuration */
status = usb_add_config(cdev, &config_driver, do_config);
if (status < 0)
- goto put;
+ goto free_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
return 0;
+free_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
put:
list_for_each_entry(m, &hidg_func_list, node) {
if (m == n)
@@ -213,6 +212,10 @@ static int hid_unbind(struct usb_composite_dev *cdev)
usb_put_function(n->f);
usb_put_function_instance(n->fi);
}
+
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c
index e7bfb081f111..bda3c519110f 100644
--- a/drivers/usb/gadget/legacy/mass_storage.c
+++ b/drivers/usb/gadget/legacy/mass_storage.c
@@ -64,21 +64,7 @@ static struct usb_device_descriptor msg_device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /*
- * REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
static struct usb_string strings_dev[] = {
[USB_GADGET_MANUFACTURER_IDX].s = "",
@@ -191,10 +177,6 @@ static int msg_bind(struct usb_composite_dev *cdev)
if (status)
goto fail;
- status = fsg_common_set_nluns(opts->common, config.nluns);
- if (status)
- goto fail_set_nluns;
-
fsg_common_set_ops(opts->common, &ops);
status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
@@ -214,9 +196,20 @@ static int msg_bind(struct usb_composite_dev *cdev)
goto fail_string_ids;
msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc)
+ goto fail_string_ids;
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
if (status < 0)
- goto fail_string_ids;
+ goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&cdev->gadget->dev,
@@ -224,11 +217,12 @@ static int msg_bind(struct usb_composite_dev *cdev)
set_bit(0, &msg_registered);
return 0;
+fail_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail_string_ids:
fsg_common_remove_luns(opts->common);
fail_set_cdev:
- fsg_common_free_luns(opts->common);
-fail_set_nluns:
fsg_common_free_buffers(opts->common);
fail:
usb_put_function_instance(fi_msg);
@@ -243,6 +237,9 @@ static int msg_unbind(struct usb_composite_dev *cdev)
if (!IS_ERR(fi_msg))
usb_put_function_instance(fi_msg);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/multi.c b/drivers/usb/gadget/legacy/multi.c
index b21b51f0c9fa..4fe794ddcd49 100644
--- a/drivers/usb/gadget/legacy/multi.c
+++ b/drivers/usb/gadget/legacy/multi.c
@@ -78,21 +78,7 @@ static struct usb_device_descriptor device_desc = {
.idProduct = cpu_to_le16(MULTI_PRODUCT_NUM),
};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &(struct usb_otg_descriptor){
- .bLength = sizeof(struct usb_otg_descriptor),
- .bDescriptorType = USB_DT_OTG,
-
- /*
- * REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
- },
- NULL,
-};
-
+static const struct usb_descriptor_header *otg_desc[2];
enum {
MULTI_STRING_RNDIS_CONFIG_IDX = USB_GADGET_FIRST_AVAIL_IDX,
@@ -407,10 +393,6 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
if (status)
goto fail2;
- status = fsg_common_set_nluns(fsg_opts->common, config.nluns);
- if (status)
- goto fail_set_nluns;
-
status = fsg_common_set_cdev(fsg_opts->common, cdev, config.can_stall);
if (status)
goto fail_set_cdev;
@@ -429,14 +411,25 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
goto fail_string_ids;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail_string_ids;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register configurations */
status = rndis_config_register(cdev);
if (unlikely(status < 0))
- goto fail_string_ids;
+ goto fail_otg_desc;
status = cdc_config_register(cdev);
if (unlikely(status < 0))
- goto fail_string_ids;
+ goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
/* we're done */
@@ -445,11 +438,12 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
/* error recovery */
+fail_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail_string_ids:
fsg_common_remove_luns(fsg_opts->common);
fail_set_cdev:
- fsg_common_free_luns(fsg_opts->common);
-fail_set_nluns:
fsg_common_free_buffers(fsg_opts->common);
fail2:
usb_put_function_instance(fi_msg);
@@ -490,6 +484,9 @@ static int multi_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_ecm);
usb_put_function_instance(fi_ecm);
#endif
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/ncm.c b/drivers/usb/gadget/legacy/ncm.c
index 6ce7421412e9..2bae4381332d 100644
--- a/drivers/usb/gadget/legacy/ncm.c
+++ b/drivers/usb/gadget/legacy/ncm.c
@@ -69,20 +69,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@@ -171,16 +158,30 @@ static int gncm_bind(struct usb_composite_dev *cdev)
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
status = usb_add_config(cdev, &ncm_config_driver,
ncm_do_config);
if (status < 0)
- goto fail;
+ goto fail1;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s\n", DRIVER_DESC);
return 0;
+fail1:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail:
usb_put_function_instance(f_ncm_inst);
return status;
@@ -192,6 +193,9 @@ static int gncm_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_ncm);
if (!IS_ERR_OR_NULL(f_ncm_inst))
usb_put_function_instance(f_ncm_inst);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/nokia.c b/drivers/usb/gadget/legacy/nokia.c
index 4bb498a38a1c..8b3f6fb1825d 100644
--- a/drivers/usb/gadget/legacy/nokia.c
+++ b/drivers/usb/gadget/legacy/nokia.c
@@ -23,7 +23,7 @@
#include "u_ether.h"
#include "u_phonet.h"
#include "u_ecm.h"
-#include "gadget_chips.h"
+#include "f_mass_storage.h"
/* Defines */
@@ -34,6 +34,29 @@ USB_GADGET_COMPOSITE_OPTIONS();
USB_ETHERNET_MODULE_PARAMETERS();
+static struct fsg_module_parameters fsg_mod_data = {
+ .stall = 0,
+ .luns = 2,
+ .removable_count = 2,
+ .removable = { 1, 1, },
+};
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
+
+#else
+
+/*
+ * Number of buffers we will use.
+ * 2 is usually enough for good buffering pipeline
+ */
+#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
+
+#endif /* CONFIG_USB_DEBUG */
+
+FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
+
#define NOKIA_VENDOR_ID 0x0421 /* Nokia */
#define NOKIA_PRODUCT_ID 0x01c8 /* Nokia Gadget */
@@ -66,10 +89,10 @@ static struct usb_gadget_strings *dev_strings[] = {
static struct usb_device_descriptor device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
+ .bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_COMM,
- .idVendor = __constant_cpu_to_le16(NOKIA_VENDOR_ID),
- .idProduct = __constant_cpu_to_le16(NOKIA_PRODUCT_ID),
+ .idVendor = cpu_to_le16(NOKIA_VENDOR_ID),
+ .idProduct = cpu_to_le16(NOKIA_PRODUCT_ID),
.bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM),
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
@@ -94,6 +117,8 @@ static struct usb_function *f_obex1_cfg2;
static struct usb_function *f_obex2_cfg2;
static struct usb_function *f_phonet_cfg1;
static struct usb_function *f_phonet_cfg2;
+static struct usb_function *f_msg_cfg1;
+static struct usb_function *f_msg_cfg2;
static struct usb_configuration nokia_config_500ma_driver = {
@@ -117,6 +142,7 @@ static struct usb_function_instance *fi_ecm;
static struct usb_function_instance *fi_obex1;
static struct usb_function_instance *fi_obex2;
static struct usb_function_instance *fi_phonet;
+static struct usb_function_instance *fi_msg;
static int nokia_bind_config(struct usb_configuration *c)
{
@@ -125,6 +151,8 @@ static int nokia_bind_config(struct usb_configuration *c)
struct usb_function *f_obex1 = NULL;
struct usb_function *f_ecm;
struct usb_function *f_obex2 = NULL;
+ struct usb_function *f_msg;
+ struct fsg_opts *fsg_opts;
int status = 0;
int obex1_stat = -1;
int obex2_stat = -1;
@@ -160,6 +188,12 @@ static int nokia_bind_config(struct usb_configuration *c)
goto err_get_ecm;
}
+ f_msg = usb_get_function(fi_msg);
+ if (IS_ERR(f_msg)) {
+ status = PTR_ERR(f_msg);
+ goto err_get_msg;
+ }
+
if (!IS_ERR_OR_NULL(f_phonet)) {
phonet_stat = usb_add_function(c, f_phonet);
if (phonet_stat)
@@ -187,21 +221,36 @@ static int nokia_bind_config(struct usb_configuration *c)
pr_debug("could not bind ecm config %d\n", status);
goto err_ecm;
}
+
+ fsg_opts = fsg_opts_from_func_inst(fi_msg);
+
+ status = fsg_common_run_thread(fsg_opts->common);
+ if (status)
+ goto err_msg;
+
+ status = usb_add_function(c, f_msg);
+ if (status)
+ goto err_msg;
+
if (c == &nokia_config_500ma_driver) {
f_acm_cfg1 = f_acm;
f_ecm_cfg1 = f_ecm;
f_phonet_cfg1 = f_phonet;
f_obex1_cfg1 = f_obex1;
f_obex2_cfg1 = f_obex2;
+ f_msg_cfg1 = f_msg;
} else {
f_acm_cfg2 = f_acm;
f_ecm_cfg2 = f_ecm;
f_phonet_cfg2 = f_phonet;
f_obex1_cfg2 = f_obex1;
f_obex2_cfg2 = f_obex2;
+ f_msg_cfg2 = f_msg;
}
return status;
+err_msg:
+ usb_remove_function(c, f_ecm);
err_ecm:
usb_remove_function(c, f_acm);
err_conf:
@@ -211,6 +260,8 @@ err_conf:
usb_remove_function(c, f_obex1);
if (!phonet_stat)
usb_remove_function(c, f_phonet);
+ usb_put_function(f_msg);
+err_get_msg:
usb_put_function(f_ecm);
err_get_ecm:
usb_put_function(f_acm);
@@ -227,6 +278,8 @@ err_get_acm:
static int nokia_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
+ struct fsg_opts *fsg_opts;
+ struct fsg_config fsg_config;
int status;
status = usb_string_ids_tab(cdev, strings_dev);
@@ -238,7 +291,7 @@ static int nokia_bind(struct usb_composite_dev *cdev)
nokia_config_500ma_driver.iConfiguration = status;
nokia_config_100ma_driver.iConfiguration = status;
- if (!gadget_supports_altsettings(gadget)) {
+ if (!gadget_is_altset_supported(gadget)) {
status = -ENODEV;
goto err_usb;
}
@@ -267,11 +320,42 @@ static int nokia_bind(struct usb_composite_dev *cdev)
goto err_acm_inst;
}
+ fi_msg = usb_get_function_instance("mass_storage");
+ if (IS_ERR(fi_msg)) {
+ status = PTR_ERR(fi_msg);
+ goto err_ecm_inst;
+ }
+
+ /* set up mass storage function */
+ fsg_config_from_params(&fsg_config, &fsg_mod_data, fsg_num_buffers);
+ fsg_config.vendor_name = "Nokia";
+ fsg_config.product_name = "N900";
+
+ fsg_opts = fsg_opts_from_func_inst(fi_msg);
+ fsg_opts->no_configfs = true;
+
+ status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers);
+ if (status)
+ goto err_msg_inst;
+
+ status = fsg_common_set_cdev(fsg_opts->common, cdev, fsg_config.can_stall);
+ if (status)
+ goto err_msg_buf;
+
+ fsg_common_set_sysfs(fsg_opts->common, true);
+
+ status = fsg_common_create_luns(fsg_opts->common, &fsg_config);
+ if (status)
+ goto err_msg_buf;
+
+ fsg_common_set_inquiry_string(fsg_opts->common, fsg_config.vendor_name,
+ fsg_config.product_name);
+
/* finally register the configuration */
status = usb_add_config(cdev, &nokia_config_500ma_driver,
nokia_bind_config);
if (status < 0)
- goto err_ecm_inst;
+ goto err_msg_luns;
status = usb_add_config(cdev, &nokia_config_100ma_driver,
nokia_bind_config);
@@ -292,6 +376,12 @@ err_put_cfg1:
if (!IS_ERR_OR_NULL(f_phonet_cfg1))
usb_put_function(f_phonet_cfg1);
usb_put_function(f_ecm_cfg1);
+err_msg_luns:
+ fsg_common_remove_luns(fsg_opts->common);
+err_msg_buf:
+ fsg_common_free_buffers(fsg_opts->common);
+err_msg_inst:
+ usb_put_function_instance(fi_msg);
err_ecm_inst:
usb_put_function_instance(fi_ecm);
err_acm_inst:
@@ -325,7 +415,10 @@ static int nokia_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_acm_cfg2);
usb_put_function(f_ecm_cfg1);
usb_put_function(f_ecm_cfg2);
+ usb_put_function(f_msg_cfg1);
+ usb_put_function(f_msg_cfg2);
+ usb_put_function_instance(fi_msg);
usb_put_function_instance(fi_ecm);
if (!IS_ERR(fi_obex2))
usb_put_function_instance(fi_obex2);
diff --git a/drivers/usb/gadget/legacy/printer.c b/drivers/usb/gadget/legacy/printer.c
index 1ce7df1060a5..a22d30a4def1 100644
--- a/drivers/usb/gadget/legacy/printer.c
+++ b/drivers/usb/gadget/legacy/printer.c
@@ -19,8 +19,6 @@
#include <linux/usb/gadget.h>
#include <linux/usb/g_printer.h>
-#include "gadget_chips.h"
-
USB_GADGET_COMPOSITE_OPTIONS();
#define DRIVER_DESC "Printer Gadget"
@@ -82,16 +80,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
- .bmAttributes = USB_OTG_SRP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/*-------------------------------------------------------------------------*/
@@ -136,7 +125,6 @@ static int printer_do_config(struct usb_configuration *c)
usb_gadget_set_selfpowered(gadget);
if (gadget_is_otg(gadget)) {
- otg_descriptor.bmAttributes |= USB_OTG_HNP;
printer_cfg_driver.descriptors = otg_desc;
printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
@@ -174,21 +162,39 @@ static int printer_bind(struct usb_composite_dev *cdev)
opts->q_len = QLEN;
ret = usb_string_ids_tab(cdev, strings);
- if (ret < 0) {
- usb_put_function_instance(fi_printer);
- return ret;
- }
+ if (ret < 0)
+ goto fail_put_func_inst;
+
device_desc.iManufacturer = strings[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings[USB_GADGET_PRODUCT_IDX].id;
device_desc.iSerialNumber = strings[USB_GADGET_SERIAL_IDX].id;
- ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config);
- if (ret) {
- usb_put_function_instance(fi_printer);
- return ret;
+ if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc) {
+ ret = -ENOMEM;
+ goto fail_put_func_inst;
+ }
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
}
+
+ ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config);
+ if (ret)
+ goto fail_free_otg_desc;
+
usb_composite_overwrite_options(cdev, &coverwrite);
return ret;
+
+fail_free_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+fail_put_func_inst:
+ usb_put_function_instance(fi_printer);
+ return ret;
}
static int printer_unbind(struct usb_composite_dev *cdev)
@@ -196,6 +202,9 @@ static int printer_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_printer);
usb_put_function_instance(fi_printer);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/serial.c b/drivers/usb/gadget/legacy/serial.c
index 8b7528f9b78e..c5d42e0347a9 100644
--- a/drivers/usb/gadget/legacy/serial.c
+++ b/drivers/usb/gadget/legacy/serial.c
@@ -17,7 +17,6 @@
#include <linux/tty_flip.h>
#include "u_serial.h"
-#include "gadget_chips.h"
/* Defines */
@@ -79,20 +78,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/*-------------------------------------------------------------------------*/
@@ -191,6 +177,18 @@ static int gs_bind(struct usb_composite_dev *cdev)
serial_config_driver.iConfiguration = status;
if (gadget_is_otg(cdev->gadget)) {
+ if (!otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc) {
+ status = -ENOMEM;
+ goto fail;
+ }
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
serial_config_driver.descriptors = otg_desc;
serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
@@ -208,13 +206,15 @@ static int gs_bind(struct usb_composite_dev *cdev)
"gser");
}
if (status < 0)
- goto fail;
+ goto fail1;
usb_composite_overwrite_options(cdev, &coverwrite);
INFO(cdev, "%s\n", GS_VERSION_NAME);
return 0;
-
+fail1:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail:
return status;
}
@@ -227,6 +227,10 @@ static int gs_unbind(struct usb_composite_dev *cdev)
usb_put_function(f_serial[i]);
usb_put_function_instance(fi_serial[i]);
}
+
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/zero.c b/drivers/usb/gadget/legacy/zero.c
index c986e8addb90..37a410056fed 100644
--- a/drivers/usb/gadget/legacy/zero.c
+++ b/drivers/usb/gadget/legacy/zero.c
@@ -121,24 +121,7 @@ static struct usb_device_descriptor device_desc = {
.bNumConfigurations = 2,
};
-#ifdef CONFIG_USB_OTG
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
-#else
-#define otg_desc NULL
-#endif
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
/* default serial number takes at least two packets */
@@ -341,6 +324,18 @@ static int zero_bind(struct usb_composite_dev *cdev)
/* support OTG systems */
if (gadget_is_otg(cdev->gadget)) {
+ if (!otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc) {
+ status = -ENOMEM;
+ goto err_conf_flb;
+ }
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
sourcesink_driver.descriptors = otg_desc;
sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
loopback_driver.descriptors = otg_desc;
@@ -359,12 +354,12 @@ static int zero_bind(struct usb_composite_dev *cdev)
}
status = usb_add_function(&sourcesink_driver, func_ss);
if (status)
- goto err_conf_flb;
+ goto err_free_otg_desc;
usb_ep_autoconfig_reset(cdev->gadget);
status = usb_add_function(&loopback_driver, func_lb);
if (status)
- goto err_conf_flb;
+ goto err_free_otg_desc;
usb_ep_autoconfig_reset(cdev->gadget);
usb_composite_overwrite_options(cdev, &coverwrite);
@@ -373,6 +368,9 @@ static int zero_bind(struct usb_composite_dev *cdev)
return 0;
+err_free_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
err_conf_flb:
usb_put_function(func_lb);
func_lb = NULL;
@@ -397,6 +395,9 @@ static int zero_unbind(struct usb_composite_dev *cdev)
if (!IS_ERR_OR_NULL(func_lb))
usb_put_function(func_lb);
usb_put_function_instance(func_inst_lb);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}