diff options
author | Tatyana Brokhman <tlinder@codeaurora.org> | 2011-06-28 16:33:49 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-06-28 11:14:36 -0700 |
commit | 48767a4e8263620c347c3fa17812c943dd0fc2fa (patch) | |
tree | 2859b92667049c57cae1c6ca02fd7897d6f3534f /drivers/usb/gadget/composite.c | |
parent | 72c973dd2b01b212a159faa330a2bc641a3ed809 (diff) |
usb: gadget: configure endpoint according to gadget speed
Add config_ep_by_speed() to configure the endpoint
according to the gadget speed.
Using this function will spare the FDs from handling
the endpoint chosen descriptor.
Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/gadget/composite.c')
-rw-r--r-- | drivers/usb/gadget/composite.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 5cbb1a41c223..1c6bd666150a 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -74,6 +74,91 @@ MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); static char composite_manufacturer[50]; /*-------------------------------------------------------------------------*/ +/** + * next_ep_desc() - advance to the next EP descriptor + * @t: currect pointer within descriptor array + * + * Return: next EP descriptor or NULL + * + * Iterate over @t until either EP descriptor found or + * NULL (that indicates end of list) encountered + */ +static struct usb_descriptor_header** +next_ep_desc(struct usb_descriptor_header **t) +{ + for (; *t; t++) { + if ((*t)->bDescriptorType == USB_DT_ENDPOINT) + return t; + } + return NULL; +} + +/* + * for_each_ep_desc()- iterate over endpoint descriptors in the + * descriptors list + * @start: pointer within descriptor array. + * @ep_desc: endpoint descriptor to use as the loop cursor + */ +#define for_each_ep_desc(start, ep_desc) \ + for (ep_desc = next_ep_desc(start); \ + ep_desc; ep_desc = next_ep_desc(ep_desc+1)) + +/** + * config_ep_by_speed() - configures the given endpoint + * according to gadget speed. + * @g: pointer to the gadget + * @f: usb function + * @_ep: the endpoint to configure + * + * Return: error code, 0 on success + * + * This function chooses the right descriptors for a given + * endpoint according to gadget speed and saves it in the + * endpoint desc field. If the endpoint already has a descriptor + * assigned to it - overwrites it with currently corresponding + * descriptor. The endpoint maxpacket field is updated according + * to the chosen descriptor. + * Note: the supplied function should hold all the descriptors + * for supported speeds + */ +int config_ep_by_speed(struct usb_gadget *g, + struct usb_function *f, + struct usb_ep *_ep) +{ + struct usb_endpoint_descriptor *chosen_desc = NULL; + struct usb_descriptor_header **speed_desc = NULL; + + struct usb_descriptor_header **d_spd; /* cursor for speed desc */ + + if (!g || !f || !_ep) + return -EIO; + + /* select desired speed */ + switch (g->speed) { + case USB_SPEED_HIGH: + if (gadget_is_dualspeed(g)) { + speed_desc = f->hs_descriptors; + break; + } + /* else: fall through */ + default: + speed_desc = f->descriptors; + } + /* find descriptors */ + for_each_ep_desc(speed_desc, d_spd) { + chosen_desc = (struct usb_endpoint_descriptor *)*d_spd; + if (chosen_desc->bEndpointAddress == _ep->address) + goto ep_found; + } + return -EIO; + +ep_found: + /* commit results */ + _ep->maxpacket = le16_to_cpu(chosen_desc->wMaxPacketSize); + _ep->desc = chosen_desc; + + return 0; +} /** * usb_add_function() - add a function to a configuration |