usb: gadget: Fix issue with config_ep_by_speed function.
Delete '.' at the end of subject.
Reply-To:
In-Reply-To: <[email protected]>
Quoted 57 lines · Pawel Laszczak
This patch adds new
config_ep_by_speed_and_altfunction which extends theconfig_ep_by_speedabout alt parameter.
This additional parameter allows to find properusb_ss_ep_comp_descriptor.Problem has appeared during testing
f_tcm(BOT/UAS) driver function.
f_tcmfunction for SS use array of headers for both BOT/UAS alternate setting:static struct
usb_descriptor_header*uasp_ss_function_desc[] = {
(structusb_descriptor_header*)&bot_intf_desc, (structusb_descriptor_header*)&uasp_ss_bi_desc, (structusb_descriptor_header*)&bot_bi_ep_comp_desc, (structusb_descriptor_header*)&uasp_ss_bo_desc, (structusb_descriptor_header*)&bot_bo_ep_comp_desc,(struct
usb_descriptor_header*)&uasp_intf_desc, (structusb_descriptor_header*)&uasp_ss_bi_desc, (structusb_descriptor_header*)&uasp_bi_ep_comp_desc, (structusb_descriptor_header*)&uasp_bi_pipe_desc, (structusb_descriptor_header*)&uasp_ss_bo_desc, (structusb_descriptor_header*)&uasp_bo_ep_comp_desc, (structusb_descriptor_header*)&uasp_bo_pipe_desc, (structusb_descriptor_header*)&uasp_ss_status_desc, (structusb_descriptor_header*)&uasp_status_in_ep_comp_desc, (structusb_descriptor_header*)&uasp_status_pipe_desc, (structusb_descriptor_header*)&uasp_ss_cmd_desc, (structusb_descriptor_header*)&uasp_cmd_comp_desc, (structusb_descriptor_header*)&uasp_cmd_pipe_desc, NULL,
};The first 5 descriptors are associated with BOT alternate setting, and others are associated with UAS.
During handling UAS alternate setting
f_tcmdriver invokesconfig_ep_by_speedand this function sets incorrect companion endpoint descriptor inusb_epobject.Instead setting
ep->comp_desctouasp_bi_ep_comp_descfunction in this case setep->comp_desctouasp_ss_bi_desc.This is due to the fact that it searches endpoint based on endpoint address:
for_each_ep_desc(speed_desc, d_spd) { chosen_desc = (struct usb_endpoint_descriptor *)*d_spd; if (chosen_desc->bEndpoitAddress == _ep->address) goto ep_found; }And in result it uses the descriptor from BOT alternate setting instead UAS.
Finally, it causes that controller driver during enabling endpoints detect that just enabled endpoint for bot.
Quoted 7 lines
Signed-off-by Jayshri Pawar <[email protected]>Signed-off-by Pawel Laszczak <[email protected]>---
Changelog:
v2
- redefineconfig_ep_by_speed()instead removing it.
- remove changes fromf_tcm.cfile.
I think you may add f_tcm.c changes as the second patch, since it is the user for this patch.
Peter
Quoted 156 lines
drivers/usb/gadget/composite.c | 78 ++++++++++++++++++++++++++-------- include/linux/usb/composite.h | 3 ++ 2 files changed, 64 insertions(+), 17 deletions(-)drivers/usb/gadget/composite.c +61
-17@@ -96,40 +96,43 @@ function_descriptors(struct usb_function *f, }/** -* next_ep_desc() - advance to the next EP descriptor +* next_desc() - advance to the next desc_type descriptor * @t: currect pointer within descriptor array +* @desc_type: descriptor type * -* Return: next EP descriptor or NULL +* Return: next desc_type descriptor or NULL * -* Iterate over @t until either EP descriptor found or +* Iterate over @t until either desc_type descriptor found or * NULL (that indicates end of list) encountered */ static struct usb_descriptor_header ** -next_ep_desc (struct usb_descriptor_header **t) +next_desc (struct usb_descriptor_header **t,u8 desc_type) {for (; *t; t++) { -if ((*t)->bDescriptorType ==USB_DT_ENDPOINT ) +if ((*t)->bDescriptorType == desc_type)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 +* for_each_desc() - iterate over desc_type descriptors in the +* descriptors list +* @start: pointer within descriptor array. +* @iter_desc: desc_type descriptor to use as the loop cursor +* @desc_type: wanted descriptr type */ -#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)) +#define for_each_desc (start, iter_desc, desc_type) \ + for (iter_desc = next_desc(start, desc_type); \ + iter_desc; iter_desc = next_desc(iter_desc + 1, desc_type))/** -* config_ep_by_speed() - configures the given endpoint +* config_ep_by_speed_and_alt() - configures the given endpoint * according to gadget speed. * @g: pointer to the gadget * @f: usb function * @_ep: the endpoint to configure +* @alt: alternate setting number * * Return: error code, 0 on success * @@ -142,11 +145,13 @@ next_ep_desc(struct usb_descriptor_header **t)* 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) +int config_ep_by_speed_and_alt (struct usb_gadget *g, +struct usb_function *f, +struct usb_ep *_ep, +u8 alt) {struct usb_endpoint_descriptor *chosen_desc =NULL ; +struct usb_interface_descriptor *int_desc =NULL ;struct usb_descriptor_header **speed_desc =NULL ;struct usb_ss_ep_comp_descriptor *comp_desc =NULL ;@@ -182,8 +187,21 @@ int config_ep_by_speed(struct usb_gadget *g,default : speed_desc = f->fs_descriptors; } + +/* find correct alternate setting descriptor */ +for_each_desc (speed_desc, d_spd,USB_DT_INTERFACE ) { + int_desc = (struct usb_interface_descriptor *)*d_spd; + +if (int_desc->bAlternateSetting == alt) { + speed_desc = d_spd; + goto intf_found; + } + } +return -EIO ; + +intf_found:/* find descriptors */ -for_each_ep_desc (speed_desc, d_spd) { +for_each_desc (speed_desc, d_spd,USB_DT_ENDPOINT ) { chosen_desc = (struct usb_endpoint_descriptor *)*d_spd;if (chosen_desc->bEndpointAddress == _ep->address) goto ep_found;@@ -237,6 +255,32 @@ int config_ep_by_speed(struct usb_gadget *g, }return 0 ; } +EXPORT_SYMBOL_GPL (config_ep_by_speed_and_alt); + +/** +* 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) +{ +return config_ep_by_speed_and_alt (g, f, _ep,0 ); +}EXPORT_SYMBOL_GPL (config_ep_by_speed);/** include/linux/usb/composite.h +3
-0@@ -249,6 +249,9 @@ int usb_function_activate(struct usb_function *);int usb_interface_id (struct usb_configuration *,struct usb_function *); +int config_ep_by_speed_and_alt (struct usb_gadget *g,struct usb_function *f, +struct usb_ep *_ep,u8 alt); +int config_ep_by_speed (struct usb_gadget *g,struct usb_function *f,struct usb_ep *_ep);Signature · 1 line
2.17.1
Signature · 2 lines
Thanks, Peter Chen