summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/composite.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/composite.c')
-rw-r--r--drivers/usb/gadget/composite.c52
1 files changed, 44 insertions, 8 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 4e3447bbd097..b474499839d3 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -19,6 +19,7 @@
#include <linux/utsname.h>
#include <linux/usb/composite.h>
+#include <linux/usb/otg.h>
#include <asm/unaligned.h>
#include "u_os_desc.h"
@@ -209,6 +210,12 @@ int usb_add_function(struct usb_configuration *config,
function->config = config;
list_add_tail(&function->list, &config->functions);
+ if (function->bind_deactivated) {
+ value = usb_function_deactivate(function);
+ if (value)
+ goto done;
+ }
+
/* REVISIT *require* function->bind? */
if (function->bind) {
value = function->bind(config, function);
@@ -279,7 +286,7 @@ int usb_function_deactivate(struct usb_function *function)
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->deactivations == 0)
- status = usb_gadget_disconnect(cdev->gadget);
+ status = usb_gadget_deactivate(cdev->gadget);
if (status == 0)
cdev->deactivations++;
@@ -311,7 +318,7 @@ int usb_function_activate(struct usb_function *function)
else {
cdev->deactivations--;
if (cdev->deactivations == 0)
- status = usb_gadget_connect(cdev->gadget);
+ status = usb_gadget_activate(cdev->gadget);
}
spin_unlock_irqrestore(&cdev->lock, flags);
@@ -896,7 +903,7 @@ void usb_remove_config(struct usb_composite_dev *cdev,
/* We support strings in multiple languages ... string descriptor zero
* says which languages are supported. The typical case will be that
- * only one language (probably English) is used, with I18N handled on
+ * only one language (probably English) is used, with i18n handled on
* the host side.
*/
@@ -949,7 +956,7 @@ static int get_string(struct usb_composite_dev *cdev,
struct usb_function *f;
int len;
- /* Yes, not only is USB's I18N support probably more than most
+ /* Yes, not only is USB's i18n support probably more than most
* folk will ever care about ... also, it's all supported here.
* (Except for UTF8 support for Unicode's "Astral Planes".)
*/
@@ -1534,6 +1541,32 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
value = min(w_length, (u16) value);
}
break;
+ case USB_DT_OTG:
+ if (gadget_is_otg(gadget)) {
+ struct usb_configuration *config;
+ int otg_desc_len = 0;
+
+ if (cdev->config)
+ config = cdev->config;
+ else
+ config = list_first_entry(
+ &cdev->configs,
+ struct usb_configuration, list);
+ if (!config)
+ goto done;
+
+ if (gadget->otg_caps &&
+ (gadget->otg_caps->otg_rev >= 0x0200))
+ otg_desc_len += sizeof(
+ struct usb_otg20_descriptor);
+ else
+ otg_desc_len += sizeof(
+ struct usb_otg_descriptor);
+
+ value = min_t(int, w_length, otg_desc_len);
+ memcpy(req->buf, config->descriptors[0], value);
+ }
+ break;
}
break;
@@ -1758,10 +1791,13 @@ unknown:
* take such requests too, if that's ever needed: to work
* in config 0, etc.
*/
- list_for_each_entry(f, &cdev->config->functions, list)
- if (f->req_match && f->req_match(f, ctrl))
- goto try_fun_setup;
- f = NULL;
+ if (cdev->config) {
+ list_for_each_entry(f, &cdev->config->functions, list)
+ if (f->req_match && f->req_match(f, ctrl))
+ goto try_fun_setup;
+ f = NULL;
+ }
+
switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_INTERFACE:
if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)