usb gadget: Configure endpoint according to gadget speed.
Subsystems (2)
PATCH v4 2/4 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 <[email protected]>
--- drivers/usb/gadget/composite.c | 76 +++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/epautoconf.c | 1 + include/linux/usb/composite.h | 21 +++++++++++ include/linux/usb/gadget.h | 3 ++ 4 files changed, 101 insertions(+), 0 deletions(-)
drivers/usb/gadget/composite.c +76 -0
@@ -74,6 +74,82 @@ 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 ; +} + +/** +* 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 in 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 choosen 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 (d_spd =next_ep_desc (speed_desc); d_spd; + d_spd =next_ep_desc (d_spd+1 )) { + chosen_desc = (struct usb_endpoint_descriptor *)*d_spd; +if (chosen_desc->bEndpointAddress == _ep->bEndpointAddress) + 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
drivers/usb/gadget/epautoconf.c +1 -0
@@ -184,6 +184,7 @@ ep_matches ( size =64 ; desc->wMaxPacketSize =cpu_to_le16 (size); } + ep->bEndpointAddress = desc->bEndpointAddress;return 1 ; }
include/linux/usb/composite.h +21 -0
@@ -138,6 +138,27 @@ int usb_function_activate(struct usb_function *);int usb_interface_id (struct usb_configuration *,struct usb_function *);/** +* 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 in 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 choosen 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); + +/** * ep_choose - select descriptor endpoint at current device speed * @g: gadget, connected and running at some speed * @hs: descriptor to use for high speed operation
include/linux/usb/gadget.h +3 -0
@@ -132,6 +132,8 @@ struct usb_ep_ops {* value can sometimes be reduced (hardware allowing), according to * the endpoint descriptor used to configure the endpoint. * @driver_data:for use by the gadget driver. +* @bEndpointAddress: used to identify the endpoint when finding +* descriptor that matches connection speed * @desc: endpoint descriptor. This pointer is set before the endpoint is * enabled and remains valid until the endpoint is disabled. *
@@ -146,6 +148,7 @@ struct usb_ep {const struct usb_ep_ops *ops;struct list_head ep_list; unsigned maxpacket:16; +u8 bEndpointAddress;const struct usb_endpoint_descriptor *desc; };
Signature · 5 lines
1.6.3.3 -- Sent by an employee of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
Hi
Quoted 5 lines · Tatyana Brokhman
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.
Quoted 8 lines
Signed-off-by Tatyana Brokhman <[email protected]>--- drivers/usb/gadget/composite.c | 76 +++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/epautoconf.c | 1 + include/linux/usb/composite.h | 21 +++++++++++ include/linux/usb/gadget.h | 3 ++ 4 files changed, 101 insertions(+), 0 deletions(-)
---cut---
Quoted 27 lines
+ */
drivers/usb/gadget/composite.c +26
-0+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 (d_spd =next_ep_desc (speed_desc); d_spd; + d_spd =next_ep_desc (d_spd+1 )) {
drivers/usb/gadget/composite.c MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); · line 149
Quoted 10 lines
drivers/usb/gadget/composite.c +10
-0+ chosen_desc = (struct usb_endpoint_descriptor *)*d_spd; +if (chosen_desc->bEndpointAddress == _ep->bEndpointAddress) + goto ep_found; + } +return -EIO ; + +ep_found: +/* commit results */ + _ep->maxpacket =le16_to_cpu (chosen_desc->wMaxPacketSize); + _ep->desc = chosen_desc;
Could you please comment on why do we need to update gadget's ep list with function's maxpacket ? Will this not affect when we switch functions ?
Quoted 3 lines
drivers/usb/gadget/composite.c +3
-0+ +return 0 ; +}