diff options
Diffstat (limited to 'drivers/usb/gadget')
68 files changed, 1393 insertions, 810 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 58b4657..b474499 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; diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c index 34e12fc..0fafa7a 100644 --- a/drivers/usb/gadget/config.c +++ b/drivers/usb/gadget/config.c @@ -20,6 +20,7 @@ #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> #include <linux/usb/composite.h> +#include <linux/usb/otg.h> /** * usb_descriptor_fillbuf - fill buffer with descriptors @@ -195,3 +196,58 @@ void usb_free_all_descriptors(struct usb_function *f) usb_free_descriptors(f->ss_descriptors); } EXPORT_SYMBOL_GPL(usb_free_all_descriptors); + +struct usb_descriptor_header *usb_otg_descriptor_alloc( + struct usb_gadget *gadget) +{ + struct usb_descriptor_header *otg_desc; + unsigned length = 0; + + if (gadget->otg_caps && (gadget->otg_caps->otg_rev >= 0x0200)) + length = sizeof(struct usb_otg20_descriptor); + else + length = sizeof(struct usb_otg_descriptor); + + otg_desc = kzalloc(length, GFP_KERNEL); + return otg_desc; +} +EXPORT_SYMBOL_GPL(usb_otg_descriptor_alloc); + +int usb_otg_descriptor_init(struct usb_gadget *gadget, + struct usb_descriptor_header *otg_desc) +{ + struct usb_otg_descriptor *otg1x_desc; + struct usb_otg20_descriptor *otg20_desc; + struct usb_otg_caps *otg_caps = gadget->otg_caps; + u8 otg_attributes = 0; + + if (!otg_desc) + return -EINVAL; + + if (otg_caps && otg_caps->otg_rev) { + if (otg_caps->hnp_support) + otg_attributes |= USB_OTG_HNP; + if (otg_caps->srp_support) + otg_attributes |= USB_OTG_SRP; + if (otg_caps->adp_support && (otg_caps->otg_rev >= 0x0200)) + otg_attributes |= USB_OTG_ADP; + } else { + otg_attributes = USB_OTG_SRP | USB_OTG_HNP; + } + + if (otg_caps && (otg_caps->otg_rev >= 0x0200)) { + otg20_desc = (struct usb_otg20_descriptor *)otg_desc; + otg20_desc->bLength = sizeof(struct usb_otg20_descriptor); + otg20_desc->bDescriptorType = USB_DT_OTG; + otg20_desc->bmAttributes = otg_attributes; + otg20_desc->bcdOTG = cpu_to_le16(otg_caps->otg_rev); + } else { + otg1x_desc = (struct usb_otg_descriptor *)otg_desc; + otg1x_desc->bLength = sizeof(struct usb_otg_descriptor); + otg1x_desc->bDescriptorType = USB_DT_OTG; + otg1x_desc->bmAttributes = otg_attributes; + } + + return 0; +} +EXPORT_SYMBOL_GPL(usb_otg_descriptor_init); diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 289e201..294eb74 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -41,6 +41,8 @@ int check_user_usb_string(const char *name, #define MAX_NAME_LEN 40 #define MAX_USB_STRING_LANGS 2 +static const struct usb_descriptor_header *otg_desc[2]; + struct gadget_info { struct config_group group; struct config_group functions_group; @@ -55,9 +57,6 @@ struct gadget_info { struct list_head available_func; const char *udc_name; -#ifdef CONFIG_USB_OTG - struct usb_otg_descriptor otg; -#endif struct usb_composite_driver composite; struct usb_composite_dev cdev; bool use_os_desc; @@ -1376,6 +1375,19 @@ static int configfs_composite_bind(struct usb_gadget *gadget, memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN); } + if (gadget_is_otg(gadget) && !otg_desc[0]) { + struct usb_descriptor_header *usb_desc; + + usb_desc = usb_otg_descriptor_alloc(gadget); + if (!usb_desc) { + ret = -ENOMEM; + goto err_comp_cleanup; + } + usb_otg_descriptor_init(gadget, usb_desc); + otg_desc[0] = usb_desc; + otg_desc[1] = NULL; + } + /* Go through all configs, attach all functions */ list_for_each_entry(c, &gi->cdev.configs, list) { struct config_usb_cfg *cfg; @@ -1383,6 +1395,9 @@ static int configfs_composite_bind(struct usb_gadget *gadget, struct usb_function *tmp; struct gadget_config_name *cn; + if (gadget_is_otg(gadget)) + c->descriptors = otg_desc; + cfg = container_of(c, struct config_usb_cfg, c); if (!list_empty(&cfg->string_list)) { i = 0; @@ -1437,6 +1452,8 @@ static void configfs_composite_unbind(struct usb_gadget *gadget) cdev = get_gadget_data(gadget); gi = container_of(cdev, struct gadget_info, cdev); + kfree(otg_desc[0]); + otg_desc[0] = NULL; purge_configs_funcs(gi); composite_dev_cleanup(cdev); usb_ep_autoconfig_reset(cdev->gadget); @@ -1510,12 +1527,6 @@ static struct config_group *gadgets_make( if (!gi->composite.gadget_driver.function) goto err; -#ifdef CONFIG_USB_OTG - gi->otg.bLength = sizeof(struct usb_otg_descriptor); - gi->otg.bDescriptorType = USB_DT_OTG; - gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP; -#endif - config_group_init_type_name(&gi->group, name, &gadget_root_type); return &gi->group; diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 919cdfd..978435a 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -20,186 +20,6 @@ #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> -#include "gadget_chips.h" - -/* - * This should work with endpoints from controller drivers sharing the - * same endpoint naming convention. By example: - * - * - ep1, ep2, ... address is fixed, not direction or type - * - ep1in, ep2out, ... address and direction are fixed, not type - * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction - * - ep1in-bulk, ep2out-iso, ... all three are fixed - * - ep-* ... no functionality restrictions - * - * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal. - * Less common restrictions are implied by gadget_is_*(). - * - * NOTE: each endpoint is unidirectional, as specified by its USB - * descriptor; and isn't specific to a configuration or altsetting. - */ -static int -ep_matches ( - struct usb_gadget *gadget, - struct usb_ep *ep, - struct usb_endpoint_descriptor *desc, - struct usb_ss_ep_comp_descriptor *ep_comp -) -{ - u8 type; - const char *tmp; - u16 max; - - int num_req_streams = 0; - - /* endpoint already claimed? */ - if (NULL != ep->driver_data) - return 0; - - /* only support ep0 for portable CONTROL traffic */ - type = usb_endpoint_type(desc); - if (USB_ENDPOINT_XFER_CONTROL == type) - return 0; - - /* some other naming convention */ - if ('e' != ep->name[0]) - return 0; - - /* type-restriction: "-iso", "-bulk", or "-int". - * direction-restriction: "in", "out". - */ - if ('-' != ep->name[2]) { - tmp = strrchr (ep->name, '-'); - if (tmp) { - switch (type) { - case USB_ENDPOINT_XFER_INT: - /* bulk endpoints handle interrupt transfers, - * except the toggle-quirky iso-synch kind - */ - if ('s' == tmp[2]) // == "-iso" - return 0; - /* for now, avoid PXA "interrupt-in"; - * it's documented as never using DATA1. - */ - if (gadget_is_pxa (gadget) - && 'i' == tmp [1]) - return 0; - break; - case USB_ENDPOINT_XFER_BULK: - if ('b' != tmp[1]) // != "-bulk" - return 0; - break; - case USB_ENDPOINT_XFER_ISOC: - if ('s' != tmp[2]) // != "-iso" - return 0; - } - } else { - tmp = ep->name + strlen (ep->name); - } - - /* direction-restriction: "..in-..", "out-.." */ - tmp--; - if (!isdigit (*tmp)) { - if (desc->bEndpointAddress & USB_DIR_IN) { - if ('n' != *tmp) - return 0; - } else { - if ('t' != *tmp) - return 0; - } - } - } - - /* - * Get the number of required streams from the EP companion - * descriptor and see if the EP matches it - */ - if (usb_endpoint_xfer_bulk(desc)) { - if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) { - num_req_streams = ep_comp->bmAttributes & 0x1f; - if (num_req_streams > ep->max_streams) - return 0; - } - - } - - /* - * If the protocol driver hasn't yet decided on wMaxPacketSize - * and wants to know the maximum possible, provide the info. - */ - if (desc->wMaxPacketSize == 0) - desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit); - - /* endpoint maxpacket size is an input parameter, except for bulk - * where it's an output parameter representing the full speed limit. - * the usb spec fixes high speed bulk maxpacket at 512 bytes. - */ - max = 0x7ff & usb_endpoint_maxp(desc); - switch (type) { - case USB_ENDPOINT_XFER_INT: - /* INT: limit 64 bytes full speed, 1024 high/super speed */ - if (!gadget_is_dualspeed(gadget) && max > 64) - return 0; - /* FALLTHROUGH */ - - case USB_ENDPOINT_XFER_ISOC: - /* ISO: limit 1023 bytes full speed, 1024 high/super speed */ - if (ep->maxpacket_limit < max) - return 0; - if (!gadget_is_dualspeed(gadget) && max > 1023) - return 0; - - /* BOTH: "high bandwidth" works only at high speed */ - if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) { - if (!gadget_is_dualspeed(gadget)) - return 0; - /* configure your hardware with enough buffering!! */ - } - break; - } - - /* MATCH!! */ - - /* report address */ - desc->bEndpointAddress &= USB_DIR_IN; - if (isdigit (ep->name [2])) { - u8 num = simple_strtoul (&ep->name [2], NULL, 10); - desc->bEndpointAddress |= num; - } else if (desc->bEndpointAddress & USB_DIR_IN) { - if (++gadget->in_epnum > 15) - return 0; - desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum; - } else { - if (++gadget->out_epnum > 15) - return 0; - desc->bEndpointAddress |= gadget->out_epnum; - } - - /* report (variable) full speed bulk maxpacket */ - if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) { - int size = ep->maxpacket_limit; - - /* min() doesn't work on bitfields with gcc-3.5 */ - if (size > 64) - size = 64; - desc->wMaxPacketSize = cpu_to_le16(size); - } - ep->address = desc->bEndpointAddress; - return 1; -} - -static struct usb_ep * -find_ep (struct usb_gadget *gadget, const char *name) -{ - struct usb_ep *ep; - - list_for_each_entry (ep, &gadget->ep_list, ep_list) { - if (0 == strcmp (ep->name, name)) - return ep; - } - return NULL; -} - /** * usb_ep_autoconfig_ss() - choose an endpoint matching the ep * descriptor and ep companion descriptor @@ -240,7 +60,7 @@ find_ep (struct usb_gadget *gadget, const char *name) * updated with the assigned number of streams if it is * different from the original value. To prevent the endpoint * from being returned by a later autoconfig call, claim it by - * assigning ep->driver_data to some non-null value. + * assigning ep->claimed to true. * * On failure, this returns a null endpoint descriptor. */ @@ -255,74 +75,58 @@ struct usb_ep *usb_ep_autoconfig_ss( type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; - /* First, apply chip-specific "best usage" knowledge. - * This might make a good usb_gadget_ops hook ... - */ - if (gadget_is_net2280(gadget)) { - char name[8]; - - if (type == USB_ENDPOINT_XFER_INT) { - /* ep-e, ep-f are PIO with only 64 byte fifos */ - ep = find_ep(gadget, "ep-e"); - if (ep && ep_matches(gadget, ep, desc, ep_comp)) - goto found_ep; - ep = find_ep(gadget, "ep-f"); - if (ep && ep_matches(gadget, ep, desc, ep_comp)) - goto found_ep; - } - - /* USB3380: use same address for usb and hardware endpoints */ - snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc), - usb_endpoint_dir_in(desc) ? "in" : "out"); - ep = find_ep(gadget, name); - if (ep && ep_matches(gadget, ep, desc, ep_comp)) + if (gadget->ops->match_ep) { + ep = gadget->ops->match_ep(gadget, desc, ep_comp); + if (ep) goto found_ep; - } else if (gadget_is_goku (gadget)) { - if (USB_ENDPOINT_XFER_INT == type) { - /* single buffering is enough */ - ep = find_ep(gadget, "ep3-bulk"); - if (ep && ep_matches(gadget, ep, desc, ep_comp)) - goto found_ep; - } else if (USB_ENDPOINT_XFER_BULK == type - && (USB_DIR_IN & desc->bEndpointAddress)) { - /* DMA may be available */ - ep = find_ep(gadget, "ep2-bulk"); - if (ep && ep_matches(gadget, ep, desc, - ep_comp)) - goto found_ep; - } - -#ifdef CONFIG_BLACKFIN - } else if (gadget_is_musbhdrc(gadget)) { - if ((USB_ENDPOINT_XFER_BULK == type) || - (USB_ENDPOINT_XFER_ISOC == type)) { - if (USB_DIR_IN & desc->bEndpointAddress) - ep = find_ep (gadget, "ep5in"); - else - ep = find_ep (gadget, "ep6out"); - } else if (USB_ENDPOINT_XFER_INT == type) { - if (USB_DIR_IN & desc->bEndpointAddress) - ep = find_ep(gadget, "ep1in"); - else - ep = find_ep(gadget, "ep2out"); - } else - ep = NULL; - if (ep && ep_matches(gadget, ep, desc, ep_comp)) - goto found_ep; -#endif } /* Second, look at endpoints until an unclaimed one looks usable */ list_for_each_entry (ep, &gadget->ep_list, ep_list) { - if (ep_matches(gadget, ep, desc, ep_comp)) + if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp)) goto found_ep; } /* Fail */ return NULL; found_ep: + + /* + * If the protocol driver hasn't yet decided on wMaxPacketSize + * and wants to know the maximum possible, provide the info. + */ + if (desc->wMaxPacketSize == 0) + desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit); + + /* report address */ + desc->bEndpointAddress &= USB_DIR_IN; + if (isdigit(ep->name[2])) { + u8 num = simple_strtoul(&ep->name[2], NULL, 10); + desc->bEndpointAddress |= num; + } else if (desc->bEndpointAddress & USB_DIR_IN) { + if (++gadget->in_epnum > 15) + return NULL; + desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum; + } else { + if (++gadget->out_epnum > 15) + return NULL; + desc->bEndpointAddress |= gadget->out_epnum; + } + + /* report (variable) full speed bulk maxpacket */ + if ((type == USB_ENDPOINT_XFER_BULK) && !ep_comp) { + int size = ep->maxpacket_limit; + + /* min() doesn't work on bitfields with gcc-3.5 */ + if (size > 64) + size = 64; + desc->wMaxPacketSize = cpu_to_le16(size); + } + + ep->address = desc->bEndpointAddress; ep->desc = NULL; ep->comp_desc = NULL; + ep->claimed = true; return ep; } EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss); @@ -354,7 +158,7 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss); * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value * is initialized as if the endpoint were used at full speed. To prevent * the endpoint from being returned by a later autoconfig call, claim it - * by assigning ep->driver_data to some non-null value. + * by assigning ep->claimed to true. * * On failure, this returns a null endpoint descriptor. */ @@ -373,7 +177,7 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig); * * Use this for devices where one configuration may need to assign * endpoint resources very differently from the next one. It clears - * state such as ep->driver_data and the record of assigned endpoints + * state such as ep->claimed and the record of assigned endpoints * used by usb_ep_autoconfig(). */ void usb_ep_autoconfig_reset (struct usb_gadget *gadget) @@ -381,7 +185,7 @@ void usb_ep_autoconfig_reset (struct usb_gadget *gadget) struct usb_ep *ep; list_for_each_entry (ep, &gadget->ep_list, ep_list) { - ep->driver_data = NULL; + ep->claimed = false; } gadget->in_epnum = 0; gadget->out_epnum = 0; diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c index aad8165..be9df09 100644 --- a/drivers/usb/gadget/function/f_acm.c +++ b/drivers/usb/gadget/function/f_acm.c @@ -21,7 +21,6 @@ #include <linux/err.h> #include "u_serial.h" -#include "gadget_chips.h" /* diff --git a/drivers/usb/gadget/function/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c index 798760f..7b7424f 100644 --- a/drivers/usb/gadget/function/f_ecm.c +++ b/drivers/usb/gadget/function/f_ecm.c @@ -585,8 +585,8 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) /* Enable zlps by default for ECM conformance; * override for musb_hdrc (avoids txdma ovhead). */ - ecm->port.is_zlp_ok = !(gadget_is_musbhdrc(cdev->gadget) - ); + ecm->port.is_zlp_ok = + gadget_is_zlp_supported(cdev->gadget); ecm->port.cdc_filter = DEFAULT_FILTER; DBG(cdev, "activate ecm\n"); net = gether_connect(&ecm->port); diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 6e7be91..adc6d52 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -2897,11 +2897,17 @@ static int ffs_func_bind(struct usb_configuration *c, struct usb_function *f) { struct f_fs_opts *ffs_opts = ffs_do_functionfs_bind(f, c); + struct ffs_function *func = ffs_func_from_usb(f); + int ret; if (IS_ERR(ffs_opts)) return PTR_ERR(ffs_opts); - return _ffs_func_bind(c, f); + ret = _ffs_func_bind(c, f); + if (ret && !--ffs_opts->refcnt) + functionfs_unbind(func->ffs); + + return ret; } diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index f7f35a3..6df9715 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -699,6 +699,10 @@ static inline int hidg_get_minor(void) int ret; ret = ida_simple_get(&hidg_ida, 0, 0, GFP_KERNEL); + if (ret >= HIDG_MINORS) { + ida_simple_remove(&hidg_ida, ret); + ret = -ENODEV; + } return ret; } diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c index 39f49f1..6e2fe63 100644 --- a/drivers/usb/gadget/function/f_loopback.c +++ b/drivers/usb/gadget/function/f_loopback.c @@ -28,11 +28,6 @@ * This takes messages of various sizes written OUT to a device, and loops * them back so they can be read IN from it. It has been used by certain * test applications. It supports limited testing of data queueing logic. - * - * - * This is currently packaged as a configuration driver, which can't be - * combined with other functions to make composite devices. However, it - * can be combined with other independent configurations. */ struct f_loopback { struct usb_function function; diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index f936268..a6eb537 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -54,7 +54,7 @@ * following fields: * * nluns Number of LUNs function have (anywhere from 1 - * to FSG_MAX_LUNS which is 8). + * to FSG_MAX_LUNS). * luns An array of LUN configuration values. This * should be filled for each LUN that * function will include (ie. for "nluns" @@ -214,12 +214,12 @@ #include <linux/string.h> #include <linux/freezer.h> #include <linux/module.h> +#include <linux/uaccess.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> #include <linux/usb/composite.h> -#include "gadget_chips.h" #include "configfs.h" @@ -279,9 +279,8 @@ struct fsg_common { int cmnd_size; u8 cmnd[MAX_COMMAND_SIZE]; - unsigned int nluns; unsigned int lun; - struct fsg_lun **luns; + struct fsg_lun *luns[FSG_MAX_LUNS]; struct fsg_lun *curlun; unsigned int bulk_out_maxpacket; @@ -490,6 +489,16 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) spin_unlock(&common->lock); } +static int _fsg_common_get_max_lun(struct fsg_common *common) +{ + int i = ARRAY_SIZE(common->luns) - 1; + + while (i >= 0 && !common->luns[i]) + --i; + + return i; +} + static int fsg_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) { @@ -533,7 +542,7 @@ static int fsg_setup(struct usb_function *f, w_length != 1) return -EDOM; VDBG(fsg, "get max LUN\n"); - *(u8 *)req->buf = fsg->common->nluns - 1; + *(u8 *)req->buf = _fsg_common_get_max_lun(fsg->common); /* Respond with data/status */ req->length = min((u16)1, w_length); @@ -2131,8 +2140,9 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) } /* Is the CBW meaningful? */ - if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN || - cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { + if (cbw->Lun >= ARRAY_SIZE(common->luns) || + cbw->Flags & ~US_BULK_FLAG_IN || cbw->Length <= 0 || + cbw->Length > MAX_COMMAND_SIZE) { DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " "cmdlen %u\n", cbw->Lun, cbw->Flags, cbw->Length); @@ -2159,7 +2169,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) if (common->data_size == 0) common->data_dir = DATA_DIR_NONE; common->lun = cbw->Lun; - if (common->lun < common->nluns) + if (common->lun < ARRAY_SIZE(common->luns)) common->curlun = common->luns[common->lun]; else common->curlun = NULL; @@ -2307,7 +2317,7 @@ reset: } common->running = 1; - for (i = 0; i < common->nluns; ++i) + for (i = 0; i < ARRAY_SIZE(common->luns); ++i) if (common->luns[i]) common->luns[i]->unit_attention_data = SS_RESET_OCCURRED; @@ -2409,7 +2419,7 @@ static void handle_exception(struct fsg_common *common) if (old_state == FSG_STATE_ABORT_BULK_OUT) common->state = FSG_STATE_STATUS_PHASE; else { - for (i = 0; i < common->nluns; ++i) { + for (i = 0; i < ARRAY_SIZE(common->luns); ++i) { curlun = common->luns[i]; if (!curlun) continue; @@ -2453,7 +2463,7 @@ static void handle_exception(struct fsg_common *common) * a waste of time. Ditto for the INTERFACE_CHANGE and * CONFIG_CHANGE cases. */ - /* for (i = 0; i < common->nluns; ++i) */ + /* for (i = 0; i < common->ARRAY_SIZE(common->luns); ++i) */ /* if (common->luns[i]) */ /* common->luns[i]->unit_attention_data = */ /* SS_RESET_OCCURRED; */ @@ -2552,12 +2562,11 @@ static int fsg_main_thread(void *common_) if (!common->ops || !common->ops->thread_exits || common->ops->thread_exits(common) < 0) { - struct fsg_lun **curlun_it = common->luns; - unsigned i = common->nluns; + int i; down_write(&common->filesem); - for (; i--; ++curlun_it) { - struct fsg_lun *curlun = *curlun_it; + for (i = 0; i < ARRAY_SIZE(common->luns); --i) { + struct fsg_lun *curlun = common->luns[i]; if (!curlun || !fsg_lun_is_open(curlun)) continue; @@ -2676,6 +2685,7 @@ static struct fsg_common *fsg_common_setup(struct fsg_common *common) init_completion(&common->thread_notifier); init_waitqueue_head(&common->fsg_wait); common->state = FSG_STATE_TERMINATED; + memset(common->luns, 0, sizeof(common->luns)); return common; } @@ -2742,9 +2752,9 @@ error_release: } EXPORT_SYMBOL_GPL(fsg_common_set_num_buffers); -void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs) +void fsg_common_remove_lun(struct fsg_lun *lun) { - if (sysfs) + if (device_is_registered(&lun->dev)) device_unregister(&lun->dev); fsg_lun_close(lun); kfree(lun); @@ -2757,48 +2767,16 @@ static void _fsg_common_remove_luns(struct fsg_common *common, int n) for (i = 0; i < n; ++i) if (common->luns[i]) { - fsg_common_remove_lun(common->luns[i], common->sysfs); + fsg_common_remove_lun(common->luns[i]); common->luns[i] = NULL; } } -EXPORT_SYMBOL_GPL(fsg_common_remove_luns); void fsg_common_remove_luns(struct fsg_common *common) { - _fsg_common_remove_luns(common, common->nluns); -} - -void fsg_common_free_luns(struct fsg_common *common) -{ - fsg_common_remove_luns(common); - kfree(common->luns); - common->luns = NULL; -} -EXPORT_SYMBOL_GPL(fsg_common_free_luns); - -int fsg_common_set_nluns(struct fsg_common *common, int nluns) -{ - struct fsg_lun **curlun; - - /* Find out how many LUNs there should be */ - if (nluns < 1 || nluns > FSG_MAX_LUNS) { - pr_err("invalid number of LUNs: %u\n", nluns); - return -EINVAL; - } - - curlun = kcalloc(FSG_MAX_LUNS, sizeof(*curlun), GFP_KERNEL); - if (unlikely(!curlun)) - return -ENOMEM; - - if (common->luns) - fsg_common_free_luns(common); - - common->luns = curlun; - common->nluns = nluns; - - return 0; + _fsg_common_remove_luns(common, ARRAY_SIZE(common->luns)); } -EXPORT_SYMBOL_GPL(fsg_common_set_nluns); +EXPORT_SYMBOL_GPL(fsg_common_remove_luns); void fsg_common_set_ops(struct fsg_common *common, const struct fsg_operations *ops) @@ -2836,7 +2814,8 @@ int fsg_common_set_cdev(struct fsg_common *common, * halt bulk endpoints correctly. If one of them is present, * disable stalls. */ - common->can_stall = can_stall && !(gadget_is_at91(common->gadget)); + common->can_stall = can_stall && + gadget_is_stall_supported(common->gadget); return 0; } @@ -2880,7 +2859,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, char *pathbuf, *p; int rc = -ENOMEM; - if (!common->nluns || !common->luns) + if (id >= ARRAY_SIZE(common->luns)) return -ENODEV; if (common->luns[id]) @@ -2949,7 +2928,7 @@ int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, return 0; error_lun: - if (common->sysfs) + if (device_is_registered(&lun->dev)) device_unregister(&lun->dev); fsg_lun_close(lun); common->luns[id] = NULL; @@ -2964,14 +2943,16 @@ int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg) char buf[8]; /* enough for 100000000 different numbers, decimal */ int i, rc; - for (i = 0; i < common->nluns; ++i) { + fsg_common_remove_luns(common); + + for (i = 0; i < cfg->nluns; ++i) { snprintf(buf, sizeof(buf), "lun%d", i); rc = fsg_common_create_lun(common, &cfg->luns[i], i, buf, NULL); if (rc) goto fail; } - pr_info("Number of LUNs=%d\n", common->nluns); + pr_info("Number of LUNs=%d\n", cfg->nluns); return 0; @@ -3020,6 +3001,7 @@ EXPORT_SYMBOL_GPL(fsg_common_run_thread); static void fsg_common_release(struct kref *ref) { struct fsg_common *common = container_of(ref, struct fsg_common, ref); + int i; /* If the thread isn't already dead, tell it to exit now */ if (common->state != FSG_STATE_TERMINATED) { @@ -3027,22 +3009,14 @@ static void fsg_common_release(struct kref *ref) wait_for_completion(&common->thread_notifier); } - if (likely(common->luns)) { - struct fsg_lun **lun_it = common->luns; - unsigned i = common->nluns; - - /* In error recovery common->nluns may be zero. */ - for (; i; --i, ++lun_it) { - struct fsg_lun *lun = *lun_it; - if (!lun) - continue; - fsg_lun_close(lun); - if (common->sysfs) - device_unregister(&lun->dev); - kfree(lun); - } - - kfree(common->luns); + for (i = 0; i < ARRAY_SIZE(common->luns); ++i) { + struct fsg_lun *lun = common->luns[i]; + if (!lun) + continue; + fsg_lun_close(lun); + if (device_is_registered(&lun->dev)) + device_unregister(&lun->dev); + kfree(lun); } _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); @@ -3056,6 +3030,7 @@ static void fsg_common_release(struct kref *ref) static int fsg_bind(struct usb_configuration *c, struct usb_function *f) { struct fsg_dev *fsg = fsg_from_func(f); + struct fsg_common *common = fsg->common; struct usb_gadget *gadget = c->cdev->gadget; int i; struct usb_ep *ep; @@ -3063,6 +3038,13 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) int ret; struct fsg_opts *opts; + /* Don't allow to bind if we don't have at least one LUN */ + ret = _fsg_common_get_max_lun(common); + if (ret < 0) { + pr_err("There should be at least one LUN.\n"); + return -EINVAL; + } + opts = fsg_opts_from_func_inst(f->fi); if (!opts->no_configfs) { ret = fsg_common_set_cdev(fsg->common, c->cdev, @@ -3080,7 +3062,7 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) /* New interface */ i = usb_interface_id(c, f); if (i < 0) - return i; + goto fail; fsg_intf_desc.bInterfaceNumber = i; fsg->interface_number = i; @@ -3123,7 +3105,14 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) autoconf_fail: ERROR(fsg, "unable to autoconfigure all endpoints\n"); - return -ENOTSUPP; + i = -ENOTSUPP; +fail: + /* terminate the thread */ + if (fsg->common->state != FSG_STATE_TERMINATED) { + raise_exception(fsg->common, FSG_STATE_EXIT); + wait_for_completion(&fsg->common->thread_notifier); + } + return i; } /****************************** ALLOCATE FUNCTION *************************/ @@ -3355,7 +3344,7 @@ static void fsg_lun_drop(struct config_group *group, struct config_item *item) unregister_gadget_item(gadget); } - fsg_common_remove_lun(lun_opts->lun, fsg_opts->common->sysfs); + fsg_common_remove_lun(lun_opts->lun); fsg_opts->common->luns[lun_opts->lun_id] = NULL; lun_opts->lun_id = 0; mutex_unlock(&fsg_opts->lock); @@ -3509,14 +3498,11 @@ static struct usb_function_instance *fsg_alloc_inst(void) rc = PTR_ERR(opts->common); goto release_opts; } - rc = fsg_common_set_nluns(opts->common, FSG_MAX_LUNS); - if (rc) - goto release_opts; rc = fsg_common_set_num_buffers(opts->common, CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS); if (rc) - goto release_luns; + goto release_opts; pr_info(FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); @@ -3524,6 +3510,9 @@ static struct usb_function_instance *fsg_alloc_inst(void) config.removable = true; rc = fsg_common_create_lun(opts->common, &config, 0, "lun.0", (const char **)&opts->func_inst.group.cg_item.ci_name); + if (rc) + goto release_buffers; + opts->lun0.lun = opts->common->luns[0]; opts->lun0.lun_id = 0; config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type); @@ -3534,8 +3523,8 @@ static struct usb_function_instance *fsg_alloc_inst(void) return &opts->func_inst; -release_luns: - kfree(opts->common->luns); +release_buffers: + fsg_common_free_buffers(opts->common); release_opts: kfree(opts); return ERR_PTR(rc); @@ -3561,23 +3550,12 @@ static struct usb_function *fsg_alloc(struct usb_function_instance *fi) struct fsg_opts *opts = fsg_opts_from_func_inst(fi); struct fsg_common *common = opts->common; struct fsg_dev *fsg; - unsigned nluns, i; fsg = kzalloc(sizeof(*fsg), GFP_KERNEL); if (unlikely(!fsg)) return ERR_PTR(-ENOMEM); mutex_lock(&opts->lock); - if (!opts->refcnt) { - for (nluns = i = 0; i < FSG_MAX_LUNS; ++i) - if (common->luns[i]) - nluns = i + 1; - if (!nluns) - pr_warn("No LUNS defined, continuing anyway\n"); - else - common->nluns = nluns; - pr_info("Number of LUNs=%u\n", common->nluns); - } opts->refcnt++; mutex_unlock(&opts->lock); diff --git a/drivers/usb/gadget/function/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h index b4866fc..445df67 100644 --- a/drivers/usb/gadget/function/f_mass_storage.h +++ b/drivers/usb/gadget/function/f_mass_storage.h @@ -137,14 +137,10 @@ void fsg_common_free_buffers(struct fsg_common *common); int fsg_common_set_cdev(struct fsg_common *common, struct usb_composite_dev *cdev, bool can_stall); -void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs); +void fsg_common_remove_lun(struct fsg_lun *lun); void fsg_common_remove_luns(struct fsg_common *common); -void fsg_common_free_luns(struct fsg_common *common); - -int fsg_common_set_nluns(struct fsg_common *common, int nluns); - void fsg_common_set_ops(struct fsg_common *common, const struct fsg_operations *ops); diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index ad50a67..a287a48 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -329,6 +329,10 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) unsigned i; int err; + /* For Control Device interface we do nothing */ + if (intf == 0) + return 0; + err = f_midi_start_ep(midi, f, midi->in_ep); if (err) return err; diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index bdcda9f..3f05c6bd 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -853,9 +853,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) /* Enable zlps by default for NCM conformance; * override for musb_hdrc (avoids txdma ovhead) */ - ncm->port.is_zlp_ok = !( - gadget_is_musbhdrc(cdev->gadget) - ); + ncm->port.is_zlp_ok = + gadget_is_zlp_supported(cdev->gadget); ncm->port.cdc_filter = DEFAULT_FILTER; DBG(cdev, "activate ncm\n"); net = gether_connect(&ncm->port); diff --git a/drivers/usb/gadget/function/f_obex.c b/drivers/usb/gadget/function/f_obex.c index a1b79c5..5460426 100644 --- a/drivers/usb/gadget/function/f_obex.c +++ b/drivers/usb/gadget/function/f_obex.c @@ -20,7 +20,6 @@ #include <linux/module.h> #include "u_serial.h" -#include "gadget_chips.h" /* @@ -37,7 +36,6 @@ struct f_obex { u8 data_id; u8 cur_alt; u8 port_num; - u8 can_activate; }; static inline struct f_obex *func_to_obex(struct usb_function *f) @@ -268,9 +266,6 @@ static void obex_connect(struct gserial *g) struct usb_composite_dev *cdev = g->func.config->cdev; int status; - if (!obex->can_activate) - return; - status = usb_function_activate(&g->func); if (status) dev_dbg(&cdev->gadget->dev, @@ -284,9 +279,6 @@ static void obex_disconnect(struct gserial *g) struct usb_composite_dev *cdev = g->func.config->cdev; int status; - if (!obex->can_activate) - return; - status = usb_function_deactivate(&g->func); if (status) dev_dbg(&cdev->gadget->dev, @@ -304,7 +296,7 @@ static inline bool can_support_obex(struct usb_configuration *c) * * Altsettings are mandatory, however... */ - if (!gadget_supports_altsettings(c->cdev->gadget)) + if (!gadget_is_altset_supported(c->cdev->gadget)) return false; /* everything else is *probably* fine ... */ @@ -378,17 +370,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f) if (status) goto fail; - /* Avoid letting this gadget enumerate until the userspace - * OBEX server is active. - */ - status = usb_function_deactivate(f); - if (status < 0) - WARNING(cdev, "obex ttyGS%d: can't prevent enumeration, %d\n", - obex->port_num, status); - else - obex->can_activate = true; - - dev_dbg(&cdev->gadget->dev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n", obex->port_num, gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", @@ -529,6 +510,7 @@ static struct usb_function *obex_alloc(struct usb_function_instance *fi) obex->port.func.get_alt = obex_get_alt; obex->port.func.disable = obex_disable; obex->port.func.free_func = obex_free; + obex->port.func.bind_deactivated = true; return &obex->port.func; } diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 44173df..8e2b6be 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -804,6 +804,8 @@ done: static void printer_reset_interface(struct printer_dev *dev) { + unsigned long flags; + if (dev->interface < 0) return; @@ -815,9 +817,11 @@ static void printer_reset_interface(struct printer_dev *dev) if (dev->out_ep->desc) usb_ep_disable(dev->out_ep); + spin_lock_irqsave(&dev->lock, flags); dev->in_ep->desc = NULL; dev->out_ep->desc = NULL; dev->interface = -1; + spin_unlock_irqrestore(&dev->lock, flags); } /* Change our operational Interface. */ @@ -1131,13 +1135,10 @@ static int printer_func_set_alt(struct usb_function *f, static void printer_func_disable(struct usb_function *f) { struct printer_dev *dev = func_to_printer(f); - unsigned long flags; DBG(dev, "%s\n", __func__); - spin_lock_irqsave(&dev->lock, flags); printer_reset_interface(dev); - spin_unlock_irqrestore(&dev->lock, flags); } static inline struct f_printer_opts @@ -1248,7 +1249,15 @@ static struct config_item_type printer_func_type = { static inline int gprinter_get_minor(void) { - return ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL); + int ret; + + ret = ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL); + if (ret >= PRINTER_MINORS) { + ida_simple_remove(&printer_ida, ret); + ret = -ENODEV; + } + + return ret; } static inline void gprinter_put_minor(int minor) diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c index 2e02dfa..1d162e2 100644 --- a/drivers/usb/gadget/function/f_serial.c +++ b/drivers/usb/gadget/function/f_serial.c @@ -16,7 +16,6 @@ #include <linux/device.h> #include "u_serial.h" -#include "gadget_chips.h" /* diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c index 3a5ae99..cbfaf86 100644 --- a/drivers/usb/gadget/function/f_sourcesink.c +++ b/drivers/usb/gadget/function/f_sourcesink.c @@ -20,7 +20,6 @@ #include <linux/err.h> #include "g_zero.h" -#include "gadget_chips.h" #include "u_f.h" /* @@ -42,11 +41,6 @@ * queues are relatively independent, will receive a range of packet sizes, * and can often be made to run out completely. Those issues are important * when stress testing peripheral controller drivers. - * - * - * This is currently packaged as a configuration driver, which can't be - * combined with other functions to make composite devices. However, it - * can be combined with other independent configurations. */ struct f_sourcesink { struct usb_function function; diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 6d3eb8b..f8de7ea 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -975,6 +975,29 @@ free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) "%s:%d Error!\n", __func__, __LINE__); } +static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts, + struct usb_endpoint_descriptor *ep_desc, + unsigned int factor, bool is_playback) +{ + int chmask, srate, ssize; + u16 max_packet_size; + + if (is_playback) { + chmask = uac2_opts->p_chmask; + srate = uac2_opts->p_srate; + ssize = uac2_opts->p_ssize; + } else { + chmask = uac2_opts->c_chmask; + srate = uac2_opts->c_srate; + ssize = uac2_opts->c_ssize; + } + + max_packet_size = num_channels(chmask) * ssize * + DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1))); + ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_packet_size, + le16_to_cpu(ep_desc->wMaxPacketSize))); +} + static int afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) { @@ -1070,10 +1093,14 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) uac2->p_prm.uac2 = uac2; uac2->c_prm.uac2 = uac2; + /* Calculate wMaxPacketSize according to audio bandwidth */ + set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true); + set_ep_max_packet_size(uac2_opts, &fs_epout_desc, 1000, false); + set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true); + set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false); + hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; - hs_epout_desc.wMaxPacketSize = fs_epout_desc.wMaxPacketSize; hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; - hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize; ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL); if (ret) @@ -1162,14 +1189,14 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) factor = 1000; } else { ep_desc = &hs_epin_desc; - factor = 125; + factor = 8000; } /* pre-compute some values for iso_complete() */ uac2->p_framesize = opts->p_ssize * num_channels(opts->p_chmask); rate = opts->p_srate * uac2->p_framesize; - uac2->p_interval = (1 << (ep_desc->bInterval - 1)) * factor; + uac2->p_interval = factor / (1 << (ep_desc->bInterval - 1)); uac2->p_pktsize = min_t(unsigned int, rate / uac2->p_interval, prm->max_psize); diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index cf0df8f..743be34 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -733,12 +733,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) uvc->control_req->complete = uvc_function_ep0_complete; uvc->control_req->context = uvc; - /* Avoid letting this gadget enumerate until the userspace server is - * active. - */ - if ((ret = usb_function_deactivate(f)) < 0) - goto error; - if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) { printk(KERN_INFO "v4l2_device_register failed\n"); goto error; @@ -949,6 +943,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi) uvc->func.disable = uvc_function_disable; uvc->func.setup = uvc_function_setup; uvc->func.free_func = uvc_free; + uvc->func.bind_deactivated = true; return &uvc->func; } diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h index 70c8914..c3544e6 100644 --- a/drivers/usb/gadget/function/storage_common.h +++ b/drivers/usb/gadget/function/storage_common.h @@ -123,7 +123,7 @@ static inline bool fsg_lun_is_open(struct fsg_lun *curlun) #define FSG_BUFLEN ((u32)16384) /* Maximal number of LUNs supported in mass storage function */ -#define FSG_MAX_LUNS 8 +#define FSG_MAX_LUNS 16 enum fsg_buffer_state { BUF_STATE_EMPTY = 0, diff --git a/drivers/usb/gadget/function/u_ether.h b/drivers/usb/gadget/function/u_ether.h index 334b389..c77145b 100644 --- a/drivers/usb/gadget/function/u_ether.h +++ b/drivers/usb/gadget/function/u_ether.h @@ -20,8 +20,6 @@ #include <linux/usb/cdc.h> #include <linux/netdevice.h> -#include "gadget_chips.h" - #define QMULT_DEFAULT 5 /* @@ -259,7 +257,7 @@ void gether_disconnect(struct gether *); /* Some controllers can't support CDC Ethernet (ECM) ... */ static inline bool can_support_ecm(struct usb_gadget *gadget) { - if (!gadget_supports_altsettings(gadget)) + if (!gadget_is_altset_supported(gadget)) return false; /* Everything else is *presumably* fine ... but this is a bit diff --git a/drivers/usb/gadget/function/u_uac1.h b/drivers/usb/gadget/function/u_uac1.h index fe386df..5c2ac8e 100644 --- a/drivers/usb/gadget/function/u_uac1.h +++ b/drivers/usb/gadget/function/u_uac1.h @@ -21,8 +21,6 @@ #include <sound/pcm.h> #include <sound/pcm_params.h> -#include "gadget_chips.h" - #define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p" #define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c" #define FILE_CONTROL "/dev/snd/controlC0" diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig index d5a7102..4d682ad 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 1194b09..4b158e2 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 f289caf..685cf3b 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 afd3e37..ecd8c8d 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 204b10b..5231a32 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 a3323dc..31e9160 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, ð_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 e821931..320a81b 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 da19c48..8a18348 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 2baa572..7e5d2c4 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 e7bfb08..bda3c51 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 b21b51f..4fe794d 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 6ce7421..2bae438 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 4bb498a..8b3f6fb 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 1ce7df1..a22d30a 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 8b7528f..c5d42e0 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 c986e8a..37a4100 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; } diff --git a/drivers/usb/gadget/udc/amd5536udc.c b/drivers/usb/gadget/udc/amd5536udc.c index de7e5e2..fdacddb 100644 --- a/drivers/usb/gadget/udc/amd5536udc.c +++ b/drivers/usb/gadget/udc/amd5536udc.c @@ -138,15 +138,82 @@ static DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect, /* endpoint names used for print */ static const char ep0_string[] = "ep0in"; -static const char *const ep_string[] = { - ep0_string, - "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk", - "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk", - "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk", - "ep15in-bulk", "ep0out", "ep1out-bulk", "ep2out-bulk", "ep3out-bulk", - "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk", - "ep8out-bulk", "ep9out-bulk", "ep10out-bulk", "ep11out-bulk", - "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk" +static const struct { + const char *name; + const struct usb_ep_caps caps; +} ep_info[] = { +#define EP_INFO(_name, _caps) \ + { \ + .name = _name, \ + .caps = _caps, \ + } + + EP_INFO(ep0_string, + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep1in-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep2in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep3in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep4in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep5in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep6in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep7in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep8in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep9in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep10in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep11in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep12in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep13in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep14in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep15in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep0out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep1out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep2out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep3out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep4out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep5out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep6out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep7out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep8out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep9out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep10out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep11out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep12out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep13out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep14out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep15out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + +#undef EP_INFO }; /* DMA usage flag */ @@ -1517,7 +1584,8 @@ static void udc_setup_endpoints(struct udc *dev) for (tmp = 0; tmp < UDC_EP_NUM; tmp++) { ep = &dev->ep[tmp]; ep->dev = dev; - ep->ep.name = ep_string[tmp]; + ep->ep.name = ep_info[tmp].name; + ep->ep.caps = ep_info[tmp].caps; ep->num = tmp; /* txfifo size is calculated at enable time */ ep->txfifo = dev->txfifo; diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c index fc42264..d0d1894 100644 --- a/drivers/usb/gadget/udc/at91_udc.c +++ b/drivers/usb/gadget/udc/at91_udc.c @@ -59,15 +59,34 @@ #define DRIVER_VERSION "3 May 2006" static const char driver_name [] = "at91_udc"; -static const char * const ep_names[] = { - "ep0", - "ep1", - "ep2", - "ep3-int", - "ep4", - "ep5", + +static const struct { + const char *name; + const struct usb_ep_caps caps; +} ep_info[] = { +#define EP_INFO(_name, _caps) \ + { \ + .name = _name, \ + .caps = _caps, \ + } + + EP_INFO("ep0", + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep1", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep2", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep3-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep4", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep5", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + +#undef EP_INFO }; -#define ep0name ep_names[0] + +#define ep0name ep_info[0].name #define VBUS_POLL_TIMEOUT msecs_to_jiffies(1000) @@ -825,6 +844,7 @@ static void udc_reinit(struct at91_udc *udc) INIT_LIST_HEAD(&udc->gadget.ep_list); INIT_LIST_HEAD(&udc->gadget.ep0->ep_list); + udc->gadget.quirk_stall_not_supp = 1; for (i = 0; i < NUM_ENDPOINTS; i++) { struct at91_ep *ep = &udc->ep[i]; @@ -1830,7 +1850,8 @@ static int at91udc_probe(struct platform_device *pdev) for (i = 0; i < NUM_ENDPOINTS; i++) { ep = &udc->ep[i]; - ep->ep.name = ep_names[i]; + ep->ep.name = ep_info[i].name; + ep->ep.caps = ep_info[i].caps; ep->ep.ops = &at91_ep_ops; ep->udc = udc; ep->int_mask = BIT(i); diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 4095cce..3dfada8 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -22,7 +22,6 @@ #include <linux/usb/gadget.h> #include <linux/usb/atmel_usba_udc.h> #include <linux/delay.h> -#include <linux/platform_data/atmel.h> #include <linux/of.h> #include <linux/of_gpio.h> @@ -1989,6 +1988,10 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev, ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc"); ret = of_property_read_string(pp, "name", &name); + if (ret) { + dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret); + goto err; + } ep->ep.name = name; ep->ep_regs = udc->regs + USBA_EPT_BASE(i); @@ -2063,6 +2066,17 @@ static struct usba_ep * usba_udc_pdata(struct platform_device *pdev, ep->can_dma = pdata->ep[i].can_dma; ep->can_isoc = pdata->ep[i].can_isoc; + if (i == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = ep->can_isoc; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; + if (i) list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); } diff --git a/drivers/usb/gadget/udc/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c index 9db968b..8cbb003 100644 --- a/drivers/usb/gadget/udc/bcm63xx_udc.c +++ b/drivers/usb/gadget/udc/bcm63xx_udc.c @@ -44,9 +44,29 @@ #define DRV_MODULE_NAME "bcm63xx_udc" static const char bcm63xx_ep0name[] = "ep0"; -static const char *const bcm63xx_ep_name[] = { - bcm63xx_ep0name, - "ep1in-bulk", "ep2out-bulk", "ep3in-int", "ep4out-int", + +static const struct { + const char *name; + const struct usb_ep_caps caps; +} bcm63xx_ep_info[] = { +#define EP_INFO(_name, _caps) \ + { \ + .name = _name, \ + .caps = _caps, \ + } + + EP_INFO(bcm63xx_ep0name, + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep1in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep2out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep3in-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep4out-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_OUT)), + +#undef EP_INFO }; static bool use_fullspeed; @@ -943,7 +963,8 @@ static int bcm63xx_init_udc_hw(struct bcm63xx_udc *udc) for (i = 0; i < BCM63XX_NUM_EP; i++) { struct bcm63xx_ep *bep = &udc->bep[i]; - bep->ep.name = bcm63xx_ep_name[i]; + bep->ep.name = bcm63xx_ep_info[i].name; + bep->ep.caps = bcm63xx_ep_info[i].caps; bep->ep_num = i; bep->ep.ops = &bcm63xx_udc_ep_ops; list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list); diff --git a/drivers/usb/gadget/udc/bdc/bdc.h b/drivers/usb/gadget/udc/bdc/bdc.h index dc18a20..916d471 100644 --- a/drivers/usb/gadget/udc/bdc/bdc.h +++ b/drivers/usb/gadget/udc/bdc/bdc.h @@ -290,7 +290,7 @@ struct bdc_sr { __le32 offset[4]; }; -/* bd_table: contigous bd's in a table */ +/* bd_table: contiguous bd's in a table */ struct bd_table { struct bdc_bd *start_bd; /* dma address of start bd of table*/ diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.c b/drivers/usb/gadget/udc/bdc/bdc_ep.c index b04980c..d1b8153 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_ep.c +++ b/drivers/usb/gadget/udc/bdc/bdc_ep.c @@ -779,7 +779,7 @@ static int ep_dequeue(struct bdc_ep *ep, struct bdc_req *req) /* The current hw dequeue pointer */ tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(0)); deq_ptr_64 = tmp_32; - tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(1)); + tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS1(0)); deq_ptr_64 |= ((u64)tmp_32 << 32); /* we have the dma addr of next bd that will be fetched by hardware */ @@ -1952,12 +1952,18 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir) ep->bdc = bdc; ep->dir = dir; + if (dir) + ep->usb_ep.caps.dir_in = true; + else + ep->usb_ep.caps.dir_out = true; + /* ep->ep_num is the index inside bdc_ep */ if (epnum == 1) { ep->ep_num = 1; bdc->bdc_ep_array[ep->ep_num] = ep; snprintf(ep->name, sizeof(ep->name), "ep%d", epnum - 1); usb_ep_set_maxpacket_limit(&ep->usb_ep, EP0_MAX_PKT_SIZE); + ep->usb_ep.caps.type_control = true; ep->comp_desc = NULL; bdc->gadget.ep0 = &ep->usb_ep; } else { @@ -1971,6 +1977,9 @@ static int init_ep(struct bdc *bdc, u32 epnum, u32 dir) dir & 1 ? "in" : "out"); usb_ep_set_maxpacket_limit(&ep->usb_ep, 1024); + ep->usb_ep.caps.type_iso = true; + ep->usb_ep.caps.type_bulk = true; + ep->usb_ep.caps.type_int = true; ep->usb_ep.max_streams = 0; list_add_tail(&ep->usb_ep.ep_list, &bdc->gadget.ep_list); } diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 181112c..1379ad4 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -127,23 +127,87 @@ static inline struct dummy_request *usb_request_to_dummy_request static const char ep0name[] = "ep0"; -static const char *const ep_name[] = { - ep0name, /* everyone has ep0 */ +static const struct { + const char *name; + const struct usb_ep_caps caps; +} ep_info[] = { +#define EP_INFO(_name, _caps) \ + { \ + .name = _name, \ + .caps = _caps, \ + } + /* everyone has ep0 */ + EP_INFO(ep0name, + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), /* act like a pxa250: fifteen fixed function endpoints */ - "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int", - "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int", - "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso", - "ep15in-int", - + EP_INFO("ep1in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep2out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep3in-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep4out-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep5in-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep6in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep7out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep8in-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep9out-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep10in-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep11in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep12out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep13in-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep14out-iso", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep15in-int", + USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)), /* or like sa1100: two fixed function endpoints */ - "ep1out-bulk", "ep2in-bulk", - + EP_INFO("ep1out-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep2in-bulk", + USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)), /* and now some generic EPs so we have enough in multi config */ - "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in", - "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out", + EP_INFO("ep3out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep4in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep5out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep6out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep7in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep8out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep9in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep10out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep11out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep12in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep13out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep14in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep15out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + +#undef EP_INFO }; -#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) + +#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_info) /*-------------------------------------------------------------------------*/ @@ -938,9 +1002,10 @@ static void init_dummy_udc_hw(struct dummy *dum) for (i = 0; i < DUMMY_ENDPOINTS; i++) { struct dummy_ep *ep = &dum->ep[i]; - if (!ep_name[i]) + if (!ep_info[i].name) break; - ep->ep.name = ep_name[i]; + ep->ep.name = ep_info[i].name; + ep->ep.caps = ep_info[i].caps; ep->ep.ops = &dummy_ep_ops; list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list); ep->halted = ep->wedged = ep->already_seen = @@ -1684,7 +1749,7 @@ static void dummy_timer(unsigned long _dum_hcd) } for (i = 0; i < DUMMY_ENDPOINTS; i++) { - if (!ep_name[i]) + if (!ep_info[i].name) break; dum->ep[i].already_seen = 0; } diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c index 1137e33..6ba122c 100644 --- a/drivers/usb/gadget/udc/fotg210-udc.c +++ b/drivers/usb/gadget/udc/fotg210-udc.c @@ -384,25 +384,15 @@ static void fotg210_ep0_queue(struct fotg210_ep *ep, return; } if (ep->dir_in) { /* if IN */ - if (req->req.length) { - fotg210_start_dma(ep, req); - } else { - pr_err("%s : req->req.length = 0x%x\n", - __func__, req->req.length); - } + fotg210_start_dma(ep, req); if ((req->req.length == req->req.actual) || (req->req.actual < ep->ep.maxpacket)) fotg210_done(ep, req, 0); } else { /* OUT */ - if (!req->req.length) { - fotg210_done(ep, req, 0); - } else { - u32 value = ioread32(ep->fotg210->reg + - FOTG210_DMISGR0); + u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR0); - value &= ~DMISGR0_MCX_OUT_INT; - iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0); - } + value &= ~DMISGR0_MCX_OUT_INT; + iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0); } } @@ -1153,6 +1143,17 @@ static int fotg210_udc_probe(struct platform_device *pdev) ep->ep.name = fotg210_ep_name[i]; ep->ep.ops = &fotg210_ep_ops; usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0); + + if (i == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; } usb_ep_set_maxpacket_limit(&fotg210->ep[0]->ep, 0x40); fotg210->gadget.ep0 = &fotg210->ep[0]->ep; diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c index e0822f1..5fb6f8b 100644 --- a/drivers/usb/gadget/udc/fsl_qe_udc.c +++ b/drivers/usb/gadget/udc/fsl_qe_udc.c @@ -2417,6 +2417,17 @@ static int qe_ep_config(struct qe_udc *udc, unsigned char pipe_num) strcpy(ep->name, ep_name[pipe_num]); ep->ep.name = ep_name[pipe_num]; + if (pipe_num == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; + ep->ep.ops = &qe_ep_ops; ep->stopped = 1; usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0); diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index c60022b..aab5221 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -2313,6 +2313,19 @@ static int struct_ep_setup(struct fsl_udc *udc, unsigned char index, ep->ep.ops = &fsl_ep_ops; ep->stopped = 0; + if (index == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + if (index & 1) + ep->ep.caps.dir_in = true; + else + ep->ep.caps.dir_out = true; + /* for ep0: maxP defined in desc * for other eps, maxP is set by epautoconfig() called by gadget layer */ diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c index 3970f45..948845c 100644 --- a/drivers/usb/gadget/udc/fusb300_udc.c +++ b/drivers/usb/gadget/udc/fusb300_udc.c @@ -1450,6 +1450,17 @@ static int fusb300_probe(struct platform_device *pdev) ep->ep.name = fusb300_ep_name[i]; ep->ep.ops = &fusb300_ep_ops; usb_ep_set_maxpacket_limit(&ep->ep, HS_BULK_MAX_PACKET_SIZE); + + if (i == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; } usb_ep_set_maxpacket_limit(&fusb300->ep[0]->ep, HS_CTL_MAX_PACKET_SIZE); fusb300->ep[0]->epnum = 0; diff --git a/drivers/usb/gadget/udc/gadget_chips.h b/drivers/usb/gadget/udc/gadget_chips.h deleted file mode 100644 index bcd04bc..0000000 --- a/drivers/usb/gadget/udc/gadget_chips.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * USB device controllers have lots of quirks. Use these macros in - * gadget drivers or other code that needs to deal with them, and which - * autoconfigures instead of using early binding to the hardware. - * - * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by - * some config file that gets updated as new hardware is supported. - * (And avoiding all runtime comparisons in typical one-choice configs!) - * - * NOTE: some of these controller drivers may not be available yet. - * Some are available on 2.4 kernels; several are available, but not - * yet pushed in the 2.6 mainline tree. - */ - -#ifndef __GADGET_CHIPS_H -#define __GADGET_CHIPS_H - -#include <linux/usb/gadget.h> - -/* - * NOTICE: the entries below are alphabetical and should be kept - * that way. - * - * Always be sure to add new entries to the correct position or - * accept the bashing later. - * - * If you have forgotten the alphabetical order let VIM/EMACS - * do that for you. - */ -#define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name)) -#define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name)) -#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name)) -#define gadget_is_net2280(g) (!strcmp("net2280", (g)->name)) -#define gadget_is_pxa(g) (!strcmp("pxa25x_udc", (g)->name)) -#define gadget_is_pxa27x(g) (!strcmp("pxa27x_udc", (g)->name)) - -/** - * gadget_supports_altsettings - return true if altsettings work - * @gadget: the gadget in question - */ -static inline bool gadget_supports_altsettings(struct usb_gadget *gadget) -{ - /* PXA 21x/25x/26x has no altsettings at all */ - if (gadget_is_pxa(gadget)) - return false; - - /* PXA 27x and 3xx have *broken* altsetting support */ - if (gadget_is_pxa27x(gadget)) - return false; - - /* Everything else is *presumably* fine ... */ - return true; -} - -#endif /* __GADGET_CHIPS_H */ diff --git a/drivers/usb/gadget/udc/goku_udc.c b/drivers/usb/gadget/udc/goku_udc.c index 9e8d842..1fdfec1 100644 --- a/drivers/usb/gadget/udc/goku_udc.c +++ b/drivers/usb/gadget/udc/goku_udc.c @@ -990,6 +990,35 @@ static int goku_get_frame(struct usb_gadget *_gadget) return -EOPNOTSUPP; } +static struct usb_ep *goku_match_ep(struct usb_gadget *g, + struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *ep_comp) +{ + struct goku_udc *dev = to_goku_udc(g); + struct usb_ep *ep; + + switch (usb_endpoint_type(desc)) { + case USB_ENDPOINT_XFER_INT: + /* single buffering is enough */ + ep = &dev->ep[3].ep; + if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp)) + return ep; + break; + case USB_ENDPOINT_XFER_BULK: + if (usb_endpoint_dir_in(desc)) { + /* DMA may be available */ + ep = &dev->ep[2].ep; + if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp)) + return ep; + } + break; + default: + /* nothing */ ; + } + + return NULL; +} + static int goku_udc_start(struct usb_gadget *g, struct usb_gadget_driver *driver); static int goku_udc_stop(struct usb_gadget *g); @@ -998,6 +1027,7 @@ static const struct usb_gadget_ops goku_ops = { .get_frame = goku_get_frame, .udc_start = goku_udc_start, .udc_stop = goku_udc_stop, + .match_ep = goku_match_ep, // no remote wakeup // not selfpowered }; @@ -1257,6 +1287,14 @@ static void udc_reinit (struct goku_udc *dev) INIT_LIST_HEAD (&ep->queue); ep_reset(NULL, ep); + + if (i == 0) + ep->ep.caps.type_control = true; + else + ep->ep.caps.type_bulk = true; + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; } dev->ep[0].reg_mode = NULL; diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c index c886887..8aa2593 100644 --- a/drivers/usb/gadget/udc/gr_udc.c +++ b/drivers/usb/gadget/udc/gr_udc.c @@ -2018,12 +2018,23 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit) usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE); ep->bytes_per_buffer = MAX_CTRL_PL_SIZE; + + ep->ep.caps.type_control = true; } else { usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit); list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); + + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; } list_add_tail(&ep->ep_list, &dev->ep_list); + if (is_in) + ep->ep.caps.dir_in = true; + else + ep->ep.caps.dir_out = true; + ep->tailbuf = dma_alloc_coherent(dev->dev, ep->ep.maxpacket_limit, &ep->tailbuf_paddr, GFP_ATOMIC); if (!ep->tailbuf) diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index 3b6a785..00b5006 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -2575,6 +2575,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep0", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 0, @@ -2586,6 +2588,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep1-int", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 2, @@ -2597,6 +2601,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep2-bulk", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 4, @@ -2608,6 +2614,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep3-iso", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 1023, .hwep_num_base = 6, @@ -2619,6 +2627,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep4-int", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 8, @@ -2630,6 +2640,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep5-bulk", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 10, @@ -2641,6 +2653,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep6-iso", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 1023, .hwep_num_base = 12, @@ -2652,6 +2666,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep7-int", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 14, @@ -2663,6 +2679,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep8-bulk", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 16, @@ -2674,6 +2692,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep9-iso", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 1023, .hwep_num_base = 18, @@ -2685,6 +2705,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep10-int", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 20, @@ -2696,6 +2718,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep11-bulk", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 22, @@ -2707,6 +2731,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep12-iso", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 1023, .hwep_num_base = 24, @@ -2718,6 +2744,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep13-int", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 26, @@ -2729,6 +2757,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep14-bulk", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 64, .hwep_num_base = 28, @@ -2740,6 +2770,8 @@ static const struct lpc32xx_udc controller_template = { .ep = { .name = "ep15-bulk", .ops = &lpc32xx_ep_ops, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .maxpacket = 1023, .hwep_num_base = 30, diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c index 309706f..b1cfa96 100644 --- a/drivers/usb/gadget/udc/m66592-udc.c +++ b/drivers/usb/gadget/udc/m66592-udc.c @@ -1052,7 +1052,7 @@ static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) tmp = m66592_read(m66592, M66592_INTSTS0) & M66592_CTSQ; udelay(1); - } while (tmp != M66592_CS_IDST || timeout-- > 0); + } while (tmp != M66592_CS_IDST && timeout-- > 0); if (tmp == M66592_CS_IDST) m66592_bset(m66592, @@ -1644,6 +1644,17 @@ static int m66592_probe(struct platform_device *pdev) ep->ep.name = m66592_ep_name[i]; ep->ep.ops = &m66592_ep_ops; usb_ep_set_maxpacket_limit(&ep->ep, 512); + + if (i == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; } usb_ep_set_maxpacket_limit(&m66592->ep[0].ep, 64); m66592->ep[0].pipenum = 0; diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c index ea35a24..4c48969 100644 --- a/drivers/usb/gadget/udc/mv_u3d_core.c +++ b/drivers/usb/gadget/udc/mv_u3d_core.c @@ -1324,6 +1324,9 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d) ep->ep.ops = &mv_u3d_ep_ops; ep->wedge = 0; usb_ep_set_maxpacket_limit(&ep->ep, MV_U3D_EP0_MAX_PKT_SIZE); + ep->ep.caps.type_control = true; + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; ep->ep_num = 0; ep->ep.desc = &mv_u3d_ep0_desc; INIT_LIST_HEAD(&ep->queue); @@ -1339,14 +1342,20 @@ static int mv_u3d_eps_init(struct mv_u3d *u3d) if (i & 1) { snprintf(name, sizeof(name), "ep%din", i >> 1); ep->direction = MV_U3D_EP_DIR_IN; + ep->ep.caps.dir_in = true; } else { snprintf(name, sizeof(name), "ep%dout", i >> 1); ep->direction = MV_U3D_EP_DIR_OUT; + ep->ep.caps.dir_out = true; } ep->u3d = u3d; strncpy(ep->name, name, sizeof(ep->name)); ep->ep.name = ep->name; + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + ep->ep.ops = &mv_u3d_ep_ops; usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0); ep->ep_num = i / 2; diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c index 5da37c9..339af51 100644 --- a/drivers/usb/gadget/udc/mv_udc_core.c +++ b/drivers/usb/gadget/udc/mv_udc_core.c @@ -1257,6 +1257,9 @@ static int eps_init(struct mv_udc *udc) ep->wedge = 0; ep->stopped = 0; usb_ep_set_maxpacket_limit(&ep->ep, EP0_MAX_PKT_SIZE); + ep->ep.caps.type_control = true; + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; ep->ep_num = 0; ep->ep.desc = &mv_ep0_desc; INIT_LIST_HEAD(&ep->queue); @@ -1269,14 +1272,20 @@ static int eps_init(struct mv_udc *udc) if (i % 2) { snprintf(name, sizeof(name), "ep%din", i / 2); ep->direction = EP_DIR_IN; + ep->ep.caps.dir_in = true; } else { snprintf(name, sizeof(name), "ep%dout", i / 2); ep->direction = EP_DIR_OUT; + ep->ep.caps.dir_out = true; } ep->udc = udc; strncpy(ep->name, name, sizeof(ep->name)); ep->ep.name = ep->name; + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + ep->ep.ops = &mv_ep_ops; ep->stopped = 0; usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0); diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c index 195baf3..18f5ebd 100644 --- a/drivers/usb/gadget/udc/net2272.c +++ b/drivers/usb/gadget/udc/net2272.c @@ -1404,6 +1404,17 @@ net2272_usb_reinit(struct net2272 *dev) else ep->fifo_size = 64; net2272_ep_reset(ep); + + if (i == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; } usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64); @@ -1826,9 +1837,9 @@ net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat) if (!e || u.r.wLength > 2) goto do_stall; if (net2272_ep_read(e, EP_RSPSET) & (1 << ENDPOINT_HALT)) - status = __constant_cpu_to_le16(1); + status = cpu_to_le16(1); else - status = __constant_cpu_to_le16(0); + status = cpu_to_le16(0); /* don't bother with a request object! */ net2272_ep_write(&dev->ep[0], EP_IRQENB, 0); diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index 2bee912..cf0ed42 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -74,19 +74,58 @@ static const char driver_desc[] = DRIVER_DESC; static const u32 ep_bit[9] = { 0, 17, 2, 19, 4, 1, 18, 3, 20 }; static const char ep0name[] = "ep0"; -static const char *const ep_name[] = { - ep0name, - "ep-a", "ep-b", "ep-c", "ep-d", - "ep-e", "ep-f", "ep-g", "ep-h", -}; -/* Endpoint names for usb3380 advance mode */ -static const char *const ep_name_adv[] = { - ep0name, - "ep1in", "ep2out", "ep3in", "ep4out", - "ep1out", "ep2in", "ep3out", "ep4in", +#define EP_INFO(_name, _caps) \ + { \ + .name = _name, \ + .caps = _caps, \ + } + +static const struct { + const char *name; + const struct usb_ep_caps caps; +} ep_info_dft[] = { /* Default endpoint configuration */ + EP_INFO(ep0name, + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-a", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-b", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-c", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-d", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-e", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-f", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-g", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep-h", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)), +}, ep_info_adv[] = { /* Endpoints for usb3380 advance mode */ + EP_INFO(ep0name, + USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)), + EP_INFO("ep1in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep2out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep3in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep4out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep1out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep2in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), + EP_INFO("ep3out", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)), + EP_INFO("ep4in", + USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)), }; +#undef EP_INFO + /* mode 0 == ep-{a,b,c,d} 1K fifo each * mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable * mode 2 == ep-a 2K fifo, ep-{b,c} 1K each, ep-d unavailable @@ -1511,6 +1550,33 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on) return 0; } +static struct usb_ep *net2280_match_ep(struct usb_gadget *_gadget, + struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *ep_comp) +{ + char name[8]; + struct usb_ep *ep; + + if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT) { + /* ep-e, ep-f are PIO with only 64 byte fifos */ + ep = gadget_find_ep_by_name(_gadget, "ep-e"); + if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp)) + return ep; + ep = gadget_find_ep_by_name(_gadget, "ep-f"); + if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp)) + return ep; + } + + /* USB3380: use same address for usb and hardware endpoints */ + snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc), + usb_endpoint_dir_in(desc) ? "in" : "out"); + ep = gadget_find_ep_by_name(_gadget, name); + if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp)) + return ep; + + return NULL; +} + static int net2280_start(struct usb_gadget *_gadget, struct usb_gadget_driver *driver); static int net2280_stop(struct usb_gadget *_gadget); @@ -1522,6 +1588,7 @@ static const struct usb_gadget_ops net2280_ops = { .pullup = net2280_pullup, .udc_start = net2280_start, .udc_stop = net2280_stop, + .match_ep = net2280_match_ep, }; /*-------------------------------------------------------------------------*/ @@ -2055,7 +2122,8 @@ static void usb_reinit_228x(struct net2280 *dev) for (tmp = 0; tmp < 7; tmp++) { struct net2280_ep *ep = &dev->ep[tmp]; - ep->ep.name = ep_name[tmp]; + ep->ep.name = ep_info_dft[tmp].name; + ep->ep.caps = ep_info_dft[tmp].caps; ep->dev = dev; ep->num = tmp; @@ -2095,7 +2163,10 @@ static void usb_reinit_338x(struct net2280 *dev) for (i = 0; i < dev->n_ep; i++) { struct net2280_ep *ep = &dev->ep[i]; - ep->ep.name = dev->enhanced_mode ? ep_name_adv[i] : ep_name[i]; + ep->ep.name = dev->enhanced_mode ? ep_info_adv[i].name : + ep_info_dft[i].name; + ep->ep.caps = dev->enhanced_mode ? ep_info_adv[i].caps : + ep_info_dft[i].caps; ep->dev = dev; ep->num = i; diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index e2fcdb8..9b7d394 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -2579,6 +2579,28 @@ omap_ep_setup(char *name, u8 addr, u8 type, ep->double_buf = dbuf; ep->udc = udc; + switch (type) { + case USB_ENDPOINT_XFER_CONTROL: + ep->ep.caps.type_control = true; + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; + break; + case USB_ENDPOINT_XFER_ISOC: + ep->ep.caps.type_iso = true; + break; + case USB_ENDPOINT_XFER_BULK: + ep->ep.caps.type_bulk = true; + break; + case USB_ENDPOINT_XFER_INT: + ep->ep.caps.type_int = true; + break; + }; + + if (addr & USB_DIR_IN) + ep->ep.caps.dir_in = true; + else + ep->ep.caps.dir_out = true; + ep->ep.name = ep->name; ep->ep.ops = &omap_ep_ops; ep->maxpacket = maxp; diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index 613547f..e5f4c52 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c @@ -620,9 +620,9 @@ static inline void pch_udc_vbus_session(struct pch_udc_dev *dev, dev->vbus_session = 1; } else { if (dev->driver && dev->driver->disconnect) { - spin_unlock(&dev->lock); - dev->driver->disconnect(&dev->gadget); spin_lock(&dev->lock); + dev->driver->disconnect(&dev->gadget); + spin_unlock(&dev->lock); } pch_udc_set_disconnect(dev); dev->vbus_session = 0; @@ -1191,9 +1191,9 @@ static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on) pch_udc_reconnect(dev); } else { if (dev->driver && dev->driver->disconnect) { - spin_unlock(&dev->lock); - dev->driver->disconnect(&dev->gadget); spin_lock(&dev->lock); + dev->driver->disconnect(&dev->gadget); + spin_unlock(&dev->lock); } pch_udc_set_disconnect(dev); } @@ -1488,11 +1488,11 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req, req->dma_mapped = 0; } ep->halted = 1; - spin_unlock(&dev->lock); + spin_lock(&dev->lock); if (!ep->in) pch_udc_ep_clear_rrdy(ep); usb_gadget_giveback_request(&ep->ep, &req->req); - spin_lock(&dev->lock); + spin_unlock(&dev->lock); ep->halted = halted; } @@ -1793,7 +1793,7 @@ static struct usb_request *pch_udc_alloc_request(struct usb_ep *usbep, } /* prevent from using desc. - set HOST BUSY */ dma_desc->status |= PCH_UDC_BS_HST_BSY; - dma_desc->dataptr = __constant_cpu_to_le32(DMA_ADDR_INVALID); + dma_desc->dataptr = cpu_to_le32(DMA_ADDR_INVALID); req->td_data = dma_desc; req->td_data_last = dma_desc; req->chain_len = 1; @@ -2414,7 +2414,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep; else /* OUT */ dev->gadget.ep0 = &ep->ep; - spin_unlock(&dev->lock); + spin_lock(&dev->lock); /* If Mass storage Reset */ if ((dev->setup_data.bRequestType == 0x21) && (dev->setup_data.bRequest == 0xFF)) @@ -2422,7 +2422,7 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) /* call gadget with setup data received */ setup_supported = dev->driver->setup(&dev->gadget, &dev->setup_data); - spin_lock(&dev->lock); + spin_unlock(&dev->lock); if (dev->setup_data.bRequestType & USB_DIR_IN) { ep->td_data->status = (ep->td_data->status & @@ -2594,9 +2594,9 @@ static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev) empty_req_queue(ep); } if (dev->driver) { - spin_unlock(&dev->lock); - usb_gadget_udc_reset(&dev->gadget, dev->driver); spin_lock(&dev->lock); + usb_gadget_udc_reset(&dev->gadget, dev->driver); + spin_unlock(&dev->lock); } } @@ -2675,9 +2675,9 @@ static void pch_udc_svc_intf_interrupt(struct pch_udc_dev *dev) dev->ep[i].halted = 0; } dev->stall = 0; - spin_unlock(&dev->lock); - ret = dev->driver->setup(&dev->gadget, &dev->setup_data); spin_lock(&dev->lock); + ret = dev->driver->setup(&dev->gadget, &dev->setup_data); + spin_unlock(&dev->lock); } /** @@ -2712,9 +2712,9 @@ static void pch_udc_svc_cfg_interrupt(struct pch_udc_dev *dev) dev->stall = 0; /* call gadget zero with setup data received */ - spin_unlock(&dev->lock); - ret = dev->driver->setup(&dev->gadget, &dev->setup_data); spin_lock(&dev->lock); + ret = dev->driver->setup(&dev->gadget, &dev->setup_data); + spin_unlock(&dev->lock); } /** @@ -2747,18 +2747,18 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr) if (dev_intr & UDC_DEVINT_US) { if (dev->driver && dev->driver->suspend) { - spin_unlock(&dev->lock); - dev->driver->suspend(&dev->gadget); spin_lock(&dev->lock); + dev->driver->suspend(&dev->gadget); + spin_unlock(&dev->lock); } vbus = pch_vbus_gpio_get_value(dev); if ((dev->vbus_session == 0) && (vbus != 1)) { if (dev->driver && dev->driver->disconnect) { - spin_unlock(&dev->lock); - dev->driver->disconnect(&dev->gadget); spin_lock(&dev->lock); + dev->driver->disconnect(&dev->gadget); + spin_unlock(&dev->lock); } pch_udc_reconnect(dev); } else if ((dev->vbus_session == 0) @@ -2895,11 +2895,21 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev) ep->in = ~i & 1; ep->ep.name = ep_string[i]; ep->ep.ops = &pch_udc_ep_ops; - if (ep->in) + if (ep->in) { ep->offset_addr = ep->num * UDC_EP_REG_SHIFT; - else + ep->ep.caps.dir_in = true; + } else { ep->offset_addr = (UDC_EPINT_OUT_SHIFT + ep->num) * UDC_EP_REG_SHIFT; + ep->ep.caps.dir_out = true; + } + if (i == UDC_EP0IN_IDX || i == UDC_EP0OUT_IDX) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } /* need to set ep->ep.maxpacket and set Default Configuration?*/ usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE); list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index f6cbe66..b82cb14 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c @@ -1176,6 +1176,7 @@ static void udc_reinit(struct pxa25x_udc *dev) INIT_LIST_HEAD (&dev->gadget.ep_list); INIT_LIST_HEAD (&dev->gadget.ep0->ep_list); dev->ep0state = EP0_IDLE; + dev->gadget.quirk_altset_not_supp = 1; /* basic endpoint records init */ for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) { @@ -1821,6 +1822,8 @@ static struct pxa25x_udc memory = { .name = ep0name, .ops = &pxa25x_ep_ops, .maxpacket = EP0_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, + USB_EP_CAPS_DIR_ALL), }, .dev = &memory, .reg_udccs = &UDCCS0, @@ -1833,6 +1836,8 @@ static struct pxa25x_udc memory = { .name = "ep1in-bulk", .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = BULK_FIFO_SIZE, @@ -1846,6 +1851,8 @@ static struct pxa25x_udc memory = { .name = "ep2out-bulk", .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_OUT), }, .dev = &memory, .fifo_size = BULK_FIFO_SIZE, @@ -1861,6 +1868,8 @@ static struct pxa25x_udc memory = { .name = "ep3in-iso", .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = ISO_FIFO_SIZE, @@ -1874,6 +1883,8 @@ static struct pxa25x_udc memory = { .name = "ep4out-iso", .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_OUT), }, .dev = &memory, .fifo_size = ISO_FIFO_SIZE, @@ -1888,6 +1899,7 @@ static struct pxa25x_udc memory = { .name = "ep5in-int", .ops = &pxa25x_ep_ops, .maxpacket = INT_FIFO_SIZE, + .caps = USB_EP_CAPS(0, 0), }, .dev = &memory, .fifo_size = INT_FIFO_SIZE, @@ -1903,6 +1915,8 @@ static struct pxa25x_udc memory = { .name = "ep6in-bulk", .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = BULK_FIFO_SIZE, @@ -1916,6 +1930,8 @@ static struct pxa25x_udc memory = { .name = "ep7out-bulk", .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_OUT), }, .dev = &memory, .fifo_size = BULK_FIFO_SIZE, @@ -1930,6 +1946,8 @@ static struct pxa25x_udc memory = { .name = "ep8in-iso", .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = ISO_FIFO_SIZE, @@ -1943,6 +1961,8 @@ static struct pxa25x_udc memory = { .name = "ep9out-iso", .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_OUT), }, .dev = &memory, .fifo_size = ISO_FIFO_SIZE, @@ -1957,6 +1977,7 @@ static struct pxa25x_udc memory = { .name = "ep10in-int", .ops = &pxa25x_ep_ops, .maxpacket = INT_FIFO_SIZE, + .caps = USB_EP_CAPS(0, 0), }, .dev = &memory, .fifo_size = INT_FIFO_SIZE, @@ -1972,6 +1993,8 @@ static struct pxa25x_udc memory = { .name = "ep11in-bulk", .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = BULK_FIFO_SIZE, @@ -1985,6 +2008,8 @@ static struct pxa25x_udc memory = { .name = "ep12out-bulk", .ops = &pxa25x_ep_ops, .maxpacket = BULK_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_OUT), }, .dev = &memory, .fifo_size = BULK_FIFO_SIZE, @@ -1999,6 +2024,8 @@ static struct pxa25x_udc memory = { .name = "ep13in-iso", .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_IN), }, .dev = &memory, .fifo_size = ISO_FIFO_SIZE, @@ -2012,6 +2039,8 @@ static struct pxa25x_udc memory = { .name = "ep14out-iso", .ops = &pxa25x_ep_ops, .maxpacket = ISO_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, + USB_EP_CAPS_DIR_OUT), }, .dev = &memory, .fifo_size = ISO_FIFO_SIZE, @@ -2026,6 +2055,7 @@ static struct pxa25x_udc memory = { .name = "ep15in-int", .ops = &pxa25x_ep_ops, .maxpacket = INT_FIFO_SIZE, + .caps = USB_EP_CAPS(0, 0), }, .dev = &memory, .fifo_size = INT_FIFO_SIZE, diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c index b51226a..670ac0b 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.c +++ b/drivers/usb/gadget/udc/pxa27x_udc.c @@ -1710,6 +1710,7 @@ static void udc_init_data(struct pxa_udc *dev) INIT_LIST_HEAD(&dev->gadget.ep_list); INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0]; + dev->gadget.quirk_altset_not_supp = 1; ep0_idle(dev); /* PXA endpoints init */ @@ -2422,7 +2423,7 @@ static int pxa_udc_probe(struct platform_device *pdev) } udc->udc_command = mach->udc_command; } else { - udc->gpiod = devm_gpiod_get(&pdev->dev, NULL); + udc->gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_ASIS); } regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/drivers/usb/gadget/udc/pxa27x_udc.h b/drivers/usb/gadget/udc/pxa27x_udc.h index 11e1423..cea2cb7 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.h +++ b/drivers/usb/gadget/udc/pxa27x_udc.h @@ -234,25 +234,35 @@ /* * Endpoint definition helpers */ -#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \ -{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \ +#define USB_EP_DEF(addr, bname, dir, type, maxpkt, ctype, cdir) \ +{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, \ + .caps = USB_EP_CAPS(ctype, cdir), }, \ .desc = { .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \ - .bmAttributes = type, \ + .bmAttributes = USB_ENDPOINT_XFER_ ## type, \ .wMaxPacketSize = maxpkt, }, \ .dev = &memory \ } -#define USB_EP_BULK(addr, bname, dir) \ - USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE) -#define USB_EP_ISO(addr, bname, dir) \ - USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE) -#define USB_EP_INT(addr, bname, dir) \ - USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE) -#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1) -#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0) -#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1) -#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0) -#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1) -#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, 0, EP0_FIFO_SIZE) +#define USB_EP_BULK(addr, bname, dir, cdir) \ + USB_EP_DEF(addr, bname, dir, BULK, BULK_FIFO_SIZE, \ + USB_EP_CAPS_TYPE_BULK, cdir) +#define USB_EP_ISO(addr, bname, dir, cdir) \ + USB_EP_DEF(addr, bname, dir, ISOC, ISO_FIFO_SIZE, \ + USB_EP_CAPS_TYPE_ISO, cdir) +#define USB_EP_INT(addr, bname, dir, cdir) \ + USB_EP_DEF(addr, bname, dir, INT, INT_FIFO_SIZE, \ + USB_EP_CAPS_TYPE_INT, cdir) +#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1, \ + USB_EP_CAPS_DIR_IN) +#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0, \ + USB_EP_CAPS_DIR_OUT) +#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1, \ + USB_EP_CAPS_DIR_IN) +#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0, \ + USB_EP_CAPS_DIR_OUT) +#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1, \ + USB_EP_CAPS_DIR_IN) +#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, CONTROL, EP0_FIFO_SIZE, \ + USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL) #define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \ { \ diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c index 0293f71..baa0609 100644 --- a/drivers/usb/gadget/udc/r8a66597-udc.c +++ b/drivers/usb/gadget/udc/r8a66597-udc.c @@ -1935,6 +1935,16 @@ static int r8a66597_probe(struct platform_device *pdev) ep->ep.name = r8a66597_ep_name[i]; ep->ep.ops = &r8a66597_ep_ops; usb_ep_set_maxpacket_limit(&ep->ep, 512); + + if (i == 0) { + ep->ep.caps.type_control = true; + } else { + ep->ep.caps.type_iso = true; + ep->ep.caps.type_bulk = true; + ep->ep.caps.type_int = true; + } + ep->ep.caps.dir_in = true; + ep->ep.caps.dir_out = true; } usb_ep_set_maxpacket_limit(&r8a66597->ep[0].ep, 64); r8a66597->ep[0].pipenum = 0; diff --git a/drivers/usb/gadget/udc/s3c-hsudc.c b/drivers/usb/gadget/udc/s3c-hsudc.c index 85a712a..e9def42 100644 --- a/drivers/usb/gadget/udc/s3c-hsudc.c +++ b/drivers/usb/gadget/udc/s3c-hsudc.c @@ -1005,6 +1005,21 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc, hsep->stopped = 0; hsep->wedge = 0; + if (epnum == 0) { + hsep->ep.caps.type_control = true; + hsep->ep.caps.dir_in = true; + hsep->ep.caps.dir_out = true; + } else { + hsep->ep.caps.type_iso = true; + hsep->ep.caps.type_bulk = true; + hsep->ep.caps.type_int = true; + } + + if (epnum & 1) + hsep->ep.caps.dir_in = true; + else + hsep->ep.caps.dir_out = true; + set_index(hsudc, epnum); writel(hsep->ep.maxpacket, hsudc->regs + S3C_MPR); } diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c index 5d9aa81..eb3571e 100644 --- a/drivers/usb/gadget/udc/s3c2410_udc.c +++ b/drivers/usb/gadget/udc/s3c2410_udc.c @@ -1691,6 +1691,8 @@ static struct s3c2410_udc memory = { .name = ep0name, .ops = &s3c2410_ep_ops, .maxpacket = EP0_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, + USB_EP_CAPS_DIR_ALL), }, .dev = &memory, }, @@ -1702,6 +1704,8 @@ static struct s3c2410_udc memory = { .name = "ep1-bulk", .ops = &s3c2410_ep_ops, .maxpacket = EP_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .dev = &memory, .fifo_size = EP_FIFO_SIZE, @@ -1714,6 +1718,8 @@ static struct s3c2410_udc memory = { .name = "ep2-bulk", .ops = &s3c2410_ep_ops, .maxpacket = EP_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .dev = &memory, .fifo_size = EP_FIFO_SIZE, @@ -1726,6 +1732,8 @@ static struct s3c2410_udc memory = { .name = "ep3-bulk", .ops = &s3c2410_ep_ops, .maxpacket = EP_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .dev = &memory, .fifo_size = EP_FIFO_SIZE, @@ -1738,6 +1746,8 @@ static struct s3c2410_udc memory = { .name = "ep4-bulk", .ops = &s3c2410_ep_ops, .maxpacket = EP_FIFO_SIZE, + .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, + USB_EP_CAPS_DIR_ALL), }, .dev = &memory, .fifo_size = EP_FIFO_SIZE, diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index 362ee8a..f660afb 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -131,6 +131,96 @@ EXPORT_SYMBOL_GPL(usb_gadget_giveback_request); /* ------------------------------------------------------------------------- */ +/** + * gadget_find_ep_by_name - returns ep whose name is the same as sting passed + * in second parameter or NULL if searched endpoint not found + * @g: controller to check for quirk + * @name: name of searched endpoint + */ +struct usb_ep *gadget_find_ep_by_name(struct usb_gadget *g, const char *name) +{ + struct usb_ep *ep; + + gadget_for_each_ep(ep, g) { + if (!strcmp(ep->name, name)) + return ep; + } + + return NULL; +} +EXPORT_SYMBOL_GPL(gadget_find_ep_by_name); + +/* ------------------------------------------------------------------------- */ + +int usb_gadget_ep_match_desc(struct usb_gadget *gadget, + struct usb_ep *ep, struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *ep_comp) +{ + u8 type; + u16 max; + int num_req_streams = 0; + + /* endpoint already claimed? */ + if (ep->claimed) + return 0; + + type = usb_endpoint_type(desc); + max = 0x7ff & usb_endpoint_maxp(desc); + + if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in) + return 0; + if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out) + return 0; + + if (max > ep->maxpacket_limit) + return 0; + + /* "high bandwidth" works only at high speed */ + if (!gadget_is_dualspeed(gadget) && usb_endpoint_maxp(desc) & (3<<11)) + return 0; + + switch (type) { + case USB_ENDPOINT_XFER_CONTROL: + /* only support ep0 for portable CONTROL traffic */ + return 0; + case USB_ENDPOINT_XFER_ISOC: + if (!ep->caps.type_iso) + return 0; + /* ISO: limit 1023 bytes full speed, 1024 high/super speed */ + if (!gadget_is_dualspeed(gadget) && max > 1023) + return 0; + break; + case USB_ENDPOINT_XFER_BULK: + if (!ep->caps.type_bulk) + return 0; + if (ep_comp && gadget_is_superspeed(gadget)) { + /* Get the number of required streams from the + * EP companion descriptor and see if the EP + * matches it + */ + num_req_streams = ep_comp->bmAttributes & 0x1f; + if (num_req_streams > ep->max_streams) + return 0; + } + break; + case USB_ENDPOINT_XFER_INT: + /* Bulk endpoints handle interrupt transfers, + * except the toggle-quirky iso-synch kind + */ + if (!ep->caps.type_int && !ep->caps.type_bulk) + return 0; + /* INT: limit 64 bytes full speed, 1024 high/super speed */ + if (!gadget_is_dualspeed(gadget) && max > 64) + return 0; + break; + } + + return 1; +} +EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc); + +/* ------------------------------------------------------------------------- */ + static void usb_gadget_state_work(struct work_struct *work) { struct usb_gadget *gadget = work_to_gadget(work); @@ -323,6 +413,7 @@ err4: err3: put_device(&udc->dev); + device_del(&gadget->dev); err2: put_device(&gadget->dev); diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c index 1f24274..1cbb0ac 100644 --- a/drivers/usb/gadget/udc/udc-xilinx.c +++ b/drivers/usb/gadget/udc/udc-xilinx.c @@ -1317,12 +1317,21 @@ static void xudc_eps_init(struct xusb_udc *udc) snprintf(ep->name, EPNAME_SIZE, "ep%d", ep_number); ep->ep_usb.name = ep->name; ep->ep_usb.ops = &xusb_ep_ops; + + ep->ep_usb.caps.type_iso = true; + ep->ep_usb.caps.type_bulk = true; + ep->ep_usb.caps.type_int = true; } else { ep->ep_usb.name = ep0name; usb_ep_set_maxpacket_limit(&ep->ep_usb, EP0_MAX_PACKET); ep->ep_usb.ops = &xusb_ep0_ops; + + ep->ep_usb.caps.type_control = true; } + ep->ep_usb.caps.dir_in = true; + ep->ep_usb.caps.dir_out = true; + ep->udc = udc; ep->epnumber = ep_number; ep->desc = NULL; |