usb: Add SuperSpeed support to the Gadget Framework
Subsystems (2)
v3 cover usb: Add SuperSpeed support to the Gadget Framework
This patch series adds Super Speed support to the Gadget framework. This is a third version of an already sent series. It was split into additional two patches.
Tatyana Brokhman (4):
usb: Add usb_endpoint_descriptor to be part of the struct usb_ep
usb: Configure endpoint according to gadget speed.
usb: Modify existing gadget drivers to use config_ep_by_speed()
instead of ep_choose.
usb:gadget: Add SuperSpeed support to the Gadget Framework
drivers/usb/gadget/Kconfig | 12 + drivers/usb/gadget/composite.c | 440 +++++++++++++++++++++++++++++++++-- drivers/usb/gadget/config.c | 25 -- drivers/usb/gadget/dbgp.c | 8 +- drivers/usb/gadget/epautoconf.c | 1 + drivers/usb/gadget/f_acm.c | 50 ++--- drivers/usb/gadget/f_audio.c | 5 +- drivers/usb/gadget/f_ecm.c | 54 ++--- drivers/usb/gadget/f_eem.c | 36 +-- drivers/usb/gadget/f_fs.c | 3 +- drivers/usb/gadget/f_hid.c | 22 +-- drivers/usb/gadget/f_loopback.c | 17 +- drivers/usb/gadget/f_mass_storage.c | 3 +- drivers/usb/gadget/f_obex.c | 32 +-- drivers/usb/gadget/f_phonet.c | 17 +- drivers/usb/gadget/f_rndis.c | 52 ++--- drivers/usb/gadget/f_serial.c | 32 +-- drivers/usb/gadget/f_sourcesink.c | 14 +- drivers/usb/gadget/f_subset.c | 33 +-- drivers/usb/gadget/f_uvc.c | 6 +- drivers/usb/gadget/file_storage.c | 3 +- drivers/usb/gadget/gmidi.c | 6 +- drivers/usb/gadget/inode.c | 6 +- drivers/usb/gadget/printer.c | 26 ++- drivers/usb/gadget/u_ether.c | 12 +- drivers/usb/gadget/u_ether.h | 4 - drivers/usb/gadget/u_serial.c | 4 +- drivers/usb/gadget/u_serial.h | 2 - include/linux/usb/composite.h | 55 ++++- include/linux/usb/gadget.h | 64 ++++-- 30 files changed, 741 insertions(+), 361 deletions(-)
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH v3 2/4 usb: 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.
--- drivers/usb/gadget/composite.c | 76 +++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/epautoconf.c | 1 + include/linux/usb/composite.h | 21 +++++++++++ include/linux/usb/gadget.h | 8 +++-- 4 files changed, 103 insertions(+), 3 deletions(-)
drivers/usb/gadget/composite.c +76 -0
@@ -70,6 +70,82 @@ module_param(iSerialNumber, charp, 0);MODULE_PARM_DESC (iSerialNumber,"SerialNumber string" );/*-------------------------------------------------------------------------*/ +/** +* 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 +5 -3
@@ -132,9 +132,10 @@ 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. -* @desc:endpoint descriptor. This pointer set before endpoint -* is enabled and remains valid until the endpoint is -* disabled. +* @bEndpointAddress: used to identify the endpoint when finding +* descriptor that matches connection speed +* @desc:endpoint descriptor. this pointer set before endpoint is enabled and +* remains valid until the endpoint is disabled. * * the bus controller driver lists all the general purpose endpoints in * gadget->ep_list. the control endpoint (gadget->ep0) is not in that list,
@@ -147,6 +148,7 @@ struct usb_ep {const struct usb_ep_ops *ops;struct list_head ep_list; unsigned maxpacket:16; +u8 bEndpointAddress;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.
PATCH v3 3/4 usb: Modify existing gadget drivers to use config_ep_by_speed() instead of ep_choose.
Remove obsolete functions:
1. ep_choose()
2. usb_find_endpoint()
--- drivers/usb/gadget/config.c | 25 ------------------- drivers/usb/gadget/f_acm.c | 47 +++++++++++-------------------------- drivers/usb/gadget/f_ecm.c | 45 +++++++++++------------------------ drivers/usb/gadget/f_eem.c | 32 +++++++------------------ drivers/usb/gadget/f_hid.c | 19 ++++---------- drivers/usb/gadget/f_loopback.c | 11 +++++--- drivers/usb/gadget/f_obex.c | 32 +++++++------------------ drivers/usb/gadget/f_phonet.c | 12 ++++---- drivers/usb/gadget/f_rndis.c | 45 ++++++++++------------------------- drivers/usb/gadget/f_serial.c | 32 ++++++------------------- drivers/usb/gadget/f_sourcesink.c | 8 ++++- drivers/usb/gadget/f_subset.c | 29 ++++------------------ include/linux/usb/composite.h | 15 ----------- include/linux/usb/gadget.h | 6 ---- 14 files changed, 98 insertions(+), 260 deletions(-)
drivers/usb/gadget/config.c +0 -25
@@ -165,28 +165,3 @@ usb_copy_descriptors(struct usb_descriptor_header **src)return ret; } -/** -* usb_find_endpoint - find a copy of an endpoint descriptor -* @src: original vector of descriptors -* @copy: copy of @src -* @match: endpoint descriptor found in @src -* -* This returns the copy of the @match descriptor made for @copy. Its -* intended use is to help remembering the endpoint descriptor to use -* when enabling a given endpoint. -*/ -struct usb_endpoint_descriptor * -usb_find_endpoint ( -struct usb_descriptor_header **src, -struct usb_descriptor_header **copy, -struct usb_endpoint_descriptor *match -) -{ -while (*src) { -if (*src == (void *) match) -return (void *)*copy; - src++; - copy++; - } -return NULL ; -}
drivers/usb/gadget/f_acm.c +14 -33
89 lines not on this page · raw message
drivers/usb/gadget/f_ecm.c +14 -31
83 lines not on this page · raw message
drivers/usb/gadget/f_eem.c +9 -23
@@ -35,17 +35,9 @@* Ethernet link. */ -struct eem_ep_descs { -struct usb_endpoint_descriptor *in; -struct usb_endpoint_descriptor *out; -}; -struct f_eem {struct gether port;u8 ctrl_id; - -struct eem_ep_descs fs; -struct eem_ep_descs hs; };static inline struct f_eem *func_to_eem (struct usb_function *f)
@@ -176,12 +168,16 @@ static int eem_set_alt(struct usb_function *f, unsigned intf, unsigned alt)gether_disconnect (&eem->port); } -if (!eem->port.in_ep->desc) { +if (!eem->port.in_ep->desc || !eem->port.out_ep->desc) {DBG (cdev,"init eem\n" ); - eem->port.in_ep->desc =ep_choose (cdev->gadget, - eem->hs.in, eem->fs.in); - eem->port.out_ep->desc =ep_choose (cdev->gadget, - eem->hs.out, eem->fs.out); +if (config_ep_by_speed (cdev->gadget, f, + eem->port.in_ep) || +config_ep_by_speed (cdev->gadget, f, + eem->port.out_ep)) { + eem->port.in_ep->desc =NULL ; + eem->port.out_ep->desc =NULL ; + goto fail; + } }/* zlps should not occur because zero-length EEM packets
@@ -253,11 +249,6 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)if (!f->descriptors) goto fail; - eem->fs.in =usb_find_endpoint (eem_fs_function, - f->descriptors, &eem_fs_in_desc); - eem->fs.out =usb_find_endpoint (eem_fs_function, - f->descriptors, &eem_fs_out_desc); -/* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at * both speeds
@@ -272,11 +263,6 @@ eem_bind(struct usb_configuration *c, struct usb_function *f) f->hs_descriptors =usb_copy_descriptors (eem_hs_function);if (!f->hs_descriptors) goto fail; - - eem->hs.in =usb_find_endpoint (eem_hs_function, - f->hs_descriptors, &eem_hs_in_desc); - eem->hs.out =usb_find_endpoint (eem_hs_function, - f->hs_descriptors, &eem_hs_out_desc); } DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n",
drivers/usb/gadget/f_hid.c +6 -13
@@ -60,8 +60,6 @@ struct f_hidg {struct cdev cdev;struct usb_function func;struct usb_ep *in_ep; -struct usb_endpoint_descriptor *fs_in_ep_desc; -struct usb_endpoint_descriptor *hs_in_ep_desc; };static inline struct f_hidg *func_to_hidg (struct usb_function *f)
@@ -430,8 +428,12 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)if (hidg->in_ep->driver_data !=NULL )usb_ep_disable (hidg->in_ep); - hidg->in_ep->desc =ep_choose (f->config->cdev->gadget, - hidg->hs_in_ep_desc, hidg->fs_in_ep_desc); + status =config_ep_by_speed (f->config->cdev->gadget, f, + hidg->in_ep); +if (status) { +ERROR (cdev,"config_ep_by_speed FAILED!\n" ); + goto fail; + } status =usb_ep_enable (hidg->in_ep);if (status <0 ) {ERROR (cdev,"Enable endpoint FAILED!\n" );
@@ -501,21 +503,12 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)if (!f->descriptors) goto fail; - hidg->fs_in_ep_desc =usb_find_endpoint (hidg_fs_descriptors, - f->descriptors, - &hidg_fs_in_ep_desc); -if (gadget_is_dualspeed (c->cdev->gadget)) { hidg_hs_in_ep_desc.bEndpointAddress = hidg_fs_in_ep_desc.bEndpointAddress; f->hs_descriptors =usb_copy_descriptors (hidg_hs_descriptors);if (!f->hs_descriptors) goto fail; - hidg->hs_in_ep_desc =usb_find_endpoint (hidg_hs_descriptors, - f->hs_descriptors, - &hidg_hs_in_ep_desc); - }else { - hidg->hs_in_ep_desc =NULL ; }mutex_init (&hidg->lock);
drivers/usb/gadget/f_loopback.c +7 -4
@@ -256,8 +256,9 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)/* one endpoint writes data back IN to the host */ ep = loop->in_ep; - ep->desc =ep_choose (cdev->gadget, - &hs_loop_source_desc, &fs_loop_source_desc); + result =config_ep_by_speed (cdev->gadget, &(loop->function), ep); +if (result) +return result; result =usb_ep_enable (ep);if (result <0 )return result;
@@ -265,8 +266,10 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)/* one endpoint just reads OUT packets */ ep = loop->out_ep; - ep->desc =ep_choose (cdev->gadget, - &hs_loop_sink_desc, &fs_loop_sink_desc); + result =config_ep_by_speed (cdev->gadget, &(loop->function), ep); +if (result) + goto fail0; + result =usb_ep_enable (ep);if (result <0 ) { fail0:
drivers/usb/gadget/f_obex.c +9 -23
@@ -39,20 +39,12 @@* ready to handle the commands. */ -struct obex_ep_descs { -struct usb_endpoint_descriptor *obex_in; -struct usb_endpoint_descriptor *obex_out; -}; -struct f_obex {struct gserial port;u8 ctrl_id;u8 data_id;u8 port_num;u8 can_activate; - -struct obex_ep_descs fs; -struct obex_ep_descs hs; };static inline struct f_obex *func_to_obex (struct usb_function *f)
@@ -227,12 +219,16 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)gserial_disconnect (&obex->port); } -if (!obex->port.in->desc) { +if (!obex->port.in->desc || !obex->port.out->desc) {DBG (cdev,"init obex ttyGS%d\n" , obex->port_num); - obex->port.in->desc =ep_choose (cdev->gadget, - obex->hs.obex_in, obex->fs.obex_in); - obex->port.out->desc =ep_choose (cdev->gadget, - obex->hs.obex_out, obex->fs.obex_out); +if (config_ep_by_speed (cdev->gadget, f, + obex->port.in) || +config_ep_by_speed (cdev->gadget, f, + obex->port.out)) { + obex->port.out->desc =NULL ; + obex->port.in->desc =NULL ; + goto fail; + } }if (alt ==1 ) {
@@ -346,11 +342,6 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)/* copy descriptors, and track endpoint copies */ f->descriptors =usb_copy_descriptors (fs_function); - obex->fs.obex_in =usb_find_endpoint (fs_function, - f->descriptors, &obex_fs_ep_in_desc); - obex->fs.obex_out =usb_find_endpoint (fs_function, - f->descriptors, &obex_fs_ep_out_desc); -/* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at * both speeds
@@ -364,11 +355,6 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)/* copy descriptors, and track endpoint copies */ f->hs_descriptors =usb_copy_descriptors (hs_function); - - obex->hs.obex_in =usb_find_endpoint (hs_function, - f->hs_descriptors, &obex_hs_ep_in_desc); - obex->hs.obex_out =usb_find_endpoint (hs_function, - f->hs_descriptors, &obex_hs_ep_out_desc); }/* Avoid letting this gadget enumerate until the userspace
drivers/usb/gadget/f_phonet.c +6 -6
@@ -424,12 +424,12 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)if (alt ==1 ) {int i; - fp->out_ep->desc =ep_choose (gadget, - &pn_hs_sink_desc, - &pn_fs_sink_desc); - fp->in_ep->desc =ep_choose (gadget, - &pn_hs_source_desc, - &pn_fs_source_desc); +if (config_ep_by_speed (gadget, f, fp->in_ep) || +config_ep_by_speed (gadget, f, fp->out_ep)) { + fp->in_ep->desc =NULL ; + fp->out_ep->desc =NULL ; +return -EINVAL ; + }usb_ep_enable (fp->out_ep);usb_ep_enable (fp->in_ep);
drivers/usb/gadget/f_rndis.c +13 -32
83 lines not on this page · raw message
drivers/usb/gadget/f_serial.c +8 -24
@@ -27,18 +27,10 @@* if you can arrange appropriate host side drivers. */ -struct gser_descs { -struct usb_endpoint_descriptor *in; -struct usb_endpoint_descriptor *out; -}; -struct f_gser {struct gserial port;u8 data_id;u8 port_num; - -struct gser_descs fs; -struct gser_descs hs; };static inline struct f_gser *func_to_gser (struct usb_function *f)
@@ -136,12 +128,15 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)if (gser->port.in->driver_data) {DBG (cdev,"reset generic ttyGS%d\n" , gser->port_num);gserial_disconnect (&gser->port); - }else { + } +if (!gser->port.in->desc || !gser->port.out->desc) {DBG (cdev,"activate generic ttyGS%d\n" , gser->port_num); - gser->port.in->desc =ep_choose (cdev->gadget, - gser->hs.in, gser->fs.in); - gser->port.out->desc =ep_choose (cdev->gadget, - gser->hs.out, gser->fs.out); +if (!config_ep_by_speed (cdev->gadget, f, gser->port.in) || + !config_ep_by_speed (cdev->gadget, f, gser->port.out)) { + gser->port.in->desc =NULL ; + gser->port.out->desc =NULL ; +return -EINVAL ; + } }gserial_connect (&gser->port, gser->port_num);return 0 ;
@@ -193,12 +188,6 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)/* copy descriptors, and track endpoint copies */ f->descriptors =usb_copy_descriptors (gser_fs_function); - gser->fs.in =usb_find_endpoint (gser_fs_function, - f->descriptors, &gser_fs_in_desc); - gser->fs.out =usb_find_endpoint (gser_fs_function, - f->descriptors, &gser_fs_out_desc); - -/* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at * both speeds
@@ -211,11 +200,6 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)/* copy descriptors, and track endpoint copies */ f->hs_descriptors =usb_copy_descriptors (gser_hs_function); - - gser->hs.in =usb_find_endpoint (gser_hs_function, - f->hs_descriptors, &gser_hs_in_desc); - gser->hs.out =usb_find_endpoint (gser_hs_function, - f->hs_descriptors, &gser_hs_out_desc); } DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
drivers/usb/gadget/f_sourcesink.c +6 -2
@@ -347,7 +347,9 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss)/* one endpoint writes (sources) zeroes IN (to the host) */ ep = ss->in_ep; - ep->desc =ep_choose (cdev->gadget, &hs_source_desc, &fs_source_desc); + result =config_ep_by_speed (cdev->gadget, &(ss->function), ep); +if (result) +return result; result =usb_ep_enable (ep);if (result <0 )return result;
@@ -364,7 +366,9 @@ fail:/* one endpoint reads (sinks) anything OUT (from the host) */ ep = ss->out_ep; - ep->desc =ep_choose (cdev->gadget, &hs_sink_desc, &fs_sink_desc); + result =config_ep_by_speed (cdev->gadget, &(ss->function), ep); +if (result) + goto fail; result =usb_ep_enable (ep);if (result <0 ) goto fail;
drivers/usb/gadget/f_subset.c +6 -23
@@ -57,18 +57,10 @@* caring about specific product and vendor IDs. */ -struct geth_descs { -struct usb_endpoint_descriptor *in; -struct usb_endpoint_descriptor *out; -}; -struct f_gether {struct gether port;char ethaddr[14 ]; - -struct geth_descs fs; -struct geth_descs hs; };static inline struct f_gether *func_to_geth (struct usb_function *f)
@@ -243,10 +235,12 @@ static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt) }DBG (cdev,"init + activate cdc subset\n" ); - geth->port.in_ep->desc =ep_choose (cdev->gadget, - geth->hs.in, geth->fs.in); - geth->port.out_ep->desc =ep_choose (cdev->gadget, - geth->hs.out, geth->fs.out); +if (config_ep_by_speed (cdev->gadget, f, geth->port.in_ep) || +config_ep_by_speed (cdev->gadget, f, geth->port.out_ep)) { + geth->port.in_ep->desc =NULL ; + geth->port.out_ep->desc =NULL ; +return -EINVAL ; + } net =gether_connect (&geth->port);return IS_ERR (net) ?PTR_ERR (net) :0 ;
@@ -297,12 +291,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)/* copy descriptors, and track endpoint copies */ f->descriptors =usb_copy_descriptors (fs_eth_function); - geth->fs.in =usb_find_endpoint (fs_eth_function, - f->descriptors, &fs_subset_in_desc); - geth->fs.out =usb_find_endpoint (fs_eth_function, - f->descriptors, &fs_subset_out_desc); - -/* support all relevant hardware speeds... we expect that when * hardware is dual speed, all bulk-capable endpoints work at * both speeds
@@ -315,11 +303,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)/* copy descriptors, and track endpoint copies */ f->hs_descriptors =usb_copy_descriptors (hs_eth_function); - - geth->hs.in =usb_find_endpoint (hs_eth_function, - f->hs_descriptors, &hs_subset_in_desc); - geth->hs.out =usb_find_endpoint (hs_eth_function, - f->hs_descriptors, &hs_subset_out_desc); }/* NOTE: all that is done without knowing or caring about
include/linux/usb/composite.h +0 -15
@@ -158,21 +158,6 @@ int usb_interface_id(struct usb_configuration *, struct usb_function *);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 -* @fs: descriptor to use for full or low speed operation -*/ -static inline struct usb_endpoint_descriptor * -ep_choose (struct usb_gadget *g,struct usb_endpoint_descriptor *hs, -struct usb_endpoint_descriptor *fs) -{ -if (gadget_is_dualspeed (g) && g->speed ==USB_SPEED_HIGH ) -return hs; -return fs; -} -#define MAX_CONFIG_INTERFACES 16/* arbitrary; max 255 */ /**
include/linux/usb/gadget.h +0 -6
@@ -875,12 +875,6 @@ int usb_gadget_config_buf(const struct usb_config_descriptor *config,struct usb_descriptor_header **usb_copy_descriptors (struct usb_descriptor_header **); -/* return copy of endpoint descriptor given original descriptor set */ -struct usb_endpoint_descriptor *usb_find_endpoint ( -struct usb_descriptor_header **src, -struct usb_descriptor_header **copy, -struct usb_endpoint_descriptor *match); -/** * usb_free_descriptors - free descriptors returned by usb_copy_descriptors() * @v: vector of descriptors
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.
PATCH v3 4/4 usb:gadget: Add SuperSpeed support to the Gadget Framework
This patch adds the SuperSpeed functionality to the gadget framework. In order not to force all the gadget drivers to supply SuperSpeed descriptors when operating in SuperSpeed mode the following approach was taken:
If we're operating in SuperSpeed mode and the gadget driver didn't supply SuperSpeed descriptors, the composite layer will automatically create SuperSpeed descriptors with default values.
Support for new SuperSpeed BOS descriptor was added.
Support for SET_FEATURE and GET_STATUS requests in SuperSpeed mode was added.
--- drivers/usb/gadget/Kconfig | 12 ++ drivers/usb/gadget/composite.c | 366 +++++++++++++++++++++++++++++++++++++--- include/linux/usb/composite.h | 25 +++ include/linux/usb/gadget.h | 29 +++ 4 files changed, 411 insertions(+), 21 deletions(-)
drivers/usb/gadget/Kconfig +12 -0
@@ -552,6 +552,18 @@ config USB_GADGET_DUALSPEED Means that gadget drivers should include extra descriptors and code to handle dual-speed controllers. +config USB_GADGET_SUPERSPEED + boolean "Gadget operating in Super Speed" + depends on USB_GADGET + depends on USB_GADGET_DUALSPEED + default n + help + Enabling this feature enables Super Speed support in the Gadget + driver. It means that gadget drivers should provide extra (SuperSpeed) + descriptors to the host. + For composite devices: if SuperSpeed descriptors weren't supplied by + the FD, they will be automatically generated with default values. + # # USB Gadget Drivers #
drivers/usb/gadget/composite.c +345 -21
525 lines not on this page · raw message
include/linux/usb/composite.h +25 -0
@@ -51,6 +51,18 @@ struct usb_configuration;* @hs_descriptors: Table of high speed descriptors, using interface and * string identifiers assigned during @bind(). If this pointer is null, * the function will not be available at high speed. +* @ss_descriptors: Table of super speed descriptors. If +* wasnt supplied by the FD during @bind() and +* !ss_not_capble, will be generated automaticly with +* default values while working in superspeed mode. If this +* pointer is null after initiation, the function will not +* be available at super speed. +* @ss_not_capable: This flag is used by the FD to indicate if +* this function is SS capble. Meaning: if SS descriptors +* weren't supplied by the FD, and the flag is set ss +* descriptors will NOT be automatically generated +* @ss_desc_allocated: This flag indicates whether the ss descriptors were +* dynamically allocated (and needs to be released). * @config: assigned when @usb_add_function() is called; this is the * configuration with which this function is associated. * @bind: Before the gadget can register, all of its functions bind() to the
@@ -69,6 +81,10 @@ struct usb_configuration;* @setup: Used for interface-specific control requests. * @suspend: Notifies functions when the host stops sending USB traffic. * @resume: Notifies functions when the host restarts USB traffic. +* @get_status: Returns function status as a reply to +* GetStatus() request when the recepient is Interface. +* @func_suspend: callback to be called when +* SetFeature(FUNCTION_SUSPEND) is reseived * * A single USB function uses one or more interfaces, and should in most * cases support operation at both full and high speeds. Each function is
@@ -98,6 +114,10 @@ struct usb_function {struct usb_gadget_strings **strings;struct usb_descriptor_header **descriptors;struct usb_descriptor_header **hs_descriptors; +struct usb_descriptor_header **ss_descriptors; + + unsigned ss_desc_allocated:1; + unsigned ss_not_capable:1;struct usb_configuration *config;
@@ -124,6 +144,10 @@ struct usb_function {void (*suspend)(struct usb_function *);void (*resume)(struct usb_function *); +/* USB 3.0 additions */ +int (*get_status)(struct usb_function *); +int (*func_suspend)(struct usb_function *, +u8 suspend_opt);/* private: */ /* internals */ struct list_head list;
@@ -232,6 +256,7 @@ struct usb_configuration {struct list_head list;struct list_head functions;u8 next_interface_id; + unsigned superspeed:1; unsigned highspeed:1; unsigned fullspeed:1;struct usb_function *interface[MAX_CONFIG_INTERFACES ];
include/linux/usb/gadget.h +29 -0
@@ -136,6 +136,8 @@ struct usb_ep_ops {* descriptor that matches connection speed * @desc:endpoint descriptor. this pointer set before endpoint is enabled and * remains valid until the endpoint is disabled. +* @comp_desc: In case of SuperSpeed support, this is the +* endpoint companion descriptor that is used to configure the endpoint * * the bus controller driver lists all the general purpose endpoints in * gadget->ep_list. the control endpoint (gadget->ep0) is not in that list,
@@ -150,6 +152,7 @@ struct usb_ep { unsigned maxpacket:16;u8 bEndpointAddress;struct usb_endpoint_descriptor *desc; +struct usb_ss_ep_comp_descriptor *comp_desc; };/*-------------------------------------------------------------------------*/
@@ -417,6 +420,14 @@ static inline void usb_ep_fifo_flush(struct usb_ep *ep)/*-------------------------------------------------------------------------*/ +struct usb_dcd_config_params { +__u8 bU1devExitLat;/* U1 Device exit Latency */ +#define USB_DEFULT_U1_DEV_EXIT_LAT 0x01/* Less then 1 microsec */ +__u16 bU2DevExitLat;/* U2 Device exit Latency */ +#define USB_DEFULT_U2_DEV_EXIT_LAT 0x1F4/* Less then 500 microsec */ +}; + +struct usb_gadget ;/* the rest of the api to the controller hardware: device operations,
@@ -431,6 +442,7 @@ struct usb_gadget_ops {int (*pullup) (struct usb_gadget *,int is_on);int (*ioctl)(struct usb_gadget *,unsigned code,unsigned long param); +void (*get_config_params)(struct usb_dcd_config_params *); };/**
@@ -522,6 +534,23 @@ static inline int gadget_is_dualspeed(struct usb_gadget *g) }/** +* gadget_is_superspeed() - return true if the hardware handles +* supperspeed +* @g: controller that might support supper speed +*/ +static inline int gadget_is_superspeed (struct usb_gadget *g) +{ +#ifdef CONFIG_USB_GADGET_SUPERSPEED +/* runtime test would check "g->is_superspeed" ... that might be +* useful to work around hardware bugs, but is mostly pointless +*/ +return 1 ; +#else +return 0 ; +#endif +} + +/** * gadget_is_otg - return true iff the hardware is OTG-ready * @g: controller that might have a Mini-AB connector *
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.
Re: [RFC/PATCH v3 2/4] usb: Configure endpoint according to gadget speed.
In reply to Tatyana Brokhmanmaybe Bob has an opinion ...
-mike
Quoted 181 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.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| 8 +++--4 files changed, 103 insertions(+), 3 deletions(-)drivers/usb/gadget/composite.c +76
-0@@ -70,6 +70,82 @@ module_param(iSerialNumber, charp, 0); MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); /*-------------------------------------------------------------------------*/ +/** +* 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 +5
-4@@ -132,9 +132,10 @@ 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. - * @desc:endpoint descriptor. This pointer set before endpoint - * is enabled and remains valid until the endpoint is - * disabled. + * @bEndpointAddress: used to identify the endpoint when finding + * descriptor that matches connection speed + * @desc:endpoint descriptor. this pointer set before endpoint is enabled and + * remains valid until the endpoint is disabled. * * the bus controller driver lists all the general purpose endpoints in * gadget->ep_list. the control endpoint (gadget->ep0) is not in that list,@@ -147,6 +148,7 @@ struct usb_ep { const struct usb_ep_ops *ops; struct list_head ep_list; unsigned maxpacket:16; + u8 bEndpointAddress; struct usb_endpoint_descriptor *desc; }; --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. --
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC/PATCH v3 1/4] usb: Add usb_endpoint_descriptor to be part of the struct usb_ep
In reply to a message not in the archiveQuoted 15 lines · Tatyana Brokhman
Change
usb_ep_enable()prototype to use endpoint descriptor fromusb_ep. This optimization spares the FDs from saving the endpoint chosen descriptor. This optimization is not full though. To fully exploit this change one needs to update all the UDCs as well since in the current implementation each of them saves the endpoint descriptor in it's internal (and extended) endpoint structure.Signed-off-by Tatyana Brokhman <[email protected]>drivers/usb/gadget/file_storage.c +0
-0
drivers/usb/gadget/file_storage.c static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep, · line 2752
Quoted 9 lines
drivers/usb/gadget/file_storage.c +2
-1@@ -2745,7 +2745,8 @@ static int enable_endpoint(struct fsg_dev *fsg, struct usb_ep *ep,int rc; ep->driver_data = fsg; - rc =usb_ep_enable (ep, d); + ep->desc = (struct usb_endpoint_descriptor *)d; + rc =usb_ep_enable (ep);if (rc)ERROR (fsg,"can't enable %s, result %d\n" , ep->name, rc);return rc;
Instead of casting the variable, you should remove the "const" qualifiers here and in the callers. After all, if usb_ep_enable is going to change the descriptor then we shouldn't call it "const".
Alternatively, if usb_ep_enable _isn't_ going to change the descriptor then perhaps the new pointer added to usb_ep should be declared "const".
Alan Stern
Hello All
I've sent the bellow patch series for review more then a week ago and got only one comment on one of the patches. I'm not sure what I'm supposed to do next. Does this mean that the rest of them are ok? Should I resend them?
Right after this series I've uploaded another patch series adding SuperSpeed support to the dummy_hcd framework. The above applies to that as well.
I'm sorry if this email is not inappropriate; I'm new at this and still learning the code release process.
Thank you for your support
Best Regards
Tanya Brokhman
Quoted 50 lines
This patch series adds Super Speed support to the Gadget framework. This is a third version of an already sent series. It was split into additional
two patches.Tatyana Brokhman (4):
usb: Addusb_endpoint_descriptorto be part of the structusb_ep
usb: Configure endpoint according to gadget speed.
usb: Modify existing gadget drivers to useconfig_ep_by_speed()
instead ofep_choose.
usb:gadget: Add SuperSpeed support to the Gadget Frameworkdrivers/usb/gadget/Kconfig | 12 + drivers/usb/gadget/composite.c | 440 +++++++++++++++++++++++++++++++++-- drivers/usb/gadget/config.c | 25 -- drivers/usb/gadget/dbgp.c | 8 +- drivers/usb/gadget/epautoconf.c | 1 + drivers/usb/gadget/f_acm.c | 50 ++--- drivers/usb/gadget/f_audio.c | 5 +- drivers/usb/gadget/f_ecm.c | 54 ++--- drivers/usb/gadget/f_eem.c | 36 +-- drivers/usb/gadget/f_fs.c | 3 +- drivers/usb/gadget/f_hid.c | 22 +-- drivers/usb/gadget/f_loopback.c | 17 +- drivers/usb/gadget/f_mass_storage.c | 3 +- drivers/usb/gadget/f_obex.c | 32 +-- drivers/usb/gadget/f_phonet.c | 17 +- drivers/usb/gadget/f_rndis.c | 52 ++--- drivers/usb/gadget/f_serial.c | 32 +-- drivers/usb/gadget/f_sourcesink.c | 14 +- drivers/usb/gadget/f_subset.c | 33 +-- drivers/usb/gadget/f_uvc.c | 6 +- drivers/usb/gadget/file_storage.c | 3 +- drivers/usb/gadget/gmidi.c | 6 +- drivers/usb/gadget/inode.c | 6 +- drivers/usb/gadget/printer.c | 26 ++- drivers/usb/gadget/u_ether.c | 12 +- drivers/usb/gadget/u_ether.h | 4 - drivers/usb/gadget/u_serial.c | 4 +- drivers/usb/gadget/u_serial.h | 2 - include/linux/usb/composite.h | 55 ++++- include/linux/usb/gadget.h | 64 ++++-- 30 files changed, 741 insertions(+), 361 deletions(-)--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 4 lines · --- On Tue, 11/9/10, [email protected] <[email protected]> wrote:
Hello All
I've sent the bellow patch series for review more then a week ago
And that wasn't the first iteration (v1,v2,v3).
and got
Quoted 3 lines
only one comment on one of the patches. I'm not sure what I'm supposed to
do next.
You could try responding to the questions that I asked a while back (probably for V1 or V2).
There were both "why" questions, and another approach to handling the endpoint descriptors.
Lack of answers to those questions is why your last post of these framework patches is still sitting in my mailbox waiting for review (or more likely deletion).
Does this mean that the rest of them are ok?
Quoted 2 lines
Should I resend
them?
Answer to both questions is "NO". First deal with those ignored questions. They're surely at least a month old by now. They should have gone to the list, but maybe mailer misbehavior sent them to a smaller audience (just you, etc).
If absolutely necessary, I can probably dig up those emails again and re-send; better if you try to find them first, and respond.
I think they're the last emails from me on these threads.
- Dave
Quoted 5 lines · David Brownell
If absolutely necessary, I can probably dig up those emails again and re-send; better if you try to find them first, and respond.
I think they're the last emails from me on these threads.
These questions?
http://www.spinics.net/lists/linux-usb/msg36962.html
http://www.spinics.net/lists/linux-usb/msg37285.html
It looks like the first round of these patches didn't CC linux-arm-msm, so I didn't see your questions.
Daniel
Signature · 2 lines
Sent by a consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
Quoted 11 lines
Quoted 6 lines
If absolutely necessary, I can probably dig up those emails again and re-send; better if you try to find them first, and respond.
I think they're the last emails from me on these threads.These questions?
http://www.spinics.net/lists/linux-usb/msg36962.html
http://www.spinics.net/lists/linux-usb/msg37285.html
No; those are old, not the most
recent questions.
Quoted 4 lines
It looks like the first round of these patches didn't CC linux-arm-msm,
so I didn't see your questions.
Is that an open list, or one that trashes email
from non-subscribers?
Regardless, linux-usb is where I'd expect to
see such discussions archived.
- Dave
Quoted 6 lines · David Brownell
Quoted 6 lines
Quoted 5 lines
If absolutely necessary, I can probably dig up those emails again and re-send; better if you try to find them first, and respond.
I think they're the last emails from me on these threads.
Quoted 7 lines
Quoted 4 lines
These questions?
http://www.spinics.net/lists/linux-usb/msg36962.html
http://www.spinics.net/lists/linux-usb/msg37285.htmlNo; those are old, not the most
recent questions.
Ok.
Quoted 7 lines
Quoted 4 lines
It looks like the first round of these patches didn't CC linux-arm-msm,
so I didn't see your questions.Is that an open list, or one that trashes email
from non-subscribers?
open list. It's on vger.
Daniel
Signature · 2 lines
Sent by a consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
Quoted 6 lines · David Brownell
Quoted 3 lines
It looks like the first round of these patches didn't CC linux-arm-msm,
so I didn't see your questions.Is that an open list, or one that trashes email
from non-subscribers?
It's on vger, same place as most of the lists. The archives don't seem to be working, I'll look into that.
David
Hello Dave,
Thank you for your quick response!
This is a surprise to me since I did address all the comments/questions I got, especially the ones from so long ago. The only thing in my TODO list is the comment on the latest version of this series but I'm waiting for more inputs.
I've located all your questions and my answers to them in my sent-items and will resend them all in a sec.
Please let me know if I did miss something and if this is the case accept my apology. I'll be happy to address any questions/comments you might have.
Thanks
Tanya Brokhman
Quoted 55 lines
--- On Tue, 11/9/10, [email protected] <[email protected]>
Quoted 4 lines · wrote:
Hello All
I've sent the bellow patch series for review more then a week ago
And that wasn't the first iteration (v1,v2,v3).
and got
Quoted 3 lines
only one comment on one of the patches. I'm not sure what I'm supposed to
do next.You could try responding to the questions that I asked a while back (probably for V1 or V2).
There were both "why" questions, and another approach to handling the endpoint descriptors.
Lack of answers to those questions is why your last post of these framework patches is still sitting in my mailbox waiting for review (or more likely deletion).
Does this mean that the rest of them are ok?
Quoted 2 lines
Should I resend
them?Answer to both questions is "NO". First deal with those ignored questions. They're surely at least a month old by now. They should have gone to the list, but maybe mailer misbehavior sent them to a smaller audience (just you, etc).
If absolutely necessary, I can probably dig up those emails again and re-send; better if you try to find them first, and respond.
I think they're the last emails from me on these threads.- Dave
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html