diff options
Diffstat (limited to 'drivers/usb/gadget/composite.c')
-rw-r--r-- | drivers/usb/gadget/composite.c | 52 |
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) |