usb gadget: Add SuperSpeed support to the Gadget Framework
Subsystems (2)
v12 cover usb gadget: Add SuperSpeed support to the Gadget Framework
It was tested in the following ways:
1. Dummy_hcd and g_zero gadget with our internally developed unittest. (See bellow)
2. Our DCD (that is not ready for upstreaming yet but we're working on it) and g_mass_storage gadget. With this setup we passed USBCV 2.0 and 3.0.
3. We developed a UAS gadget driver that is also working with this implementation over our DCD and the UAS Linux host driver. Its operational both in SS and in HS mode. Was released to the community in another patch series.
4. All of the other existing gadget drivers were minimally testes on the dummy_hcd setup as well (successful enumeration).
The unittest framework that was used for testing can be downloaded fromgit://codeaurora.org/quic/usb3/ut/.git
Please use the upstream branch.
See https://www.codeaurora.org/gitweb/quic/usb3/?p=ut/.git;a=summary for more details.
Tatyana Brokhman (8):
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
usb: Add streams support to the gadget framework usb:dummy_hcd: use the shared_hcd infrastructure
usb: Adding SuperSpeed support to dummy_hcd usb:gadget: coding style fixes
drivers/usb/gadget/Kconfig | 11 + drivers/usb/gadget/composite.c | 356 ++++++++++++- drivers/usb/gadget/config.c | 25 - drivers/usb/gadget/dbgp.c | 8 +- drivers/usb/gadget/dummy_hcd.c | 997 ++++++++++++++++++++++++++--------- drivers/usb/gadget/epautoconf.c | 133 ++++- 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 | 33 +- drivers/usb/gadget/f_ncm.c | 58 +-- 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/ch9.h | 2 - include/linux/usb/composite.h | 32 +- include/linux/usb/gadget.h | 69 ++- 33 files changed, 1457 insertions(+), 703 deletions(-)
Signature · 5 lines
1.7.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 v12 1/8 usb: Add usb_endpoint_descriptor to be part of the struct usb_ep
Change usb_ep_enable() prototype to use endpoint descriptor from usb_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.
--- drivers/usb/gadget/dbgp.c | 8 +++++--- drivers/usb/gadget/f_acm.c | 9 ++++----- drivers/usb/gadget/f_audio.c | 5 ++--- drivers/usb/gadget/f_ecm.c | 17 ++++++++--------- drivers/usb/gadget/f_eem.c | 10 +++++----- drivers/usb/gadget/f_fs.c | 3 ++- drivers/usb/gadget/f_hid.c | 5 ++--- drivers/usb/gadget/f_loopback.c | 14 ++++++-------- drivers/usb/gadget/f_mass_storage.c | 3 ++- drivers/usb/gadget/f_ncm.c | 17 ++++++++--------- drivers/usb/gadget/f_obex.c | 6 +++--- drivers/usb/gadget/f_phonet.c | 9 ++++----- drivers/usb/gadget/f_rndis.c | 15 +++++++-------- drivers/usb/gadget/f_serial.c | 4 ++-- drivers/usb/gadget/f_sourcesink.c | 10 ++++------ drivers/usb/gadget/f_subset.c | 8 ++++---- 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/gadget.h | 16 +++++++--------- 26 files changed, 111 insertions(+), 117 deletions(-)
drivers/usb/gadget/dbgp.c +5 -3
@@ -173,7 +173,9 @@ fail_1:static int __enable_ep (struct usb_ep *ep,struct usb_endpoint_descriptor *desc) { -int err =usb_ep_enable (ep, desc); +int err; + ep->desc = desc; + err =usb_ep_enable (ep); ep->driver_data = dbgp.gadget;return err; }
@@ -268,8 +270,8 @@ static int __init dbgp_configure_endpoints(struct usb_gadget *gadget) dbgp.serial->in = dbgp.i_ep; dbgp.serial->out = dbgp.o_ep; - dbgp.serial->in_desc = &i_desc; - dbgp.serial->out_desc = &o_desc; + dbgp.serial->in->desc = &i_desc; + dbgp.serial->out->desc = &o_desc;if (gserial_setup (gadget,1 ) <0 ) { stp =3 ;
drivers/usb/gadget/f_acm.c +4 -5
@@ -62,7 +62,6 @@ struct f_acm {struct acm_ep_descs hs;struct usb_ep *notify; -struct usb_endpoint_descriptor *notify_desc;struct usb_request *notify_req;struct usb_cdc_line_coding port_line_coding;/* 8-N-1 etc */
@@ -405,11 +404,11 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)usb_ep_disable (acm->notify); }else {VDBG (cdev,"init acm ctrl interface %d\n" , intf); - acm->notify_desc =ep_choose (cdev->gadget, + acm->notify->desc =ep_choose (cdev->gadget, acm->hs.notify, acm->fs.notify); } -usb_ep_enable (acm->notify, acm->notify_desc); +usb_ep_enable (acm->notify); acm->notify->driver_data = acm; }else if (intf == acm->data_id) {
@@ -418,9 +417,9 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)gserial_disconnect (&acm->port); }else {DBG (cdev,"activate acm ttyGS%d\n" , acm->port_num); - acm->port.in_desc =ep_choose (cdev->gadget, + acm->port.in->desc =ep_choose (cdev->gadget, acm->hs.in, acm->fs.in); - acm->port.out_desc =ep_choose (cdev->gadget, + acm->port.out->desc =ep_choose (cdev->gadget, acm->hs.out, acm->fs.out); }gserial_connect (&acm->port, acm->port_num);
drivers/usb/gadget/f_audio.c +2 -3
@@ -279,7 +279,6 @@ struct f_audio {/* endpoints handle full and/or high speeds */ struct usb_ep *out_ep; -struct usb_endpoint_descriptor *out_desc;spinlock_t lock;struct f_audio_buf *copy_buf;
@@ -575,7 +574,7 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)if (intf ==1 ) {if (alt ==1 ) { -usb_ep_enable (out_ep, audio->out_desc); +usb_ep_enable (out_ep); out_ep->driver_data = audio; audio->copy_buf =f_audio_buffer_alloc (audio_buf_size);if (IS_ERR (audio->copy_buf))
@@ -677,6 +676,7 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)if (!ep) goto fail; audio->out_ep = ep; + audio->out_ep->desc = &as_out_ep_desc; ep->driver_data = cdev;/* claim */ status = -ENOMEM ;
@@ -776,7 +776,6 @@ int __init audio_bind_config(struct usb_configuration *c) audio->card.func.set_alt = f_audio_set_alt; audio->card.func.setup = f_audio_setup; audio->card.func.disable = f_audio_disable; - audio->out_desc = &as_out_ep_desc;control_selector_init (audio);
drivers/usb/gadget/f_ecm.c +8 -9
@@ -68,7 +68,6 @@ struct f_ecm {struct ecm_ep_descs hs;struct usb_ep *notify; -struct usb_endpoint_descriptor *notify_desc;struct usb_request *notify_req;u8 notify_state;bool is_open;
@@ -466,11 +465,11 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)usb_ep_disable (ecm->notify); }else {VDBG (cdev,"init ecm ctrl %d\n" , intf); - ecm->notify_desc =ep_choose (cdev->gadget, + ecm->notify->desc =ep_choose (cdev->gadget, ecm->hs.notify, ecm->fs.notify); } -usb_ep_enable (ecm->notify, ecm->notify_desc); +usb_ep_enable (ecm->notify); ecm->notify->driver_data = ecm;/* Data interface has two altsettings, 0 and 1 */
@@ -483,11 +482,11 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)gether_disconnect (&ecm->port); } -if (!ecm->port.in) { +if (!ecm->port.in_ep->desc) {DBG (cdev,"init ecm\n" ); - ecm->port.in =ep_choose (cdev->gadget, + ecm->port.in_ep->desc =ep_choose (cdev->gadget, ecm->hs.in, ecm->fs.in); - ecm->port.out =ep_choose (cdev->gadget, + ecm->port.out_ep->desc =ep_choose (cdev->gadget, ecm->hs.out, ecm->fs.out); }
@@ -549,7 +548,7 @@ static void ecm_disable(struct usb_function *f)if (ecm->notify->driver_data) {usb_ep_disable (ecm->notify); ecm->notify->driver_data =NULL ; - ecm->notify_desc =NULL ; + ecm->notify->desc =NULL ; } }
@@ -723,9 +722,9 @@ fail:/* we might as well release our claims on endpoints */ if (ecm->notify) ecm->notify->driver_data =NULL ; -if (ecm->port.out) +if (ecm->port.out_ep->desc) ecm->port.out_ep->driver_data =NULL ; -if (ecm->port.in) +if (ecm->port.in_ep->desc) ecm->port.in_ep->driver_data =NULL ;ERROR (cdev,"%s: can't bind, err %d\n" , f->name, status);
drivers/usb/gadget/f_eem.c +5 -5
@@ -176,11 +176,11 @@ static int eem_set_alt(struct usb_function *f, unsigned intf, unsigned alt)gether_disconnect (&eem->port); } -if (!eem->port.in) { +if (!eem->port.in_ep->desc) {DBG (cdev,"init eem\n" ); - eem->port.in =ep_choose (cdev->gadget, + eem->port.in_ep->desc =ep_choose (cdev->gadget, eem->hs.in, eem->fs.in); - eem->port.out =ep_choose (cdev->gadget, + eem->port.out_ep->desc =ep_choose (cdev->gadget, eem->hs.out, eem->fs.out); }
@@ -289,9 +289,9 @@ fail:usb_free_descriptors (f->descriptors);/* we might as well release our claims on endpoints */ -if (eem->port.out) +if (eem->port.out_ep->desc) eem->port.out_ep->driver_data =NULL ; -if (eem->port.in) +if (eem->port.in_ep->desc) eem->port.in_ep->driver_data =NULL ;ERROR (cdev,"%s: can't bind, err %d\n" , f->name, status);
drivers/usb/gadget/f_fs.c +2 -1
@@ -1544,7 +1544,8 @@ static int ffs_func_eps_enable(struct ffs_function *func) ds = ep->descs[ep->descs[1 ] ?1 :0 ]; ep->ep->driver_data = ep; - ret =usb_ep_enable (ep->ep, ds); + ep->ep->desc = ds; + ret =usb_ep_enable (ep->ep);if (likely (!ret)) { epfile->ep = ep; epfile->in =usb_endpoint_dir_in (ds);
drivers/usb/gadget/f_hid.c +2 -3
@@ -416,7 +416,6 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) {struct usb_composite_dev *cdev = f->config->cdev;struct f_hidg *hidg =func_to_hidg (f); -const struct usb_endpoint_descriptor *ep_desc;int status =0 ;VDBG (cdev,"hidg_set_alt intf:%d alt:%d\n" , intf, alt);
@@ -426,9 +425,9 @@ 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); - ep_desc =ep_choose (f->config->cdev->gadget, + hidg->in_ep->desc =ep_choose (f->config->cdev->gadget, hidg->hs_in_ep_desc, hidg->fs_in_ep_desc); - status =usb_ep_enable (hidg->in_ep, ep_desc); + status =usb_ep_enable (hidg->in_ep);if (status <0 ) {ERROR (cdev,"Enable endpoint FAILED!\n" ); goto fail;
drivers/usb/gadget/f_loopback.c +6 -8
@@ -250,26 +250,24 @@ static int enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop) { int result = 0; -const struct usb_endpoint_descriptor *src, *sink;struct usb_ep *ep;struct usb_request *req;unsigned i; - src =ep_choose (cdev->gadget, - &hs_loop_source_desc, &fs_loop_source_desc); - sink =ep_choose (cdev->gadget, - &hs_loop_sink_desc, &fs_loop_sink_desc); -/* one endpoint writes data back IN to the host */ ep = loop->in_ep; - result =usb_ep_enable (ep, src); + ep->desc =ep_choose (cdev->gadget, + &hs_loop_source_desc, &fs_loop_source_desc); + result =usb_ep_enable (ep);if (result <0 )return result; ep->driver_data = loop;/* one endpoint just reads OUT packets */ ep = loop->out_ep; - result =usb_ep_enable (ep, sink); + ep->desc =ep_choose (cdev->gadget, + &hs_loop_sink_desc, &fs_loop_sink_desc); + result =usb_ep_enable (ep);if (result <0 ) { fail0: ep = loop->in_ep;
drivers/usb/gadget/f_mass_storage.c +2 -1
@@ -2330,7 +2330,8 @@ static int enable_endpoint(struct fsg_common *common, struct usb_ep *ep,int rc; ep->driver_data = common; - rc =usb_ep_enable (ep, d); + ep->desc = (struct usb_endpoint_descriptor *)d; + rc =usb_ep_enable (ep);if (rc)ERROR (common,"can't enable %s, result %d\n" , ep->name, rc);return rc;
drivers/usb/gadget/f_ncm.c +8 -9
@@ -70,7 +70,6 @@ struct f_ncm {struct ncm_ep_descs hs;struct usb_ep *notify; -struct usb_endpoint_descriptor *notify_desc;struct usb_request *notify_req;u8 notify_state;bool is_open;
@@ -804,11 +803,11 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)usb_ep_disable (ncm->notify); }else {DBG (cdev,"init ncm ctrl %d\n" , intf); - ncm->notify_desc =ep_choose (cdev->gadget, + ncm->notify->desc =ep_choose (cdev->gadget, ncm->hs.notify, ncm->fs.notify); } -usb_ep_enable (ncm->notify, ncm->notify_desc); +usb_ep_enable (ncm->notify); ncm->notify->driver_data = ncm;/* Data interface has two altsettings, 0 and 1 */
@@ -829,12 +828,12 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)if (alt ==1 ) {struct net_device *net; -if (!ncm->port.in) { +if (!ncm->port.in_ep->desc) {DBG (cdev,"init ncm\n" ); - ncm->port.in =ep_choose (cdev->gadget, + ncm->port.in_ep->desc =ep_choose (cdev->gadget, ncm->hs.in, ncm->fs.in); - ncm->port.out =ep_choose (cdev->gadget, + ncm->port.out_ep->desc =ep_choose (cdev->gadget, ncm->hs.out, ncm->fs.out); }
@@ -1111,7 +1110,7 @@ static void ncm_disable(struct usb_function *f)if (ncm->notify->driver_data) {usb_ep_disable (ncm->notify); ncm->notify->driver_data =NULL ; - ncm->notify_desc =NULL ; + ncm->notify->desc =NULL ; } }
@@ -1288,9 +1287,9 @@ fail:/* we might as well release our claims on endpoints */ if (ncm->notify) ncm->notify->driver_data =NULL ; -if (ncm->port.out) +if (ncm->port.out_ep->desc) ncm->port.out_ep->driver_data =NULL ; -if (ncm->port.in) +if (ncm->port.in_ep->desc) ncm->port.in_ep->driver_data =NULL ;ERROR (cdev,"%s: can't bind, err %d\n" , f->name, status);
drivers/usb/gadget/f_obex.c +3 -3
@@ -227,11 +227,11 @@ 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) {DBG (cdev,"init obex ttyGS%d\n" , obex->port_num); - obex->port.in_desc =ep_choose (cdev->gadget, + 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->port.out->desc =ep_choose (cdev->gadget, obex->hs.obex_out, obex->fs.obex_out); }
drivers/usb/gadget/f_phonet.c +4 -5
@@ -427,17 +427,16 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)spin_lock (&port->lock);__pn_reset (f);if (alt ==1 ) { -struct usb_endpoint_descriptor *out, *in;int i; - out =ep_choose (gadget, + fp->out_ep->desc =ep_choose (gadget, &pn_hs_sink_desc, &pn_fs_sink_desc); - in =ep_choose (gadget, + fp->in_ep->desc =ep_choose (gadget, &pn_hs_source_desc, &pn_fs_source_desc); -usb_ep_enable (fp->out_ep, out); -usb_ep_enable (fp->in_ep, in); +usb_ep_enable (fp->out_ep); +usb_ep_enable (fp->in_ep); port->usb = fp; fp->out_ep->driver_data = fp;
drivers/usb/gadget/f_rndis.c +7 -8
@@ -92,7 +92,6 @@ struct f_rndis {struct rndis_ep_descs hs;struct usb_ep *notify; -struct usb_endpoint_descriptor *notify_desc;struct usb_request *notify_req;atomic_t notify_count; };
@@ -486,11 +485,11 @@ static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)usb_ep_disable (rndis->notify); }else {VDBG (cdev,"init rndis ctrl %d\n" , intf); - rndis->notify_desc =ep_choose (cdev->gadget, + rndis->notify->desc =ep_choose (cdev->gadget, rndis->hs.notify, rndis->fs.notify); } -usb_ep_enable (rndis->notify, rndis->notify_desc); +usb_ep_enable (rndis->notify); rndis->notify->driver_data = rndis; }else if (intf == rndis->data_id) {
@@ -501,11 +500,11 @@ static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)gether_disconnect (&rndis->port); } -if (!rndis->port.in) { +if (!rndis->port.in_ep->desc) {DBG (cdev,"init rndis\n" ); - rndis->port.in =ep_choose (cdev->gadget, + rndis->port.in_ep->desc =ep_choose (cdev->gadget, rndis->hs.in, rndis->fs.in); - rndis->port.out =ep_choose (cdev->gadget, + rndis->port.out_ep->desc =ep_choose (cdev->gadget, rndis->hs.out, rndis->fs.out); }
@@ -738,9 +737,9 @@ fail:/* we might as well release our claims on endpoints */ if (rndis->notify) rndis->notify->driver_data =NULL ; -if (rndis->port.out) +if (rndis->port.out_ep->desc) rndis->port.out_ep->driver_data =NULL ; -if (rndis->port.in) +if (rndis->port.in_ep->desc) rndis->port.in_ep->driver_data =NULL ;ERROR (cdev,"%s: can't bind, err %d\n" , f->name, status);
drivers/usb/gadget/f_serial.c +2 -2
@@ -138,9 +138,9 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)gserial_disconnect (&gser->port); }else {DBG (cdev,"activate generic ttyGS%d\n" , gser->port_num); - gser->port.in_desc =ep_choose (cdev->gadget, + gser->port.in->desc =ep_choose (cdev->gadget, gser->hs.in, gser->fs.in); - gser->port.out_desc =ep_choose (cdev->gadget, + gser->port.out->desc =ep_choose (cdev->gadget, gser->hs.out, gser->fs.out); }gserial_connect (&gser->port, gser->port_num);
drivers/usb/gadget/f_sourcesink.c +4 -6
@@ -343,15 +343,12 @@ static int enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss) { int result = 0; -const struct usb_endpoint_descriptor *src, *sink;struct usb_ep *ep; - src =ep_choose (cdev->gadget, &hs_source_desc, &fs_source_desc); - sink =ep_choose (cdev->gadget, &hs_sink_desc, &fs_sink_desc); -/* one endpoint writes (sources) zeroes IN (to the host) */ ep = ss->in_ep; - result =usb_ep_enable (ep, src); + ep->desc =ep_choose (cdev->gadget, &hs_source_desc, &fs_source_desc); + result =usb_ep_enable (ep);if (result <0 )return result; ep->driver_data = ss;
@@ -367,7 +364,8 @@ fail:/* one endpoint reads (sinks) anything OUT (from the host) */ ep = ss->out_ep; - result =usb_ep_enable (ep, sink); + ep->desc =ep_choose (cdev->gadget, &hs_sink_desc, &fs_sink_desc); + result =usb_ep_enable (ep);if (result <0 ) goto fail; ep->driver_data = ss;
drivers/usb/gadget/f_subset.c +4 -4
@@ -243,9 +243,9 @@ static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt) }DBG (cdev,"init + activate cdc subset\n" ); - geth->port.in =ep_choose (cdev->gadget, + geth->port.in_ep->desc =ep_choose (cdev->gadget, geth->hs.in, geth->fs.in); - geth->port.out =ep_choose (cdev->gadget, + geth->port.out_ep->desc =ep_choose (cdev->gadget, geth->hs.out, geth->fs.out); net =gether_connect (&geth->port);
@@ -334,9 +334,9 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) fail:/* we might as well release our claims on endpoints */ -if (geth->port.out) +if (geth->port.out_ep->desc) geth->port.out_ep->driver_data =NULL ; -if (geth->port.in) +if (geth->port.in_ep->desc) geth->port.in_ep->driver_data =NULL ;ERROR (cdev,"%s: can't bind, err %d\n" , f->name, status);
drivers/usb/gadget/f_uvc.c +4 -2
@@ -262,8 +262,10 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)if (uvc->state !=UVC_STATE_CONNECTED )return 0 ; -if (uvc->video.ep) -usb_ep_enable (uvc->video.ep, &uvc_streaming_ep); +if (uvc->video.ep) { + uvc->video.ep->desc = &uvc_streaming_ep; +usb_ep_enable (uvc->video.ep); + }memset (&v4l2_event,0 ,sizeof (v4l2_event)); v4l2_event.type =UVC_EVENT_STREAMON ;
drivers/usb/gadget/file_storage.c +2 -1
@@ -2713,7 +2713,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 = d; + rc =usb_ep_enable (ep);if (rc)ERROR (fsg,"can't enable %s, result %d\n" , ep->name, rc);return rc;
drivers/usb/gadget/gmidi.c +4 -2
@@ -537,14 +537,16 @@ static int set_gmidi_config(struct gmidi_device *dev, gfp_t gfp_flags)struct usb_ep *ep;unsigned i; - err =usb_ep_enable (dev->in_ep, &bulk_in_desc); + dev->in_ep->desc = &bulk_in_desc; + err =usb_ep_enable (dev->in_ep);if (err) {ERROR (dev,"can't start %s: %d\n" , dev->in_ep->name, err); goto fail; } dev->in_ep->driver_data = dev; - err =usb_ep_enable (dev->out_ep, &bulk_out_desc); + dev->out_ep->desc = &bulk_out_desc; + err =usb_ep_enable (dev->out_ep);if (err) {ERROR (dev,"can't start %s: %d\n" , dev->out_ep->name, err); goto fail;
drivers/usb/gadget/inode.c +4 -2
@@ -830,14 +830,16 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)switch (data->dev->gadget->speed) {case USB_SPEED_LOW :case USB_SPEED_FULL : - value =usb_ep_enable (ep, &data->desc); + ep->desc = &data->desc; + value =usb_ep_enable (ep);if (value ==0 ) data->state =STATE_EP_ENABLED ;break ;#ifdef CONFIG_USB_GADGET_DUALSPEED case USB_SPEED_HIGH :/* fails if caller didn't provide that descriptor... */ - value =usb_ep_enable (ep, &data->hs_desc); + ep->desc = &data->hs_desc; + value =usb_ep_enable (ep);if (value ==0 ) data->state =STATE_EP_ENABLED ;break ;
drivers/usb/gadget/printer.c +14 -12
@@ -89,8 +89,7 @@ struct printer_dev {u8 config;s8 interface;struct usb_ep *in_ep, *out_ep; -const struct usb_endpoint_descriptor - *in, *out; +struct list_head rx_reqs;/* List of free RX structs */ struct list_head rx_reqs_active;/* List of Active RX xfers */ struct list_head rx_buffers;/* List of completed xfers */
@@ -895,19 +894,20 @@ set_printer_interface(struct printer_dev *dev) {int result =0 ; - dev->in =ep_desc (dev->gadget, &hs_ep_in_desc, &fs_ep_in_desc); + dev->in_ep->desc =ep_desc (dev->gadget, &hs_ep_in_desc, &fs_ep_in_desc); dev->in_ep->driver_data = dev; - dev->out =ep_desc (dev->gadget, &hs_ep_out_desc, &fs_ep_out_desc); + dev->out_ep->desc =ep_desc (dev->gadget, &hs_ep_out_desc, + &fs_ep_out_desc); dev->out_ep->driver_data = dev; - result =usb_ep_enable (dev->in_ep, dev->in); + result =usb_ep_enable (dev->in_ep);if (result !=0 ) {DBG (dev,"enable %s --> %d\n" , dev->in_ep->name, result); goto done; } - result =usb_ep_enable (dev->out_ep, dev->out); + result =usb_ep_enable (dev->out_ep);if (result !=0 ) {DBG (dev,"enable %s --> %d\n" , dev->in_ep->name, result); goto done;
@@ -918,8 +918,8 @@ done:if (result !=0 ) { (void )usb_ep_disable (dev->in_ep); (void )usb_ep_disable (dev->out_ep); - dev->in =NULL ; - dev->out =NULL ; + dev->in_ep->desc =NULL ; + dev->out_ep->desc =NULL ; }/* caller is responsible for cleanup on error */
@@ -933,12 +933,14 @@ static void printer_reset_interface(struct printer_dev *dev)DBG (dev,"%s\n" , __func__); -if (dev->in) +if (dev->in_ep->desc)usb_ep_disable (dev->in_ep); -if (dev->out) +if (dev->out_ep->desc)usb_ep_disable (dev->out_ep); + dev->in_ep->desc =NULL ; + dev->out_ep->desc =NULL ; dev->interface =-1 ; }
@@ -1104,9 +1106,9 @@ static void printer_soft_reset(struct printer_dev *dev)list_add (&req->list, &dev->tx_reqs); } -if (usb_ep_enable (dev->in_ep, dev->in)) +if (usb_ep_enable (dev->in_ep))DBG (dev,"Failed to enable USB in_ep\n" ); -if (usb_ep_enable (dev->out_ep, dev->out)) +if (usb_ep_enable (dev->out_ep))DBG (dev,"Failed to enable USB out_ep\n" );wake_up_interruptible (&dev->rx_wait);
drivers/usb/gadget/u_ether.c +6 -6
@@ -693,8 +693,8 @@ static int eth_stop(struct net_device *net)usb_ep_disable (link->out_ep);if (netif_carrier_ok (net)) {DBG (dev,"host still using in/out endpoints\n" ); -usb_ep_enable (link->in_ep, link->in); -usb_ep_enable (link->out_ep, link->out); +usb_ep_enable (link->in_ep); +usb_ep_enable (link->out_ep); } }spin_unlock_irqrestore (&dev->lock, flags);
@@ -871,7 +871,7 @@ struct net_device *gether_connect(struct gether *link)return ERR_PTR (-EINVAL ); link->in_ep->driver_data = dev; - result =usb_ep_enable (link->in_ep, link->in); + result =usb_ep_enable (link->in_ep);if (result !=0 ) {DBG (dev,"enable %s --> %d\n" , link->in_ep->name, result);
@@ -879,7 +879,7 @@ struct net_device *gether_connect(struct gether *link) } link->out_ep->driver_data = dev; - result =usb_ep_enable (link->out_ep, link->out); + result =usb_ep_enable (link->out_ep);if (result !=0 ) {DBG (dev,"enable %s --> %d\n" , link->out_ep->name, result);
@@ -969,7 +969,7 @@ void gether_disconnect(struct gether *link) }spin_unlock (&dev->req_lock); link->in_ep->driver_data =NULL ; - link->in =NULL ; + link->in_ep->desc =NULL ;usb_ep_disable (link->out_ep);spin_lock (&dev->req_lock);
@@ -984,7 +984,7 @@ void gether_disconnect(struct gether *link) }spin_unlock (&dev->req_lock); link->out_ep->driver_data =NULL ; - link->out =NULL ; + link->out_ep->desc =NULL ;/* finish forgetting about this USB link episode */ dev->header_len =0 ;
drivers/usb/gadget/u_ether.h +0 -4
@@ -52,10 +52,6 @@ struct gether {struct usb_ep *in_ep;struct usb_ep *out_ep; -/* descriptors match device speed at gether_connect() time */ -struct usb_endpoint_descriptor *in; -struct usb_endpoint_descriptor *out; -bool is_zlp_ok;u16 cdc_filter;
drivers/usb/gadget/u_serial.c +2 -2
@@ -1247,12 +1247,12 @@ int gserial_connect(struct gserial *gser, u8 port_num) port = ports[port_num].port;/* activate the endpoints */ - status =usb_ep_enable (gser->in, gser->in_desc); + status =usb_ep_enable (gser->in);if (status <0 )return status; gser->in->driver_data = port; - status =usb_ep_enable (gser->out, gser->out_desc); + status =usb_ep_enable (gser->out);if (status <0 ) goto fail_out; gser->out->driver_data = port;
drivers/usb/gadget/u_serial.h +0 -2
@@ -35,8 +35,6 @@ struct gserial {struct usb_ep *in;struct usb_ep *out; -struct usb_endpoint_descriptor *in_desc; -struct usb_endpoint_descriptor *out_desc;/* REVISIT avoid this CDC-ACM support harder ... */ struct usb_cdc_line_coding port_line_coding;/* 9600-8-N-1 etc */
include/linux/usb/gadget.h +7 -9
@@ -131,8 +131,9 @@ struct usb_ep_ops {* @maxpacket:The maximum packet size used on this endpoint. The initial * 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. all other fields are -* read-only to gadget drivers. +* @driver_data:for use by the gadget driver. +* @desc: endpoint descriptor. This pointer is set before the 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,
@@ -145,6 +146,7 @@ struct usb_ep {const struct usb_ep_ops *ops;struct list_head ep_list; unsigned maxpacket:16; +const struct usb_endpoint_descriptor *desc; };/*-------------------------------------------------------------------------*/
@@ -153,11 +155,8 @@ struct usb_ep {* usb_ep_enable - configure endpoint, making it usable * @ep:the endpoint being configured. may not be the endpoint named "ep0". * drivers discover endpoints through the ep_list of a usb_gadget. -* @desc:descriptor for desired behavior. caller guarantees this pointer -* remains valid until the endpoint is disabled; the data byte order -* is little-endian (usb-standard). * -* when configurations are set, or when interface settings change, the driver +* When configurations are set, or when interface settings change, the driver * will enable or disable the relevant endpoints. while it is enabled, an * endpoint may be used for i/o until the driver receives a disconnect() from * the host or until the endpoint is disabled.
@@ -172,10 +171,9 @@ struct usb_ep {* * returns zero, or a negative error code. */ -static inline int usb_ep_enable (struct usb_ep *ep, -const struct usb_endpoint_descriptor *desc) +static inline int usb_ep_enable (struct usb_ep *ep) { -return ep->ops->enable (ep, desc); +return ep->ops->enable (ep, ep->desc); }/**
Signature · 9 lines
1.7.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-usb" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v12 2/8 usb: Configure endpoint according to gadget speed.
In reply to Tatyana BrokhmanAdd 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 | 85 +++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/epautoconf.c | 1 + include/linux/usb/composite.h | 3 + include/linux/usb/gadget.h | 3 + 4 files changed, 92 insertions(+), 0 deletions(-)
drivers/usb/gadget/composite.c +85 -0
@@ -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
drivers/usb/gadget/epautoconf.c +1 -0
@@ -191,6 +191,7 @@ ep_matches ( size =64 ; desc->wMaxPacketSize =cpu_to_le16 (size); } + ep->address = desc->bEndpointAddress;return 1 ; }
include/linux/usb/composite.h +3 -0
@@ -145,6 +145,9 @@ int usb_function_activate(struct usb_function *);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
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. +* @address: 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 address;const struct usb_endpoint_descriptor *desc; };
Signature · 5 lines
1.7.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 v12 3/8 usb: Modify existing gadget drivers to use config_ep_by_speed() instead of ep_choose.
In reply to Tatyana BrokhmanRemove 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_mass_storage.c | 34 +++++++++--------------- drivers/usb/gadget/f_ncm.c | 49 ++++++++++------------------------ 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 ---- 16 files changed, 126 insertions(+), 315 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
@@ -59,8 +59,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)
@@ -425,8 +423,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" );
@@ -497,21 +499,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_mass_storage.c +13 -21
@@ -2324,19 +2324,6 @@ static int get_next_command(struct fsg_common *common)/*-------------------------------------------------------------------------*/ -static int enable_endpoint (struct fsg_common *common,struct usb_ep *ep, -const struct usb_endpoint_descriptor *d) -{ -int rc; - - ep->driver_data = common; - ep->desc = (struct usb_endpoint_descriptor *)d; - rc =usb_ep_enable (ep); -if (rc) -ERROR (common,"can't enable %s, result %d\n" , ep->name, rc); -return rc; -} -static int alloc_request (struct fsg_common *common,struct usb_ep *ep,struct usb_request **preq) {
@@ -2350,7 +2337,6 @@ static int alloc_request(struct fsg_common *common, struct usb_ep *ep,/* Reset interface setting and re-init endpoint state (toggle etc). */ static int do_set_interface (struct fsg_common *common,struct fsg_dev *new_fsg) { -const struct usb_endpoint_descriptor *d;struct fsg_dev *fsg;int i, rc =0 ;
@@ -2397,20 +2383,26 @@ reset: fsg = common->fsg;/* Enable the endpoints */ - d =fsg_ep_desc (common->gadget, - &fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc); - rc =enable_endpoint (common, fsg->bulk_in, d); + rc =config_ep_by_speed (common->gadget, &(fsg->function), fsg->bulk_in); +if (rc) + goto reset; + rc =usb_ep_enable (fsg->bulk_in);if (rc) goto reset; + fsg->bulk_in->driver_data = common; fsg->bulk_in_enabled =1 ; - d =fsg_ep_desc (common->gadget, - &fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc); - rc =enable_endpoint (common, fsg->bulk_out, d); + rc =config_ep_by_speed (common->gadget, &(fsg->function), + fsg->bulk_out); +if (rc) + goto reset; + rc =usb_ep_enable (fsg->bulk_out);if (rc) goto reset; + fsg->bulk_out->driver_data = common; fsg->bulk_out_enabled =1 ; - common->bulk_out_maxpacket =le16_to_cpu (d->wMaxPacketSize); + common->bulk_out_maxpacket = +le16_to_cpu (fsg->bulk_out->desc->wMaxPacketSize);clear_bit (IGNORE_BULK_OUT , &fsg->atomic_bitflags);/* Allocate the requests */
drivers/usb/gadget/f_ncm.c +15 -34
87 lines not on this page · raw message
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
@@ -429,12 +429,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
@@ -148,21 +148,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
@@ -871,12 +871,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.7.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 v12 4/8 usb:gadget: Add SuperSpeed support to the Gadget Framework
In reply to Tatyana BrokhmanThis patch adds the SuperSpeed functionality to the gadget framework. 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 | 11 ++ drivers/usb/gadget/composite.c | 253 ++++++++++++++++++++++++++++++++++++--- drivers/usb/gadget/epautoconf.c | 7 +- include/linux/usb/ch9.h | 2 - include/linux/usb/composite.h | 16 +++ include/linux/usb/gadget.h | 34 +++++ 6 files changed, 301 insertions(+), 22 deletions(-)
drivers/usb/gadget/Kconfig +11 -0
@@ -640,6 +640,17 @@ 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 + 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 +236 -17
401 lines not on this page · raw message
drivers/usb/gadget/epautoconf.c +4 -3
@@ -142,13 +142,13 @@ ep_matches ( max =0x7ff &le16_to_cpu (desc->wMaxPacketSize);switch (type) {case USB_ENDPOINT_XFER_INT : -/* INT: limit 64 bytes full speed, 1024 high speed */ +/* INT: limit 64 bytes full speed, 1024 high/super speed */ if (!gadget->is_dualspeed && max >64 )return 0 ;/* FALLTHROUGH */ case USB_ENDPOINT_XFER_ISOC : -/* ISO: limit 1023 bytes full speed, 1024 high speed */ +/* ISO: limit 1023 bytes full speed, 1024 high/super speed */ if (ep->maxpacket < max)return 0 ;if (!gadget->is_dualspeed && max >1023 )
@@ -183,7 +183,8 @@ ep_matches ( }/* report (variable) full speed bulk maxpacket */ -if (USB_ENDPOINT_XFER_BULK == type) { +if ((USB_ENDPOINT_XFER_BULK == type) + && (gadget->speed <USB_SPEED_HIGH )) {int size = ep->maxpacket;/* min() doesn't work on bitfields with gcc-3.5 */
include/linux/usb/ch9.h +0 -2
@@ -142,8 +142,6 @@#define USB_DEVICE_LTM_ENABLE 50/* dev may send LTM */ #define USB_INTRF_FUNC_SUSPEND 0/* function suspend */ -#define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00 -#define USB_ENDPOINT_HALT 0/* IN/OUT will STALL */ /* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
include/linux/usb/composite.h +16 -0
@@ -59,6 +59,12 @@ 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. * @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
@@ -77,6 +83,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
@@ -106,6 +116,7 @@ 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;struct usb_configuration *config;
@@ -132,6 +143,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;
@@ -219,6 +234,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 +34 -0
@@ -131,11 +131,15 @@ struct usb_ep_ops {* @maxpacket:The maximum packet size used on this endpoint. The initial * value can sometimes be reduced (hardware allowing), according to * the endpoint descriptor used to configure the endpoint. +* @mult: multiplier, 'mult' value for SS Isoc EPs +* @maxburst: the maximum number of bursts supported by this EP (for usb3) * @driver_data:for use by the gadget driver. * @address: 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. +* @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,
@@ -148,8 +152,12 @@ struct usb_ep {const struct usb_ep_ops *ops;struct list_head ep_list; unsigned maxpacket:16; + unsigned mult:2; + unsigned pad:1; + unsigned maxburst:4;u8 address;const struct usb_endpoint_descriptor *desc; +const struct usb_ss_ep_comp_descriptor *comp_desc; };/*-------------------------------------------------------------------------*/
@@ -417,6 +425,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 */ +__le16 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 +447,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 +539,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 · 9 lines
1.7.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-usb" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v12 4/8] usb:gadget: Add SuperSpeed support to the Gadget Framework
Quoted 14 lines · * Tatyana Brokhman | 2011-05-23 09:41:13 [+0300]:
drivers/usb/gadget/composite.c +5
-0@@ -1015,6 +1175,62 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) *((u8 *)req->buf) = value; value =min (w_length, (u16 )1 );break ; + +/* +* USB 3.0 additions: +* Function driver should handle get_status request. If such cb +* wasn't supplied we respond with default value = 0
drivers/usb/gadget/composite.c composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) · line 1192
Quoted 10 lines
drivers/usb/gadget/composite.c +10
-0+* Note: function driver should supply such cb only for the first +* interface of the function +*/ +case USB_REQ_GET_STATUS : +if (!gadget_is_superspeed (gadget)) + goto unknown; +if (ctrl->bRequestType != (USB_DIR_IN |USB_RECIP_INTERFACE )) + goto unknown; + value =2 ;/* This is the length of the get_status reply */ + *((__le16 *)req->buf) =0 ;
Mike please correct me if I'm wrong bug this looks like a case for put_unaligned_le16().
Is someone actually using gadget support on blackfin? I'm asking because config_buf() (same file, upstream) is using req->buf to build the descriptors in place and one element is le16 which should be affected.
drivers/usb/gadget/composite.c composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) · line 1201
Quoted 9 lines
drivers/usb/gadget/composite.c +9
-0+if (!cdev->config || intf >=MAX_CONFIG_INTERFACES ) +break ; + f = cdev->config->interface[intf]; +if (!f) +break ; + status = f->get_status ? f->get_status (f) :0 ; +if (status <0 ) +break ; + *((__le16 *)req->buf) =cpu_to_le16 (status &0x0000ffff );
and here.
drivers/usb/gadget/composite.c composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) · line 1202
Quoted 1 line
drivers/usb/gadget/composite.c +1
-0+break ;
Sebastian
Re: [PATCH v12 4/8] usb:gadget: Add SuperSpeed support to the Gadget Framework
Quoted 23 lines · Sebastian Andrzej Siewior
Quoted 22 lines · * Tatyana Brokhman | 2011-05-23 09:41:13 [+0300]:
drivers/usb/gadget/composite.c +13
-0@@ -1015,6 +1175,62 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) *((u8 *)req->buf) = value; value = min(w_length, (u16) 1); break; + + /* + * USB 3.0 additions: + * Function driver should handle get_status request. If such cb + * wasn't supplied we respond with default value = 0 + * Note: function driver should supply such cb only for the first + * interface of the function + */ + case USB_REQ_GET_STATUS: + if (!gadget_is_superspeed(gadget)) + goto unknown; + if (ctrl->bRequestType != (USB_DIR_IN | USB_RECIP_INTERFACE)) + goto unknown;
Quoted 8 lines
drivers/usb/gadget/composite.c composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) · line 1192
Quoted 2 lines
drivers/usb/gadget/composite.c +2
-0+ value = 2; /* This is the length of the get_status reply */ + *((__le16 *)req->buf) = 0;Mike please correct me if I'm wrong bug this looks like a case for
put_unaligned_le16().
Is someone actually using gadget support on blackfin? I'm asking becauseconfig_buf()(same file, upstream) is usingreq->bufto build the descriptors in place and one element is le16 which should be affected.
yes, we do gadget stuff heavily on Blackfin with a few different controllers. if things broke, we'd be unhappy ;). -mike
RE: [PATCH v12 4/8] usb:gadget: Add SuperSpeed support to the Gadget Framework
In reply to Sebastian Andrzej SiewiorHi Sebastian,
Quoted 7 lines
drivers/usb/gadget/composite.c composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
Quoted 4 lines
drivers/usb/gadget/composite.c +4
-0+case USB_REQ_GET_STATUS : +if (!gadget_is_superspeed (gadget)) + goto unknown; + if (ctrl->bRequestType != (USB_DIR_IN |
USB_RECIP_INTERFACE))Review
Quoted 2 lines
(quoted diff) +2
-0+ goto unknown; + value = 2; /* This is the length of the get_status
reply
Quoted 10 lines
*/
drivers/usb/gadget/composite.c composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) · line 1192
Quoted 1 line
drivers/usb/gadget/composite.c +1
-0+ *((__le16 *)req->buf) =0 ;Mike please correct me if I'm wrong bug this looks like a case for
put_unaligned_le16().
Is someone actually using gadget support on blackfin? I'm asking becauseconfig_buf()(same file, upstream) is usingreq->bufto build the descriptors in place and one element is le16 which should be affected.
Mike answered that you're right in your observation. I'm not familiar with blackfin. Could you please elaborate on this? I understand that I need to use put_unaligned_le16(), will do, but I would like to better understand why and if there is a way to test this so that blackfin won't be broken.
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Re: [PATCH v12 4/8] usb:gadget: Add SuperSpeed support to the Gadget Framework
Quoted 15 lines · Tanya Brokhman
Quoted 8 lines
Quoted 7 lines
+ case
USB_REQ_GET_STATUS:
+ if (!gadget_is_superspeed(gadget))
+ goto unknown;
+ if (ctrl->bRequestType!= (USB_DIR_IN|USB_RECIP_INTERFACE))
+ goto unknown;
+ value = 2; /* This is the length of theget_status
+ *((__le16 *)req->buf) = 0;Quoted 6 lines
Mike please correct me if I'm wrong bug this looks like a case for
put_unaligned_le16().
Is someone actually using gadget support on blackfin? I'm asking becauseconfig_buf()(same file, upstream) is usingreq->bufto build the descriptors in place and one element is le16 which should be affected.
Quoted 4 lines
Mike answered that you're right in your observation. I'm not familiar with blackfin. Could you please elaborate on this? I understand that I need to use
put_unaligned_le16(), will do, but I would like to better understand why and if there is a way to test this so that blackfin won't be broken.
not all arches support unaligned accesses. or they do, but it's done via (non-trivial) exception processing in software. req->buf is of type void* and so presumably is not guaranteed to be aligned on a 2 byte boundary.
-mike
RE: [PATCH v12 4/8] usb:gadget: Add SuperSpeed support to the Gadget Framework
Quoted 6 lines
Quoted 2 lines
Mike answered that you're right in your observation. I'm not familiar
with
Quoted 1 line
blackfin. Could you please elaborate on this? I understand that I
need to
Quoted 1 line
use
put_unaligned_le16(), will do, but I would like to better
Quoted 8 lines
understand why
Quoted 1 line
and if there is a way to test this so that blackfin won't be broken.
not all arches support unaligned accesses. or they do, but it's done via (non-trivial) exception processing in software.
req->bufis of type void* and so presumably is not guaranteed to be aligned on a 2 byte boundary.
-mike
Thanks for the explanation, Mike! I'll update the patch.
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Re: [PATCH v12 4/8] usb:gadget: Add SuperSpeed support to the Gadget Framework
Quoted 6 lines · Tanya Brokhman
Quoted 6 lines
Quoted 5 lines
Mike answered that you're right in your observation. I'm not familiar with blackfin. Could you please elaborate on this? I understand that I need to use
put_unaligned_le16(), will do, but I would like to better understand why and if there is a way to test this so that blackfin won't be broken.
Quoted 6 lines
Quoted 4 lines
not all arches support unaligned accesses. or they do, but it's done via (non-trivial) exception processing in software. req->buf is of type void* and so presumably is not guaranteed to be aligned on a 2 byte boundary.
Thanks for the explanation, Mike! I'll update the patch.
also, for arches where unaligned accesses work (like x86), the unaligned macros will simply expand to direct accesses like the code you had originally.
-mike
PATCH v12 5/8 usb: Add streams support to the gadget framework
In reply to Tatyana BrokhmanThis patch defines necessary fields to support streaming for USB3.0. It implements a new function (usb_ep_autoconfig_ss) to be used instead of the existing usb_ep_autoconfig when working in SS mode and there is a need to search for an endpoint according to the number of required streams.
--- drivers/usb/gadget/epautoconf.c | 125 +++++++++++++++++++++++++++++++-------- include/linux/usb/gadget.h | 10 +++ 2 files changed, 110 insertions(+), 25 deletions(-)
drivers/usb/gadget/epautoconf.c +100 -25
@@ -63,13 +63,16 @@ static intep_matches ( struct usb_gadget *gadget, struct usb_ep *ep, - struct usb_endpoint_descriptor *desc + 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 ;
@@ -129,6 +132,22 @@ ep_matches ( }/* +* 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) { + num_req_streams = ep_comp->bmAttributes &0x1f ; +if (num_req_streams > ep->max_streams) +return 0 ; +/* Update the ep_comp descriptor if needed */ +if (num_req_streams != ep->max_streams) + ep_comp->bmAttributes = ep->max_streams; + } + + } + +/* * If the protocol driver hasn't yet decided on wMaxPacketSize * and wants to know the maximum possible, provide the info. */
@@ -209,38 +228,53 @@ find_ep (struct usb_gadget *gadget, const char *name) }/** -* usb_ep_autoconfig - choose an endpoint matching the descriptor +* usb_ep_autoconfig_ss() - choose an endpoint matching the ep +* descriptor and ep companion descriptor * @gadget: The device to which the endpoint must belong. * @desc: Endpoint descriptor, with endpoint direction and transfer mode -* initialized. For periodic transfers, the maximum packet -* size must also be initialized. This is modified on success. +* initialized. For periodic transfers, the maximum packet +* size must also be initialized. This is modified on +* success. +* @ep_comp: Endpoint companion descriptor, with the required +* number of streams. Will be modified when the chosen EP +* supports a different number of streams. * -* By choosing an endpoint to use with the specified descriptor, this -* routine simplifies writing gadget drivers that work with multiple -* USB device controllers. The endpoint would be passed later to -* usb_ep_enable(), along with some descriptor. +* This routine replaces the usb_ep_autoconfig when needed +* superspeed enhancments. If such enhancemnets are required, +* the FD should call usb_ep_autoconfig_ss directly and provide +* the additional ep_comp parameter. +* +* By choosing an endpoint to use with the specified descriptor, +* this routine simplifies writing gadget drivers that work with +* multiple USB device controllers. The endpoint would be +* passed later to usb_ep_enable(), along with some descriptor. * * That second descriptor won't always be the same as the first one. * For example, isochronous endpoints can be autoconfigured for high * bandwidth, and then used in several lower bandwidth altsettings. * Also, high and full speed descriptors will be different. * -* Be sure to examine and test the results of autoconfiguration on your -* hardware. This code may not make the best choices about how to use the -* USB controller, and it can't know all the restrictions that may apply. -* Some combinations of driver and hardware won't be able to autoconfigure. +* Be sure to examine and test the results of autoconfiguration +* on your hardware. This code may not make the best choices +* about how to use the USB controller, and it can't know all +* the restrictions that may apply. Some combinations of driver +* and hardware won't be able to autoconfigure. * * On success, this returns an un-claimed usb_ep, and modifies the endpoint * 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. +* is initialized as if the endpoint were used at full speed and +* the bmAttribute field in the ep companion descriptor is +* 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. * * On failure, this returns a null endpoint descriptor. */ -struct usb_ep *usb_ep_autoconfig ( +struct usb_ep *usb_ep_autoconfig_ss (struct usb_gadget *gadget, -struct usb_endpoint_descriptor *desc +struct usb_endpoint_descriptor *desc, +struct usb_ss_ep_comp_descriptor *ep_comp ) {struct usb_ep *ep;
@@ -254,23 +288,24 @@ struct usb_ep *usb_ep_autoconfig (if (gadget_is_net2280 (gadget) && 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)) +if (ep &&ep_matches (gadget, ep, desc, ep_comp))return ep; ep =find_ep (gadget,"ep-f" ); -if (ep &&ep_matches (gadget, ep, desc)) +if (ep &&ep_matches (gadget, ep, desc, ep_comp))return 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 =find_ep (gadget,"ep3-bulk" ); +if (ep &&ep_matches (gadget, ep, desc, ep_comp))return 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 =find_ep (gadget,"ep2-bulk" ); +if (ep &&ep_matches (gadget, ep, desc, + ep_comp))return ep; }
@@ -289,14 +324,14 @@ struct usb_ep *usb_ep_autoconfig ( ep = find_ep(gadget, "ep2out"); }else ep =NULL ; -if (ep &&ep_matches (gadget, ep, desc)) +if (ep &&ep_matches (gadget, ep, desc, ep_comp))return 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)) +if (ep_matches (gadget, ep, desc, ep_comp))return ep; }
@@ -305,6 +340,46 @@ struct usb_ep *usb_ep_autoconfig ( }/** +* usb_ep_autoconfig() - choose an endpoint matching the +* descriptor +* @gadget: The device to which the endpoint must belong. +* @desc: Endpoint descriptor, with endpoint direction and transfer mode +* initialized. For periodic transfers, the maximum packet +* size must also be initialized. This is modified on success. +* +* By choosing an endpoint to use with the specified descriptor, this +* routine simplifies writing gadget drivers that work with multiple +* USB device controllers. The endpoint would be passed later to +* usb_ep_enable(), along with some descriptor. +* +* That second descriptor won't always be the same as the first one. +* For example, isochronous endpoints can be autoconfigured for high +* bandwidth, and then used in several lower bandwidth altsettings. +* Also, high and full speed descriptors will be different. +* +* Be sure to examine and test the results of autoconfiguration on your +* hardware. This code may not make the best choices about how to use the +* USB controller, and it can't know all the restrictions that may apply. +* Some combinations of driver and hardware won't be able to autoconfigure. +* +* On success, this returns an un-claimed usb_ep, and modifies the endpoint +* 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. +* +* On failure, this returns a null endpoint descriptor. +*/ +struct usb_ep *usb_ep_autoconfig ( +struct usb_gadget *gadget, +struct usb_endpoint_descriptor *desc +) +{ +return usb_ep_autoconfig_ss (gadget, desc,NULL ); +} + + +/** * usb_ep_autoconfig_reset - reset endpoint autoconfig state * @gadget: device for which autoconfig state will be reset *
include/linux/usb/gadget.h +10 -0
@@ -27,6 +27,7 @@ struct usb_ep;* field, and the usb controller needs one, it is responsible * for mapping and unmapping the buffer. * @length: Length of that data +* @stream_id: The stream id, when USB3.0 bulk streams are being used * @no_interrupt: If true, hints that no completion irq is needed. * Helpful sometimes with deep request queues that are handled * directly by DMA controllers.
@@ -81,6 +82,7 @@ struct usb_request {unsigned length;dma_addr_t dma; + unsigned stream_id:16; unsigned no_interrupt:1; unsigned zero:1; unsigned short_not_ok:1;
@@ -131,6 +133,8 @@ struct usb_ep_ops {* @maxpacket:The maximum packet size used on this endpoint. The initial * value can sometimes be reduced (hardware allowing), according to * the endpoint descriptor used to configure the endpoint. +* @max_streams: The maximum number of streams supported +* by this EP (0 - 16, actual number is 2^n) * @mult: multiplier, 'mult' value for SS Isoc EPs * @maxburst: the maximum number of bursts supported by this EP (for usb3) * @driver_data:for use by the gadget driver.
@@ -152,6 +156,7 @@ struct usb_ep {const struct usb_ep_ops *ops;struct list_head ep_list; unsigned maxpacket:16; + unsigned max_streams:16; unsigned mult:2; unsigned pad:1; unsigned maxburst:4;
@@ -921,6 +926,11 @@ static inline void usb_free_descriptors(struct usb_descriptor_header **v)extern struct usb_ep *usb_ep_autoconfig (struct usb_gadget *,struct usb_endpoint_descriptor *); + +extern struct usb_ep *usb_ep_autoconfig_ss (struct usb_gadget *, +struct usb_endpoint_descriptor *, +struct usb_ss_ep_comp_descriptor *); +extern void usb_ep_autoconfig_reset (struct usb_gadget *);#endif /* __LINUX_USB_GADGET_H */
Signature · 5 lines
1.7.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 v12 6/8 usb:dummy_hcd: use the shared_hcd infrastructure
In reply to Tatyana BrokhmanThis patch is a preparation for adding SuperSpeed support to dummy hcd. It takes the master side fields out of the struct dummy to a separate structure. The init process was also modified to resemble the way it is done by xHCI.
--- drivers/usb/gadget/dummy_hcd.c | 501 +++++++++++++++++++++------------------- 1 files changed, 266 insertions(+), 235 deletions(-)
drivers/usb/gadget/dummy_hcd.c +266 -235
@@ -152,6 +152,22 @@ enum dummy_rh_state {DUMMY_RH_RUNNING }; +struct dummy_hcd { +struct dummy *dum; +enum dummy_rh_state rh_state; +struct timer_list timer; +u32 port_status; +u32 old_status; +unsigned long re_timeout; + +struct usb_device *udev; +struct list_head urbp_list; + +unsigned active:1 ; +unsigned old_active:1 ; +unsigned resuming:1 ; +}; +struct dummy {spinlock_t lock;
@@ -167,36 +183,26 @@ struct dummy {u16 devstatus; unsigned udc_suspended:1; unsigned pullup:1; - unsigned active:1; - unsigned old_active:1;/* * MASTER/HOST side support */ -enum dummy_rh_state rh_state; -struct timer_list timer; -u32 port_status; -u32 old_status; - unsigned resuming:1; -unsigned long re_timeout; - -struct usb_device *udev; -struct list_head urbp_list; +struct dummy_hcd *hs_hcd; }; -static inline struct dummy *hcd_to_dummy (struct usb_hcd *hcd) +static inline struct dummy_hcd *hcd_to_dummy_hcd (struct usb_hcd *hcd) { -return (struct dummy *) (hcd->hcd_priv); +return (struct dummy_hcd *) (hcd->hcd_priv); } -static inline struct usb_hcd *dummy_to_hcd (struct dummy *dum) +static inline struct usb_hcd *dummy_hcd_to_hcd (struct dummy_hcd *dum) { return container_of((void *) dum, struct usb_hcd, hcd_priv); } -static inline struct device *dummy_dev (struct dummy *dum) +static inline struct device *dummy_dev (struct dummy_hcd *dum) { -return dummy_to_hcd (dum)->self.controller; +return dummy_hcd_to_hcd (dum)->self.controller; }static inline struct device *udc_dev (struct dummy *dum)
@@ -209,9 +215,10 @@ static inline struct dummy *ep_to_dummy (struct dummy_ep *ep) return container_of (ep->gadget, struct dummy, gadget); } -static inline struct dummy *gadget_to_dummy (struct usb_gadget *gadget) +static inline struct dummy_hcd *gadget_to_dummy_hcd (struct usb_gadget *gadget) { - return container_of (gadget, struct dummy, gadget); + struct dummy *dum = container_of(gadget, struct dummy, gadget); +return dum->hs_hcd; }static inline struct dummy *gadget_dev_to_dummy (struct device *dev)
@@ -219,7 +226,7 @@ static inline struct dummy *gadget_dev_to_dummy (struct device *dev) return container_of (dev, struct dummy, gadget.dev); } -static struct dummy *the_controller; +static struct dummy the_controller;/*-------------------------------------------------------------------------*/
@@ -260,60 +267,64 @@ stop_activity (struct dummy *dum) }/* caller must hold lock */ -static void -set_link_state (struct dummy *dum) +static void set_link_state (struct dummy_hcd *dum_hcd) { - dum->active =0 ; -if ((dum->port_status &USB_PORT_STAT_POWER ) ==0 ) - dum->port_status =0 ; +struct dummy *dum = dum_hcd->dum; + + dum_hcd->active =0 ; +if ((dum_hcd->port_status &USB_PORT_STAT_POWER ) ==0 ) + dum_hcd->port_status =0 ;/* UDC suspend must cause a disconnect */ else if (!dum->pullup || dum->udc_suspended) { - dum->port_status &= ~(USB_PORT_STAT_CONNECTION | + dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION |USB_PORT_STAT_ENABLE |USB_PORT_STAT_LOW_SPEED |USB_PORT_STAT_HIGH_SPEED |USB_PORT_STAT_SUSPEND ); -if ((dum->old_status &USB_PORT_STAT_CONNECTION ) !=0 ) - dum->port_status |= (USB_PORT_STAT_C_CONNECTION <<16 ); +if ((dum_hcd->old_status &USB_PORT_STAT_CONNECTION ) !=0 ) + dum_hcd->port_status |= + (USB_PORT_STAT_C_CONNECTION <<16 ); }else { - dum->port_status |=USB_PORT_STAT_CONNECTION ; -if ((dum->old_status &USB_PORT_STAT_CONNECTION ) ==0 ) - dum->port_status |= (USB_PORT_STAT_C_CONNECTION <<16 ); -if ((dum->port_status &USB_PORT_STAT_ENABLE ) ==0 ) - dum->port_status &= ~USB_PORT_STAT_SUSPEND ; -else if ((dum->port_status &USB_PORT_STAT_SUSPEND ) ==0 && - dum->rh_state !=DUMMY_RH_SUSPENDED ) - dum->active =1 ; + dum_hcd->port_status |=USB_PORT_STAT_CONNECTION ; +if ((dum_hcd->old_status &USB_PORT_STAT_CONNECTION ) ==0 ) + dum_hcd->port_status |= + (USB_PORT_STAT_C_CONNECTION <<16 ); +if ((dum_hcd->port_status &USB_PORT_STAT_ENABLE ) ==0 ) + dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND ; +else if ((dum_hcd->port_status &USB_PORT_STAT_SUSPEND ) ==0 && + dum_hcd->rh_state !=DUMMY_RH_SUSPENDED ) + dum_hcd->active =1 ; } -if ((dum->port_status &USB_PORT_STAT_ENABLE ) ==0 || dum->active) - dum->resuming =0 ; +if ((dum_hcd->port_status &USB_PORT_STAT_ENABLE ) ==0 || + dum_hcd->active) + dum_hcd->resuming =0 ; -if ((dum->port_status &USB_PORT_STAT_CONNECTION ) ==0 || - (dum->port_status &USB_PORT_STAT_RESET ) !=0 ) { -if ((dum->old_status &USB_PORT_STAT_CONNECTION ) !=0 && - (dum->old_status &USB_PORT_STAT_RESET ) ==0 && +if ((dum_hcd->port_status &USB_PORT_STAT_CONNECTION ) ==0 || + (dum_hcd->port_status &USB_PORT_STAT_RESET ) !=0 ) { +if ((dum_hcd->old_status &USB_PORT_STAT_CONNECTION ) !=0 && + (dum_hcd->old_status &USB_PORT_STAT_RESET ) ==0 && dum->driver) {stop_activity (dum);spin_unlock (&dum->lock); dum->driver->disconnect (&dum->gadget);spin_lock (&dum->lock); } - }else if (dum->active != dum->old_active) { -if (dum->old_active && dum->driver->suspend) { + }else if (dum_hcd->active != dum_hcd->old_active) { +if (dum_hcd->old_active && dum->driver->suspend) {spin_unlock (&dum->lock); dum->driver->suspend (&dum->gadget);spin_lock (&dum->lock); - }else if (!dum->old_active && dum->driver->resume) { + }else if (!dum_hcd->old_active && dum->driver->resume) {spin_unlock (&dum->lock); dum->driver->resume (&dum->gadget);spin_lock (&dum->lock); } } - dum->old_status = dum->port_status; - dum->old_active = dum->active; + dum_hcd->old_status = dum_hcd->port_status; + dum_hcd->old_active = dum_hcd->active; }/*-------------------------------------------------------------------------*/
@@ -332,6 +343,7 @@ static int dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) { struct dummy *dum; +struct dummy_hcd *dum_hcd;struct dummy_ep *ep;unsigned max;int retval;
@@ -341,9 +353,17 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) || desc->bDescriptorType != USB_DT_ENDPOINT)return -EINVAL ; dum =ep_to_dummy (ep); -if (!dum->driver || !is_enabled (dum)) +if (!dum->driver) +return -ESHUTDOWN ; + dum_hcd = dum->hs_hcd; +if (!is_enabled (dum_hcd))return -ESHUTDOWN ; - max =le16_to_cpu (desc->wMaxPacketSize) &0x3ff ; + +/* +* For HS/FS devices only bits 0..10 of the wMaxPacketSize represent the +* maximum packet size. +*/ + max =le16_to_cpu (desc->wMaxPacketSize) &0x7ff ;/* drivers must not request bad settings, since lower levels * (hardware or its drivers) may not check. some endpoints
@@ -507,6 +527,7 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,struct dummy_ep *ep;struct dummy_request *req;struct dummy *dum; +struct dummy_hcd *dum_hcd;unsigned long flags; req =usb_request_to_dummy_request (_req);
@@ -518,7 +539,8 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,return -EINVAL ; dum =ep_to_dummy (ep); -if (!dum->driver || !is_enabled (dum)) + dum_hcd = dum->hs_hcd; +if (!dum->driver || !is_enabled (dum_hcd))return -ESHUTDOWN ;#if 0
@@ -662,24 +684,24 @@ static int dummy_g_get_frame (struct usb_gadget *_gadget)static int dummy_wakeup (struct usb_gadget *_gadget) { -struct dummy *dum; +struct dummy_hcd *dum_hcd; - dum =gadget_to_dummy (_gadget); -if (!(dum->devstatus & ( (1 <<USB_DEVICE_B_HNP_ENABLE ) + dum_hcd =gadget_to_dummy_hcd (_gadget); +if (!(dum_hcd->dum->devstatus & ((1 <<USB_DEVICE_B_HNP_ENABLE ) | (1 <<USB_DEVICE_REMOTE_WAKEUP ))))return -EINVAL ; -if ((dum->port_status &USB_PORT_STAT_CONNECTION ) ==0 ) +if ((dum_hcd->port_status &USB_PORT_STAT_CONNECTION ) ==0 )return -ENOLINK ; -if ((dum->port_status &USB_PORT_STAT_SUSPEND ) ==0 && - dum->rh_state !=DUMMY_RH_SUSPENDED ) +if ((dum_hcd->port_status &USB_PORT_STAT_SUSPEND ) ==0 && + dum_hcd->rh_state !=DUMMY_RH_SUSPENDED )return -EIO ;/* FIXME: What if the root hub is suspended but the port isn't? */ /* hub notices our request, issues downstream resume, etc */ - dum->resuming =1 ; - dum->re_timeout = jiffies +msecs_to_jiffies (20 ); -mod_timer (&dummy_to_hcd (dum)->rh_timer, dum->re_timeout); + dum_hcd->resuming =1 ; + dum_hcd->re_timeout = jiffies +msecs_to_jiffies (20 ); +mod_timer (&dummy_hcd_to_hcd (dum_hcd)->rh_timer, dum_hcd->re_timeout);return 0 ; }
@@ -687,7 +709,7 @@ static int dummy_set_selfpowered (struct usb_gadget *_gadget, int value) {struct dummy *dum; - dum =gadget_to_dummy (_gadget); + dum = (gadget_to_dummy_hcd (_gadget))->dum;if (value) dum->devstatus |= (1 <<USB_DEVICE_SELF_POWERED );else
@@ -700,13 +722,12 @@ static int dummy_pullup (struct usb_gadget *_gadget, int value)struct dummy *dum;unsigned long flags; - dum =gadget_to_dummy (_gadget); + dum =gadget_to_dummy_hcd (_gadget)->dum;spin_lock_irqsave (&dum->lock, flags); dum->pullup = (value !=0 ); -set_link_state (dum); +set_link_state (dum->hs_hcd);spin_unlock_irqrestore (&dum->lock, flags); - -usb_hcd_poll_rh_status (dummy_to_hcd (dum)); +usb_hcd_poll_rh_status (dummy_hcd_to_hcd (dum->hs_hcd));return 0 ; }
@@ -751,7 +772,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *)) { - struct dummy *dum = the_controller; + struct dummy *dum = &the_controller;int retval, i;if (!dum)
@@ -787,7 +808,8 @@ usb_gadget_probe_driver(struct usb_gadget_driver *driver, } dum->gadget.ep0 = &dum->ep [0 ].ep; - dum->ep [0 ].ep.maxpacket =64 ; + dum->gadget.speed =min ((u8 )driver->speed, (u8 )USB_SPEED_HIGH ) ; + dum->ep[0 ].ep.maxpacket =64 ;list_del_init (&dum->ep [0 ].ep.ep_list);INIT_LIST_HEAD (&dum->fifo_req.queue);
@@ -806,10 +828,12 @@ usb_gadget_probe_driver(struct usb_gadget_driver *driver,/* khubd will enumerate this in a while */ spin_lock_irq (&dum->lock); dum->pullup =1 ; -set_link_state (dum); + dum->gadget.is_otg = + (dummy_hcd_to_hcd (dum->hs_hcd)->self.otg_port !=0 ); +set_link_state (dum->hs_hcd);spin_unlock_irq (&dum->lock); -usb_hcd_poll_rh_status (dummy_to_hcd (dum)); +usb_hcd_poll_rh_status (dummy_hcd_to_hcd (dum->hs_hcd));return 0 ; }EXPORT_SYMBOL (usb_gadget_probe_driver);
@@ -817,7 +841,7 @@ EXPORT_SYMBOL(usb_gadget_probe_driver);int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) { -struct dummy *dum = the_controller; +struct dummy *dum = &the_controller;unsigned long flags;if (!dum)
@@ -830,7 +854,7 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)spin_lock_irqsave (&dum->lock, flags); dum->pullup =0 ; -set_link_state (dum); +set_link_state (dum->hs_hcd);spin_unlock_irqrestore (&dum->lock, flags); driver->unbind (&dum->gadget);
@@ -839,10 +863,9 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)spin_lock_irqsave (&dum->lock, flags); dum->pullup =0 ; -set_link_state (dum); +set_link_state (dum->hs_hcd);spin_unlock_irqrestore (&dum->lock, flags); - -usb_hcd_poll_rh_status (dummy_to_hcd (dum)); +usb_hcd_poll_rh_status (dummy_hcd_to_hcd (dum->hs_hcd));return 0 ; }EXPORT_SYMBOL (usb_gadget_unregister_driver);
@@ -864,25 +887,18 @@ EXPORT_SYMBOL (net2280_set_fifo_mode);static void dummy_gadget_release (struct device *dev) { -struct dummy *dum =gadget_dev_to_dummy (dev); - -usb_put_hcd (dummy_to_hcd (dum)); +return ; }static int dummy_udc_probe (struct platform_device *pdev) { -struct dummy *dum = the_controller; +struct dummy *dum = &the_controller;int rc; -usb_get_hcd (dummy_to_hcd (dum)); - dum->gadget.name = gadget_name; dum->gadget.ops = &dummy_ops; dum->gadget.is_dualspeed =1 ; -/* maybe claim OTG support, though we won't complete HNP */ - dum->gadget.is_otg = (dummy_to_hcd (dum)->self.otg_port !=0 ); -dev_set_name (&dum->gadget.dev,"gadget" ); dum->gadget.dev.parent = &pdev->dev; dum->gadget.dev.release = dummy_gadget_release;
@@ -917,10 +933,10 @@ static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)dev_dbg (&pdev->dev,"%s\n" , __func__);spin_lock_irq (&dum->lock); dum->udc_suspended =1 ; -set_link_state (dum); +set_link_state (dum->hs_hcd);spin_unlock_irq (&dum->lock); -usb_hcd_poll_rh_status (dummy_to_hcd (dum)); +usb_hcd_poll_rh_status (dummy_hcd_to_hcd (dum->hs_hcd));return 0 ; }
@@ -931,10 +947,10 @@ static int dummy_udc_resume (struct platform_device *pdev)dev_dbg (&pdev->dev,"%s\n" , __func__);spin_lock_irq (&dum->lock); dum->udc_suspended =0 ; -set_link_state (dum); +set_link_state (dum->hs_hcd);spin_unlock_irq (&dum->lock); -usb_hcd_poll_rh_status (dummy_to_hcd (dum)); +usb_hcd_poll_rh_status (dummy_hcd_to_hcd (dum->hs_hcd));return 0 ; }
@@ -968,7 +984,7 @@ static int dummy_urb_enqueue ( struct urb *urb, gfp_t mem_flags ) { -struct dummy *dum; +struct dummy_hcd *dum_hcd;struct urbp *urbp;unsigned long flags;int rc;
@@ -981,51 +997,51 @@ static int dummy_urb_enqueue (return -ENOMEM ; urbp->urb = urb; - dum =hcd_to_dummy (hcd); -spin_lock_irqsave (&dum->lock, flags); + dum_hcd =hcd_to_dummy_hcd (hcd); +spin_lock_irqsave (&dum_hcd->dum->lock, flags); rc =usb_hcd_link_urb_to_ep (hcd, urb);if (rc) {kfree (urbp); goto done; } -if (!dum->udev) { - dum->udev = urb->dev; -usb_get_dev (dum->udev); - }else if (unlikely (dum->udev != urb->dev)) -dev_err (dummy_dev (dum),"usb_device address has changed!\n" ); +if (!dum_hcd->udev) { + dum_hcd->udev = urb->dev; +usb_get_dev (dum_hcd->udev); + }else if (unlikely (dum_hcd->udev != urb->dev)) +dev_err (dummy_dev (dum_hcd),"usb_device address has changed!\n" ); -list_add_tail (&urbp->urbp_list, &dum->urbp_list); +list_add_tail (&urbp->urbp_list, &dum_hcd->urbp_list); urb->hcpriv = urbp;if (usb_pipetype (urb->pipe) ==PIPE_CONTROL ) urb->error_count =1 ;/* mark as a new urb */ /* kick the scheduler, it'll do the rest */ -if (!timer_pending (&dum->timer)) -mod_timer (&dum->timer, jiffies +1 ); +if (!timer_pending (&dum_hcd->timer)) +mod_timer (&dum_hcd->timer, jiffies +1 ); done: -spin_unlock_irqrestore (&dum->lock, flags); +spin_unlock_irqrestore (&dum_hcd->dum->lock, flags);return rc; }static int dummy_urb_dequeue (struct usb_hcd *hcd,struct urb *urb,int status) { -struct dummy *dum; +struct dummy_hcd *dum_hcd;unsigned long flags;int rc;/* giveback happens automatically in timer callback, * so make sure the callback happens */ - dum =hcd_to_dummy (hcd); -spin_lock_irqsave (&dum->lock, flags); + dum_hcd =hcd_to_dummy_hcd (hcd); +spin_lock_irqsave (&dum_hcd->dum->lock, flags); rc =usb_hcd_check_unlink_urb (hcd, urb, status); -if (!rc && dum->rh_state !=DUMMY_RH_RUNNING && - !list_empty (&dum->urbp_list)) -mod_timer (&dum->timer, jiffies); +if (!rc && dum_hcd->rh_state !=DUMMY_RH_RUNNING && + !list_empty (&dum_hcd->urbp_list)) +mod_timer (&dum_hcd->timer, jiffies); -spin_unlock_irqrestore (&dum->lock, flags); +spin_unlock_irqrestore (&dum_hcd->dum->lock, flags);return rc; }
@@ -1165,7 +1181,7 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)return limit; } -#define is_active (dum) ((dum->port_status & \ +#define is_active (dum_hcd) ((dum_hcd->port_status & \ (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | \ USB_PORT_STAT_SUSPEND)) \ == (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE))
@@ -1174,7 +1190,7 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address) {int i; -if (!is_active (dum)) +if (!is_active (dum->hs_hcd))return NULL ;if ((address & ~USB_DIR_IN ) ==0 )return &dum->ep [0 ];
@@ -1211,11 +1227,12 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)* 1 - if the request wasn't handles * error code on error */ -static int handle_control_request (struct dummy *dum,struct urb *urb, +static int handle_control_request (struct dummy_hcd *dum_hcd,struct urb *urb,struct usb_ctrlrequest *setup,int *status) {struct dummy_ep *ep2; +struct dummy *dum = dum_hcd->dum;int ret_val =1 ;unsigned w_index;unsigned w_value;
@@ -1334,9 +1351,10 @@ static int handle_control_request(struct dummy *dum, struct urb *urb,/* drive both sides of the transfers; looks like irq handlers to * both drivers except the callbacks aren't in_irq(). */ -static void dummy_timer (unsigned long _dum) +static void dummy_timer (unsigned long _dum_hcd) { -struct dummy *dum = (struct dummy *) _dum; +struct dummy_hcd *dum_hcd = (struct dummy_hcd *) _dum_hcd; +struct dummy *dum = dum_hcd->dum;struct urbp *urbp, *tmp;unsigned long flags;int limit, total;
@@ -1354,7 +1372,7 @@ static void dummy_timer (unsigned long _dum) total =512 /*bytes*/ *13 /*packets*/ *8 /*uframes*/ ;break ;default : -dev_err (dummy_dev (dum),"bogus device speed\n" ); +dev_err (dummy_dev (dum_hcd),"bogus device speed\n" );return ; }
@@ -1363,8 +1381,8 @@ static void dummy_timer (unsigned long _dum)/* look at each urb queued by the host side driver */ spin_lock_irqsave (&dum->lock, flags); -if (!dum->udev) { -dev_err (dummy_dev (dum), +if (!dum_hcd->udev) { +dev_err (dummy_dev (dum_hcd),"timer fired with no URBs pending?\n" );spin_unlock_irqrestore (&dum->lock, flags);return ;
@@ -1377,7 +1395,7 @@ static void dummy_timer (unsigned long _dum) } restart: - list_for_each_entry_safe (urbp, tmp, &dum->urbp_list, urbp_list) { +list_for_each_entry_safe (urbp, tmp, &dum_hcd->urbp_list, urbp_list) {struct urb *urb;struct dummy_request *req;u8 address;
@@ -1388,7 +1406,7 @@ restart: urb = urbp->urb;if (urb->unlinked) goto return_urb; -else if (dum->rh_state !=DUMMY_RH_RUNNING ) +else if (dum_hcd->rh_state !=DUMMY_RH_RUNNING )continue ; type =usb_pipetype (urb->pipe);
@@ -1406,7 +1424,7 @@ restart: ep =find_endpoint (dum, address);if (!ep) {/* set_configuration() disagreement */ -dev_dbg (dummy_dev (dum), +dev_dbg (dummy_dev (dum_hcd),"no ep configured for urb %p\n" , urb); status = -EPROTO ;
@@ -1422,7 +1440,7 @@ restart: }if (ep->halted && !ep->setup_stage) {/* NOTE: must not be iso! */ -dev_dbg (dummy_dev (dum),"ep %s halted, urb %p\n" , +dev_dbg (dummy_dev (dum_hcd),"ep %s halted, urb %p\n" , ep->ep.name, urb); status = -EPIPE ; goto return_urb;
@@ -1457,7 +1475,7 @@ restart: ep->setup_stage =0 ; ep->halted =0 ; - value =handle_control_request (dum, urb, &setup, + value =handle_control_request (dum_hcd, urb, &setup, &status);/* gadget driver handles all other requests. block
@@ -1527,20 +1545,20 @@ return_urb:if (ep) ep->already_seen = ep->setup_stage =0 ; -usb_hcd_unlink_urb_from_ep (dummy_to_hcd (dum), urb); +usb_hcd_unlink_urb_from_ep (dummy_hcd_to_hcd (dum_hcd), urb);spin_unlock (&dum->lock); -usb_hcd_giveback_urb (dummy_to_hcd (dum), urb, status); +usb_hcd_giveback_urb (dummy_hcd_to_hcd (dum_hcd), urb, status);spin_lock (&dum->lock); goto restart; } -if (list_empty (&dum->urbp_list)) { -usb_put_dev (dum->udev); - dum->udev =NULL ; - }else if (dum->rh_state ==DUMMY_RH_RUNNING ) { +if (list_empty (&dum_hcd->urbp_list)) { +usb_put_dev (dum_hcd->udev); + dum_hcd->udev =NULL ; + }else if (dum_hcd->rh_state ==DUMMY_RH_RUNNING ) {/* want a 1 msec delay here */ -mod_timer (&dum->timer, jiffies +msecs_to_jiffies (1 )); +mod_timer (&dum_hcd->timer, jiffies +msecs_to_jiffies (1 )); }spin_unlock_irqrestore (&dum->lock, flags);
@@ -1557,32 +1575,32 @@ return_urb:static int dummy_hub_status (struct usb_hcd *hcd,char *buf) { -struct dummy *dum; +struct dummy_hcd *dum_hcd;unsigned long flags;int retval =0 ; - dum =hcd_to_dummy (hcd); + dum_hcd =hcd_to_dummy_hcd (hcd); -spin_lock_irqsave (&dum->lock, flags); +spin_lock_irqsave (&dum_hcd->dum->lock, flags);if (!HCD_HW_ACCESSIBLE (hcd)) goto done; -if (dum->resuming &&time_after_eq (jiffies, dum->re_timeout)) { - dum->port_status |= (USB_PORT_STAT_C_SUSPEND <<16 ); - dum->port_status &= ~USB_PORT_STAT_SUSPEND ; -set_link_state (dum); +if (dum_hcd->resuming &&time_after_eq (jiffies, dum_hcd->re_timeout)) { + dum_hcd->port_status |= (USB_PORT_STAT_C_SUSPEND <<16 ); + dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND ; +set_link_state (dum_hcd); } -if ((dum->port_status &PORT_C_MASK ) !=0 ) { +if ((dum_hcd->port_status &PORT_C_MASK ) !=0 ) { *buf = (1 <<1 ); -dev_dbg (dummy_dev (dum),"port status 0x%08x has changes\n" , - dum->port_status); +dev_dbg (dummy_dev (dum_hcd),"port status 0x%08x has changes\n" , + dum_hcd->port_status); retval =1 ; -if (dum->rh_state ==DUMMY_RH_SUSPENDED ) +if (dum_hcd->rh_state ==DUMMY_RH_SUSPENDED )usb_hcd_resume_root_hub (hcd); } done: -spin_unlock_irqrestore (&dum->lock, flags); +spin_unlock_irqrestore (&dum_hcd->dum->lock, flags);return retval; }
@@ -1606,39 +1624,40 @@ static int dummy_hub_control ( char *buf, u16 wLength ) { -struct dummy *dum; +struct dummy_hcd *dum_hcd;int retval =0 ;unsigned long flags;if (!HCD_HW_ACCESSIBLE (hcd))return -ETIMEDOUT ; - dum =hcd_to_dummy (hcd); -spin_lock_irqsave (&dum->lock, flags); + dum_hcd =hcd_to_dummy_hcd (hcd); + +spin_lock_irqsave (&dum_hcd->dum->lock, flags);switch (typeReq) {case ClearHubFeature:break ;case ClearPortFeature:switch (wValue) {case USB_PORT_FEAT_SUSPEND : -if (dum->port_status &USB_PORT_STAT_SUSPEND ) { +if (dum_hcd->port_status &USB_PORT_STAT_SUSPEND ) {/* 20msec resume signaling */ - dum->resuming =1 ; - dum->re_timeout = jiffies + + dum_hcd->resuming =1 ; + dum_hcd->re_timeout = jiffies +msecs_to_jiffies (20 ); }break ;case USB_PORT_FEAT_POWER : -if (dum->port_status &USB_PORT_STAT_POWER ) -dev_dbg (dummy_dev (dum),"power-off\n" ); +if (dum_hcd->port_status &USB_PORT_STAT_POWER ) +dev_dbg (dummy_dev (dum_hcd),"power-off\n" );/* FALLS THROUGH */ default : - dum->port_status &= ~(1 << wValue); -set_link_state (dum); + dum_hcd->port_status &= ~(1 << wValue); +set_link_state (dum_hcd); }break ;case GetHubDescriptor: -hub_descriptor ((struct usb_hub_descriptor *) buf); +hub_descriptor ((struct usb_hub_descriptor *) buf);break ;case GetHubStatus: *(__le32 *) buf =cpu_to_le32 (0 );
@@ -1650,39 +1669,38 @@ static int dummy_hub_control (/* whoever resets or resumes must GetPortStatus to * complete it!! */ -if (dum->resuming && -time_after_eq (jiffies, dum->re_timeout)) { - dum->port_status |= (USB_PORT_STAT_C_SUSPEND <<16 ); - dum->port_status &= ~USB_PORT_STAT_SUSPEND ; +if (dum_hcd->resuming && +time_after_eq (jiffies, dum_hcd->re_timeout)) { + dum_hcd->port_status |= (USB_PORT_STAT_C_SUSPEND <<16 ); + dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND ; } -if ((dum->port_status &USB_PORT_STAT_RESET ) !=0 && -time_after_eq (jiffies, dum->re_timeout)) { - dum->port_status |= (USB_PORT_STAT_C_RESET <<16 ); - dum->port_status &= ~USB_PORT_STAT_RESET ; -if (dum->pullup) { - dum->port_status |=USB_PORT_STAT_ENABLE ; -/* give it the best speed we agree on */ - dum->gadget.speed = dum->driver->speed; - dum->gadget.ep0->maxpacket =64 ; -switch (dum->gadget.speed) { +if ((dum_hcd->port_status &USB_PORT_STAT_RESET ) !=0 && +time_after_eq (jiffies, dum_hcd->re_timeout)) { + dum_hcd->port_status |= (USB_PORT_STAT_C_RESET <<16 ); + dum_hcd->port_status &= ~USB_PORT_STAT_RESET ; +if (dum_hcd->dum->pullup) { + dum_hcd->port_status |=USB_PORT_STAT_ENABLE ; +switch (dum_hcd->dum->gadget.speed) {case USB_SPEED_HIGH : - dum->port_status |= -USB_PORT_STAT_HIGH_SPEED ; + dum_hcd->port_status |= +USB_PORT_STAT_HIGH_SPEED ;break ;case USB_SPEED_LOW : - dum->gadget.ep0->maxpacket =8 ; - dum->port_status |= + dum_hcd->dum->gadget.ep0-> + maxpacket =8 ; + dum_hcd->port_status |=USB_PORT_STAT_LOW_SPEED ;break ;default : - dum->gadget.speed =USB_SPEED_FULL ; + dum_hcd->dum->gadget.speed = +USB_SPEED_FULL ;break ; } } } -set_link_state (dum); - ((__le16 *) buf)[0 ] =cpu_to_le16 (dum->port_status); - ((__le16 *) buf)[1 ] =cpu_to_le16 (dum->port_status >>16 ); +set_link_state (dum_hcd); + ((__le16 *) buf)[0 ] =cpu_to_le16 (dum_hcd->port_status); + ((__le16 *) buf)[1 ] =cpu_to_le16 (dum_hcd->port_status >>16 );break ;case SetHubFeature: retval = -EPIPE ;
@@ -1690,87 +1708,91 @@ static int dummy_hub_control (case SetPortFeature:switch (wValue) {case USB_PORT_FEAT_SUSPEND : -if (dum->active) { - dum->port_status |=USB_PORT_STAT_SUSPEND ; +if (dum_hcd->active) { + dum_hcd->port_status |=USB_PORT_STAT_SUSPEND ;/* HNP would happen here; for now we * assume b_bus_req is always true. */ -set_link_state (dum); +set_link_state (dum_hcd);if (((1 <<USB_DEVICE_B_HNP_ENABLE ) - & dum->devstatus) !=0 ) -dev_dbg (dummy_dev (dum), + & dum_hcd->dum->devstatus) !=0 ) +dev_dbg (dummy_dev (dum_hcd),"no HNP yet!\n" ); }break ;case USB_PORT_FEAT_POWER : - dum->port_status |=USB_PORT_STAT_POWER ; -set_link_state (dum); + dum_hcd->port_status |=USB_PORT_STAT_POWER ; +set_link_state (dum_hcd);break ;case USB_PORT_FEAT_RESET :/* if it's already enabled, disable */ - dum->port_status &= ~(USB_PORT_STAT_ENABLE + dum_hcd->port_status &= ~(USB_PORT_STAT_ENABLE |USB_PORT_STAT_LOW_SPEED |USB_PORT_STAT_HIGH_SPEED ); - dum->devstatus =0 ; -/* 50msec reset signaling */ - dum->re_timeout = jiffies +msecs_to_jiffies (50 ); +/* +* We want to reset device status. All but the +* Self powered feature +*/ + dum_hcd->dum->devstatus &= + (1 <<USB_DEVICE_SELF_POWERED ); + dum_hcd->re_timeout = jiffies +msecs_to_jiffies (50 );/* FALLS THROUGH */ default : -if ((dum->port_status &USB_PORT_STAT_POWER ) !=0 ) { - dum->port_status |= (1 << wValue); -set_link_state (dum); +if ((dum_hcd->port_status & +USB_PORT_STAT_POWER ) !=0 ) { + dum_hcd->port_status |= (1 << wValue); +set_link_state (dum_hcd); } }break ;default : -dev_dbg (dummy_dev (dum), +dev_dbg (dummy_dev (dum_hcd),"hub control req%04x v%04x i%04x l%d\n" , typeReq, wValue, wIndex, wLength); -/* "protocol stall" on error */ retval = -EPIPE ; } -spin_unlock_irqrestore (&dum->lock, flags); +spin_unlock_irqrestore (&dum_hcd->dum->lock, flags); -if ((dum->port_status &PORT_C_MASK ) !=0 ) +if ((dum_hcd->port_status &PORT_C_MASK ) !=0 )usb_hcd_poll_rh_status (hcd);return retval; }static int dummy_bus_suspend (struct usb_hcd *hcd) { -struct dummy *dum =hcd_to_dummy (hcd); +struct dummy_hcd *dum_hcd =hcd_to_dummy_hcd (hcd);dev_dbg (&hcd->self.root_hub->dev,"%s\n" , __func__); -spin_lock_irq (&dum->lock); - dum->rh_state =DUMMY_RH_SUSPENDED ; -set_link_state (dum); +spin_lock_irq (&dum_hcd->dum->lock); + dum_hcd->rh_state =DUMMY_RH_SUSPENDED ; +set_link_state (dum_hcd); hcd->state =HC_STATE_SUSPENDED ; -spin_unlock_irq (&dum->lock); +spin_unlock_irq (&dum_hcd->dum->lock);return 0 ; }static int dummy_bus_resume (struct usb_hcd *hcd) { -struct dummy *dum =hcd_to_dummy (hcd); +struct dummy_hcd *dum_hcd =hcd_to_dummy_hcd (hcd);int rc =0 ;dev_dbg (&hcd->self.root_hub->dev,"%s\n" , __func__); -spin_lock_irq (&dum->lock); +spin_lock_irq (&dum_hcd->dum->lock);if (!HCD_HW_ACCESSIBLE (hcd)) { rc = -ESHUTDOWN ; }else { - dum->rh_state =DUMMY_RH_RUNNING ; -set_link_state (dum); -if (!list_empty (&dum->urbp_list)) -mod_timer (&dum->timer, jiffies); + dum_hcd->rh_state =DUMMY_RH_RUNNING ; +set_link_state (dum_hcd); +if (!list_empty (&dum_hcd->urbp_list)) +mod_timer (&dum_hcd->timer, jiffies); hcd->state =HC_STATE_RUNNING ; } -spin_unlock_irq (&dum->lock); +spin_unlock_irq (&dum_hcd->dum->lock);return rc; }
@@ -1806,43 +1828,41 @@ static ssize_t show_urbs (struct device *dev, struct device_attribute *attr, char *buf) { struct usb_hcd *hcd = dev_get_drvdata (dev); -struct dummy *dum =hcd_to_dummy (hcd); +struct dummy_hcd *dum_hcd =hcd_to_dummy_hcd (hcd);struct urbp *urbp;size_t size =0 ;unsigned long flags; -spin_lock_irqsave (&dum->lock, flags); - list_for_each_entry (urbp, &dum->urbp_list, urbp_list) { +spin_lock_irqsave (&dum_hcd->dum->lock, flags); +list_for_each_entry (urbp, &dum_hcd->urbp_list, urbp_list) {size_t temp; temp =show_urb (buf,PAGE_SIZE - size, urbp->urb); buf += temp; size += temp; } -spin_unlock_irqrestore (&dum->lock, flags); +spin_unlock_irqrestore (&dum_hcd->dum->lock, flags);return size; } static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL); -static int dummy_start (struct usb_hcd *hcd) +static int dummy_start (struct usb_hcd *hcd) { -struct dummy *dum; - - dum =hcd_to_dummy (hcd); +struct dummy_hcd *dum_hcd =hcd_to_dummy_hcd (hcd);/* * MASTER side init ... we emulate a root hub that'll only ever * talk to one device (the slave side). Also appears in sysfs, * just like more familiar pci-based HCDs. */ -spin_lock_init (&dum->lock); -init_timer (&dum->timer); - dum->timer.function = dummy_timer; - dum->timer.data = (unsigned long ) dum; - dum->rh_state =DUMMY_RH_RUNNING ; +spin_lock_init (&dum_hcd->dum->lock); +init_timer (&dum_hcd->timer); + dum_hcd->timer.function = dummy_timer; + dum_hcd->timer.data = (unsigned long )dum_hcd; + dum_hcd->rh_state =DUMMY_RH_RUNNING ; -INIT_LIST_HEAD (&dum->urbp_list); +INIT_LIST_HEAD (&dum_hcd->urbp_list); hcd->power_budget =POWER_BUDGET ; hcd->state =HC_STATE_RUNNING ;
@@ -1853,18 +1873,17 @@ static int dummy_start (struct usb_hcd *hcd)#endif /* FIXME 'urbs' should be a per-device thing, maybe in usbcore */ -return device_create_file (dummy_dev (dum), &dev_attr_urbs); +return device_create_file (dummy_dev (dum_hcd), &dev_attr_urbs); }static void dummy_stop (struct usb_hcd *hcd) {struct dummy *dum; - dum =hcd_to_dummy (hcd); - -device_remove_file (dummy_dev (dum), &dev_attr_urbs); + dum = (hcd_to_dummy_hcd (hcd))->dum; +device_remove_file (dummy_dev (hcd_to_dummy_hcd (hcd)), &dev_attr_urbs);usb_gadget_unregister_driver (dum->driver); -dev_info (dummy_dev (dum),"stopped\n" ); +dev_info (dummy_dev (hcd_to_dummy_hcd (hcd)),"stopped\n" ); }/*-------------------------------------------------------------------------*/
@@ -1874,13 +1893,26 @@ static int dummy_h_get_frame (struct usb_hcd *hcd)return dummy_g_get_frame (NULL ); } +static int dummy_setup (struct usb_hcd *hcd) +{ +if (usb_hcd_is_primary_hcd (hcd)) { + the_controller.hs_hcd =hcd_to_dummy_hcd (hcd); + the_controller.hs_hcd->dum = &the_controller; +/* Mark the first roothub as being USB 2.0. */ + hcd->speed =HCD_USB2 ; + hcd->self.root_hub->speed =USB_SPEED_HIGH ; + } +return 0 ; +} +static const struct hc_driver dummy_hcd = { .description = (char *) driver_name, .product_desc ="Dummy host controller" , - .hcd_priv_size =sizeof (struct dummy ), + .hcd_priv_size =sizeof (struct dummy_hcd ), .flags =HCD_USB2 , + .reset = dummy_setup, .start = dummy_start, .stop = dummy_stop,
@@ -1897,46 +1929,45 @@ static const struct hc_driver dummy_hcd = {static int dummy_hcd_probe (struct platform_device *pdev) { -struct usb_hcd *hcd; +struct usb_hcd *hs_hcd;int retval;dev_info (&pdev->dev,"%s, driver " DRIVER_VERSION "\n" , driver_desc); - hcd =usb_create_hcd (&dummy_hcd, &pdev->dev,dev_name (&pdev->dev)); -if (!hcd) + hs_hcd =usb_create_hcd (&dummy_hcd, &pdev->dev,dev_name (&pdev->dev)); +if (!hs_hcd)return -ENOMEM ; - the_controller =hcd_to_dummy (hcd); - retval =usb_add_hcd (hcd,0 ,0 ); + retval =usb_add_hcd (hs_hcd,0 ,0 );if (retval !=0 ) { -usb_put_hcd (hcd); - the_controller =NULL ; +usb_put_hcd (hs_hcd); + the_controller.hs_hcd =NULL ; }return retval; }static int dummy_hcd_remove (struct platform_device *pdev) { -struct usb_hcd *hcd; +struct dummy *dum; - hcd =platform_get_drvdata (pdev); -usb_remove_hcd (hcd); -usb_put_hcd (hcd); - the_controller =NULL ; + dum = (hcd_to_dummy_hcd (platform_get_drvdata (pdev)))->dum; +usb_remove_hcd (dummy_hcd_to_hcd (dum->hs_hcd)); +usb_put_hcd (dummy_hcd_to_hcd (dum->hs_hcd)); + the_controller.hs_hcd =NULL ;return 0 ; }static int dummy_hcd_suspend (struct platform_device *pdev,pm_message_t state) {struct usb_hcd *hcd; -struct dummy *dum; +struct dummy_hcd *dum_hcd;int rc =0 ;dev_dbg (&pdev->dev,"%s\n" , __func__); hcd =platform_get_drvdata (pdev); - dum =hcd_to_dummy (hcd); -if (dum->rh_state ==DUMMY_RH_RUNNING ) { + dum_hcd =hcd_to_dummy_hcd (hcd); +if (dum_hcd->rh_state ==DUMMY_RH_RUNNING ) {dev_warn (&pdev->dev,"Root hub isn't suspended!\n" ); rc = -EBUSY ; }else
@@ -1996,7 +2027,7 @@ static int __init init (void) retval =platform_device_add (the_hcd_pdev);if (retval <0 ) goto err_add_hcd; -if (!the_controller) { +if (!the_controller.hs_hcd) {/* * The hcd was added successfully but its probe function failed * for some reason.
Signature · 5 lines
1.7.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 v12 7/8 usb: Adding SuperSpeed support to dummy_hcd
In reply to Tatyana BrokhmanThis patch adds SS support to the dummy hcd module. It may be used to test SS device when no (SS) HW is available.
USB 3.0 hub includes 2 hubs - HS and SS ones.
This patch adds support for a SS hub in the dummy_hcd module. Thus, when dummy_hcd enabled it will register 2 root hubs (SS and HS).
A new module parameter was added to simulate a SuperSpeed connection. When a new device is connected it will enumerate via the HS hub by default. In order to simulate SuperSpeed connection set the is_super_speed module parameter to true.
--- drivers/usb/gadget/dummy_hcd.c | 540 +++++++++++++++++++++++++++++++++++----- 1 files changed, 483 insertions(+), 57 deletions(-)
drivers/usb/gadget/dummy_hcd.c +483 -57
@@ -70,6 +70,15 @@ MODULE_DESCRIPTION (DRIVER_DESC);MODULE_AUTHOR ("David Brownell" );MODULE_LICENSE ("GPL" ); +struct dummy_hcd_module_parameters { +bool is_super_speed; +}; + +static struct dummy_hcd_module_parameters mod_data = { + .is_super_speed = false +}; +module_param_named (is_super_speed, mod_data.is_super_speed, bool,S_IRUGO ); +MODULE_PARM_DESC (is_super_speed,"true to simulate SuperSpeed connection" );/*-------------------------------------------------------------------------*/ /* gadget side driver data structres */
@@ -188,6 +197,7 @@ struct dummy {* MASTER/HOST side support */ struct dummy_hcd *hs_hcd; +struct dummy_hcd *ss_hcd; };static inline struct dummy_hcd *hcd_to_dummy_hcd (struct usb_hcd *hcd)
@@ -218,7 +228,10 @@ static inline struct dummy *ep_to_dummy (struct dummy_ep *ep)static inline struct dummy_hcd *gadget_to_dummy_hcd (struct usb_gadget *gadget) { struct dummy *dum = container_of(gadget, struct dummy, gadget); -return dum->hs_hcd; +if (dum->gadget.speed ==USB_SPEED_SUPER ) +return dum->ss_hcd; +else +return dum->hs_hcd; }static inline struct dummy *gadget_dev_to_dummy (struct device *dev)
@@ -266,10 +279,88 @@ stop_activity (struct dummy *dum)/* driver now does any non-usb quiescing necessary */ } +/** +* set_ss_link_state() - Sets the current state of the SuperSpeed link +* @dum_hcd: pointer to the dummy_hcd structure to update the link +* state for +* +* This function updates the port_status according to the link +* state. The old status is saved befor updating. +* Note: this function should be called only for SuperSpeed +* master and the caller must hold the lock. +*/ +static void +set_ss_link_state (struct dummy_hcd *dum_hcd) +{ +struct dummy *dum = dum_hcd->dum; +if (dum->gadget.speed <USB_SPEED_SUPER ) +return ; + dum_hcd->active =0 ; +if ((dum_hcd->port_status &USB_SS_PORT_STAT_POWER ) ==0 ) + dum_hcd->port_status =0 ; + +/* UDC suspend must cause a disconnect */ +else if (!dum->pullup || dum->udc_suspended) { + dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION | +USB_PORT_STAT_ENABLE ); +if ((dum_hcd->old_status &USB_PORT_STAT_CONNECTION ) !=0 ) + dum_hcd->port_status |= + (USB_PORT_STAT_C_CONNECTION <<16 ); + }else { +/* device is connected and not suspended */ + dum_hcd->port_status |= (USB_PORT_STAT_CONNECTION | +USB_PORT_STAT_SPEED_5GBPS ) ; +if ((dum_hcd->old_status &USB_PORT_STAT_CONNECTION ) ==0 ) + dum_hcd->port_status |= + (USB_PORT_STAT_C_CONNECTION <<16 ); +if ((dum_hcd->port_status &USB_PORT_STAT_ENABLE ) ==1 && + (dum_hcd->port_status &USB_SS_PORT_LS_U0 ) ==1 && + dum_hcd->rh_state !=DUMMY_RH_SUSPENDED ) + dum_hcd->active =1 ; + } + + +if ((dum_hcd->port_status &USB_PORT_STAT_ENABLE ) ==0 || + dum_hcd->active) + dum_hcd->resuming =0 ; + +/* if !connected or reset */ +if ((dum_hcd->port_status &USB_PORT_STAT_CONNECTION ) ==0 || + (dum_hcd->port_status &USB_PORT_STAT_RESET ) !=0 ) { +/* +* We're connected and not reseted (reset occured now), +* and driver attached - disconnect! +*/ +if ((dum_hcd->old_status &USB_PORT_STAT_CONNECTION ) !=0 && + (dum_hcd->old_status &USB_PORT_STAT_RESET ) ==0 && + dum->driver) { +stop_activity (dum); +spin_unlock (&dum->lock); + dum->driver->disconnect (&dum->gadget); +spin_lock (&dum->lock); + } + }else if (dum_hcd->active != dum_hcd->old_active) { +if (dum_hcd->old_active && dum->driver->suspend) { +spin_unlock (&dum->lock); + dum->driver->suspend (&dum->gadget); +spin_lock (&dum->lock); + }else if (!dum_hcd->old_active && dum->driver->resume) { +spin_unlock (&dum->lock); + dum->driver->resume (&dum->gadget); +spin_lock (&dum->lock); + } + } + + dum_hcd->old_status = dum_hcd->port_status; + dum_hcd->old_active = dum_hcd->active; +} +/* caller must hold lock */ static void set_link_state (struct dummy_hcd *dum_hcd) {struct dummy *dum = dum_hcd->dum; +if (dum->gadget.speed ==USB_SPEED_SUPER ) +return ; dum_hcd->active =0 ;if ((dum_hcd->port_status &USB_PORT_STAT_POWER ) ==0 )
@@ -355,13 +446,17 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) dum =ep_to_dummy (ep);if (!dum->driver)return -ESHUTDOWN ; - dum_hcd = dum->hs_hcd; +if (dum->gadget.speed ==USB_SPEED_SUPER ) + dum_hcd = dum->ss_hcd; +else + dum_hcd = dum->hs_hcd;if (!is_enabled (dum_hcd))return -ESHUTDOWN ;/* * For HS/FS devices only bits 0..10 of the wMaxPacketSize represent the * maximum packet size. +* For SS devices the wMaxPacketSize is limited by 1024. */ max =le16_to_cpu (desc->wMaxPacketSize) &0x7ff ;
@@ -381,6 +476,10 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) goto done; }switch (dum->gadget.speed) { +case USB_SPEED_SUPER : +if (max ==1024 ) +break ; + goto done;case USB_SPEED_HIGH :if (max ==512 )break ;
@@ -399,6 +498,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) goto done;/* real hardware might not handle all packet sizes */ switch (dum->gadget.speed) { +case USB_SPEED_SUPER :case USB_SPEED_HIGH :if (max <=1024 )break ;
@@ -419,6 +519,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) goto done;/* real hardware might not handle all packet sizes */ switch (dum->gadget.speed) { +case USB_SPEED_SUPER :case USB_SPEED_HIGH :if (max <=1024 )break ;
@@ -539,7 +640,10 @@ dummy_queue (struct usb_ep *_ep, struct usb_request *_req,return -EINVAL ; dum =ep_to_dummy (ep); - dum_hcd = dum->hs_hcd; +if (dum->gadget.speed ==USB_SPEED_SUPER ) + dum_hcd = dum->ss_hcd; +else + dum_hcd = dum->hs_hcd;if (!dum->driver || !is_enabled (dum_hcd))return -ESHUTDOWN ;
@@ -725,9 +829,14 @@ static int dummy_pullup (struct usb_gadget *_gadget, int value) dum =gadget_to_dummy_hcd (_gadget)->dum;spin_lock_irqsave (&dum->lock, flags); dum->pullup = (value !=0 ); -set_link_state (dum->hs_hcd); +if (dum->gadget.speed ==USB_SPEED_SUPER ) +set_ss_link_state (dum->ss_hcd); +else +set_link_state (dum->hs_hcd);spin_unlock_irqrestore (&dum->lock, flags); -usb_hcd_poll_rh_status (dummy_hcd_to_hcd (dum->hs_hcd)); +usb_hcd_poll_rh_status ((dum->gadget.speed ==USB_SPEED_SUPER ? +dummy_hcd_to_hcd (dum->ss_hcd) : +dummy_hcd_to_hcd (dum->hs_hcd)));return 0 ; }
@@ -808,8 +917,21 @@ usb_gadget_probe_driver(struct usb_gadget_driver *driver, } dum->gadget.ep0 = &dum->ep [0 ].ep; - dum->gadget.speed =min ((u8 )driver->speed, (u8 )USB_SPEED_HIGH ) ; - dum->ep[0 ].ep.maxpacket =64 ; +if (mod_data.is_super_speed) + dum->gadget.speed = driver->speed; +else + dum->gadget.speed =min ((u8 )USB_SPEED_HIGH , (u8 )driver->speed); +if (dum->gadget.speed < driver->speed) +dev_dbg (udc_dev (dum),"This device can perform faster if" +" you connect it to a " +"SupeSpeed port...\n" ); + +if (dum->gadget.speed ==USB_SPEED_SUPER ) { +for (i =0 ; i <DUMMY_ENDPOINTS ; i++) + dum->ep[i].ep.max_streams =0x10 ; + dum->ep[0 ].ep.maxpacket =9 ; + }else + dum->ep[0 ].ep.maxpacket =64 ;list_del_init (&dum->ep [0 ].ep.ep_list);INIT_LIST_HEAD (&dum->fifo_req.queue);
@@ -828,12 +950,21 @@ usb_gadget_probe_driver(struct usb_gadget_driver *driver,/* khubd will enumerate this in a while */ spin_lock_irq (&dum->lock); dum->pullup =1 ; - dum->gadget.is_otg = - (dummy_hcd_to_hcd (dum->hs_hcd)->self.otg_port !=0 ); -set_link_state (dum->hs_hcd); +if (dum->gadget.speed ==USB_SPEED_SUPER ) { + dum->gadget.is_otg = + (dummy_hcd_to_hcd (dum->ss_hcd)->self.otg_port !=0 ); +set_ss_link_state (dum->ss_hcd); + }else { + dum->gadget.is_otg = + (dummy_hcd_to_hcd (dum->hs_hcd)->self.otg_port !=0 ); +set_link_state (dum->hs_hcd); + } +spin_unlock_irq (&dum->lock); -usb_hcd_poll_rh_status (dummy_hcd_to_hcd (dum->hs_hcd)); +usb_hcd_poll_rh_status ((dum->gadget.speed ==USB_SPEED_SUPER ? +dummy_hcd_to_hcd (dum->ss_hcd) : +dummy_hcd_to_hcd (dum->hs_hcd)));return 0 ; }EXPORT_SYMBOL (usb_gadget_probe_driver);
@@ -854,18 +985,25 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)spin_lock_irqsave (&dum->lock, flags); dum->pullup =0 ; -set_link_state (dum->hs_hcd); +if (dum->gadget.speed ==USB_SPEED_SUPER ) +set_ss_link_state (dum->ss_hcd); +else +set_link_state (dum->hs_hcd);spin_unlock_irqrestore (&dum->lock, flags); driver->unbind (&dum->gadget); dum->gadget.dev.driver =NULL ; dum->driver =NULL ; -spin_lock_irqsave (&dum->lock, flags); dum->pullup =0 ; -set_link_state (dum->hs_hcd); +if (dum->gadget.speed ==USB_SPEED_SUPER ) +set_ss_link_state (dum->ss_hcd); +else +set_link_state (dum->hs_hcd);spin_unlock_irqrestore (&dum->lock, flags); -usb_hcd_poll_rh_status (dummy_hcd_to_hcd (dum->hs_hcd)); +usb_hcd_poll_rh_status ((dum->gadget.speed ==USB_SPEED_SUPER ? +dummy_hcd_to_hcd (dum->ss_hcd) : +dummy_hcd_to_hcd (dum->hs_hcd)));return 0 ; }EXPORT_SYMBOL (usb_gadget_unregister_driver);
@@ -933,10 +1071,15 @@ static int dummy_udc_suspend (struct platform_device *pdev, pm_message_t state)dev_dbg (&pdev->dev,"%s\n" , __func__);spin_lock_irq (&dum->lock); dum->udc_suspended =1 ; -set_link_state (dum->hs_hcd); +if (dum->gadget.speed ==USB_SPEED_SUPER ) +set_ss_link_state (dum->ss_hcd); +else +set_link_state (dum->hs_hcd);spin_unlock_irq (&dum->lock); -usb_hcd_poll_rh_status (dummy_hcd_to_hcd (dum->hs_hcd)); +usb_hcd_poll_rh_status ((dum->gadget.speed ==USB_SPEED_SUPER ? +dummy_hcd_to_hcd (dum->ss_hcd) : +dummy_hcd_to_hcd (dum->hs_hcd)));return 0 ; }
@@ -947,10 +1090,15 @@ static int dummy_udc_resume (struct platform_device *pdev)dev_dbg (&pdev->dev,"%s\n" , __func__);spin_lock_irq (&dum->lock); dum->udc_suspended =0 ; -set_link_state (dum->hs_hcd); +if (dum->gadget.speed ==USB_SPEED_SUPER ) +set_ss_link_state (dum->ss_hcd); +else +set_link_state (dum->hs_hcd);spin_unlock_irq (&dum->lock); -usb_hcd_poll_rh_status (dummy_hcd_to_hcd (dum->hs_hcd)); +usb_hcd_poll_rh_status ((dum->gadget.speed ==USB_SPEED_SUPER ? +dummy_hcd_to_hcd (dum->ss_hcd) : +dummy_hcd_to_hcd (dum->hs_hcd)));return 0 ; }
@@ -1178,6 +1326,21 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep) tmp *=8 /* applies to entire frame */ ; limit += limit * tmp; } +if (dum->gadget.speed ==USB_SPEED_SUPER ) { +switch (ep->desc->bmAttributes &0x03 ) { +case USB_ENDPOINT_XFER_ISOC : +/* Sec. 4.4.8.2 USB3.0 Spec */ + limit =3 *16 *1024 *8 ; +break ; +case USB_ENDPOINT_XFER_INT : +/* Sec. 4.4.7.2 USB3.0 Spec */ + limit =3 *1024 *8 ; +break ; +case USB_ENDPOINT_XFER_BULK : +default : +break ; + } + }return limit; }
@@ -1190,7 +1353,8 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address) {int i; -if (!is_active (dum->hs_hcd)) +if (!is_active ((dum->gadget.speed ==USB_SPEED_SUPER ? + dum->ss_hcd : dum->hs_hcd)))return NULL ;if ((address & ~USB_DIR_IN ) ==0 )return &dum->ep [0 ];
@@ -1264,6 +1428,27 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,case USB_DEVICE_A_ALT_HNP_SUPPORT : dum->gadget.a_alt_hnp_support =1 ;break ; +case USB_DEVICE_U1_ENABLE : +if (dummy_hcd_to_hcd (dum_hcd)->speed == +HCD_USB3 ) + w_value =USB_DEV_STAT_U1_ENABLED ; +else + ret_val = -EOPNOTSUPP ; +break ; +case USB_DEVICE_U2_ENABLE : +if (dummy_hcd_to_hcd (dum_hcd)->speed == +HCD_USB3 ) + w_value =USB_DEV_STAT_U2_ENABLED ; +else + ret_val = -EOPNOTSUPP ; +break ; +case USB_DEVICE_LTM_ENABLE : +if (dummy_hcd_to_hcd (dum_hcd)->speed == +HCD_USB3 ) + w_value =USB_DEV_STAT_LTM_ENABLED ; +else + ret_val = -EOPNOTSUPP ; +break ;default : ret_val = -EOPNOTSUPP ; }
@@ -1290,6 +1475,27 @@ static int handle_control_request(struct dummy_hcd *dum_hcd, struct urb *urb,case USB_DEVICE_REMOTE_WAKEUP : w_value =USB_DEVICE_REMOTE_WAKEUP ;break ; +case USB_DEVICE_U1_ENABLE : +if (dummy_hcd_to_hcd (dum_hcd)->speed == +HCD_USB3 ) + w_value =USB_DEV_STAT_U1_ENABLED ; +else + ret_val = -EOPNOTSUPP ; +break ; +case USB_DEVICE_U2_ENABLE : +if (dummy_hcd_to_hcd (dum_hcd)->speed == +HCD_USB3 ) + w_value =USB_DEV_STAT_U2_ENABLED ; +else + ret_val = -EOPNOTSUPP ; +break ; +case USB_DEVICE_LTM_ENABLE : +if (dummy_hcd_to_hcd (dum_hcd)->speed == +HCD_USB3 ) + w_value =USB_DEV_STAT_LTM_ENABLED ; +else + ret_val = -EOPNOTSUPP ; +break ;default : ret_val = -EOPNOTSUPP ;break ;
@@ -1371,6 +1577,10 @@ static void dummy_timer(unsigned long _dum_hcd)case USB_SPEED_HIGH : total =512 /*bytes*/ *13 /*packets*/ *8 /*uframes*/ ;break ; +case USB_SPEED_SUPER : +/* Bus speed is 500000 bytes/ms, so use a little less */ + total =490000 ; +break ;default :dev_err (dummy_dev (dum_hcd),"bogus device speed\n" );return ;
@@ -1588,7 +1798,10 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf)if (dum_hcd->resuming &&time_after_eq (jiffies, dum_hcd->re_timeout)) { dum_hcd->port_status |= (USB_PORT_STAT_C_SUSPEND <<16 ); dum_hcd->port_status &= ~USB_PORT_STAT_SUSPEND ; -set_link_state (dum_hcd); +if (hcd->speed ==HCD_USB3 ) +set_ss_link_state (dum_hcd); +else +set_link_state (dum_hcd); }if ((dum_hcd->port_status &PORT_C_MASK ) !=0 ) {
@@ -1605,6 +1818,18 @@ done: }static inline void +ss_hub_descriptor (struct usb_hub_descriptor *desc) +{ +memset (desc,0 ,sizeof *desc); + desc->bDescriptorType =0x2a ; + desc->bDescLength =12 ; + desc->wHubCharacteristics =cpu_to_le16 (0x0001 ); + desc->bNbrPorts =1 ; + desc->u.ss.bHubHdrDecLat =0x04 ;/* Worst case: 0.4 micro sec*/ + desc->u.ss.DeviceRemovable =0xffff ; +} + +static inline void hub_descriptor (struct usb_hub_descriptor *desc) {memset (desc,0 ,sizeof *desc);
@@ -1640,6 +1865,12 @@ static int dummy_hub_control (case ClearPortFeature:switch (wValue) {case USB_PORT_FEAT_SUSPEND : +if (hcd->speed ==HCD_USB3 ) { +dev_dbg (dummy_dev (dum_hcd), +"USB_PORT_FEAT_SUSPEND req not " +"supported for USB 3.0 roothub\n" ); + goto error; + }if (dum_hcd->port_status &USB_PORT_STAT_SUSPEND ) {/* 20msec resume signaling */ dum_hcd->resuming =1 ;
@@ -1648,16 +1879,37 @@ static int dummy_hub_control ( }break ;case USB_PORT_FEAT_POWER : -if (dum_hcd->port_status &USB_PORT_STAT_POWER ) -dev_dbg (dummy_dev (dum_hcd),"power-off\n" ); +if (hcd->speed ==HCD_USB3 ) { +if (dum_hcd->port_status &USB_PORT_STAT_POWER ) +dev_dbg (dummy_dev (dum_hcd), +"power-off\n" ); + }else +if (dum_hcd->port_status & +USB_SS_PORT_STAT_POWER ) +dev_dbg (dummy_dev (dum_hcd), +"power-off\n" );/* FALLS THROUGH */ default : dum_hcd->port_status &= ~(1 << wValue); -set_link_state (dum_hcd); +if (hcd->speed ==HCD_USB3 ) +set_ss_link_state (dum_hcd); +else +set_link_state (dum_hcd); }break ;case GetHubDescriptor: -hub_descriptor ((struct usb_hub_descriptor *) buf); +if (hcd->speed ==HCD_USB3 && + (wLength <USB_DT_SS_HUB_SIZE || + wValue != (USB_DT_SS_HUB <<8 ))) { +dev_dbg (dummy_dev (dum_hcd), +"Wrong hub descriptor type for " +"USB 3.0 roothub.\n" ); + goto error; + } +if (hcd->speed ==HCD_USB3 ) +ss_hub_descriptor ((struct usb_hub_descriptor *) buf); +else +hub_descriptor ((struct usb_hub_descriptor *) buf);break ;case GetHubStatus: *(__le32 *) buf =cpu_to_le32 (0 );
@@ -1680,25 +1932,31 @@ static int dummy_hub_control ( dum_hcd->port_status &= ~USB_PORT_STAT_RESET ;if (dum_hcd->dum->pullup) { dum_hcd->port_status |=USB_PORT_STAT_ENABLE ; -switch (dum_hcd->dum->gadget.speed) { -case USB_SPEED_HIGH : - dum_hcd->port_status |= -USB_PORT_STAT_HIGH_SPEED ; -break ; -case USB_SPEED_LOW : - dum_hcd->dum->gadget.ep0-> - maxpacket =8 ; - dum_hcd->port_status |= -USB_PORT_STAT_LOW_SPEED ; -break ; -default : - dum_hcd->dum->gadget.speed = -USB_SPEED_FULL ; -break ; + +if (hcd->speed <HCD_USB3 ) { +switch (dum_hcd->dum->gadget.speed) { +case USB_SPEED_HIGH : + dum_hcd->port_status |= +USB_PORT_STAT_HIGH_SPEED ; +break ; +case USB_SPEED_LOW : + dum_hcd->dum->gadget.ep0-> + maxpacket =8 ; + dum_hcd->port_status |= +USB_PORT_STAT_LOW_SPEED ; +break ; +default : + dum_hcd->dum->gadget.speed = +USB_SPEED_FULL ; +break ; + } } } } -set_link_state (dum_hcd); +if (hcd->speed ==HCD_USB3 ) +set_ss_link_state (dum_hcd); +else +set_link_state (dum_hcd); ((__le16 *) buf)[0 ] =cpu_to_le16 (dum_hcd->port_status); ((__le16 *) buf)[1 ] =cpu_to_le16 (dum_hcd->port_status >>16 );break ;
@@ -1707,7 +1965,36 @@ static int dummy_hub_control (break ;case SetPortFeature:switch (wValue) { +case USB_PORT_FEAT_LINK_STATE : +if (hcd->speed !=HCD_USB3 ) { +dev_dbg (dummy_dev (dum_hcd), +"USB_PORT_FEAT_LINK_STATE req not " +"supported for USB 2.0 roothub\n" ); + goto error; + } +/* +* Since this is dummy we don't have an actual link so +* there is nothing to do for the SET_LINK_STATE cmd +*/ +break ; +case USB_PORT_FEAT_U1_TIMEOUT : +case USB_PORT_FEAT_U2_TIMEOUT : +/* TODO: add suspend/resume support! */ +if (hcd->speed !=HCD_USB3 ) { +dev_dbg (dummy_dev (dum_hcd), +"USB_PORT_FEAT_U1/2_TIMEOUT req not " +"supported for USB 2.0 roothub\n" ); + goto error; + } +break ;case USB_PORT_FEAT_SUSPEND : +/* Applicable only for USB2.0 hub */ +if (hcd->speed ==HCD_USB3 ) { +dev_dbg (dummy_dev (dum_hcd), +"USB_PORT_FEAT_SUSPEND req not " +"supported for USB 3.0 roothub\n" ); + goto error; + }if (dum_hcd->active) { dum_hcd->port_status |=USB_PORT_STAT_SUSPEND ;
@@ -1722,12 +2009,33 @@ static int dummy_hub_control ( }break ;case USB_PORT_FEAT_POWER : - dum_hcd->port_status |=USB_PORT_STAT_POWER ; -set_link_state (dum_hcd); +if (hcd->speed ==HCD_USB3 ) { + dum_hcd->port_status |=USB_SS_PORT_STAT_POWER ; +set_ss_link_state (dum_hcd); + }else { + dum_hcd->port_status |=USB_PORT_STAT_POWER ; +set_link_state (dum_hcd); + }break ; +case USB_PORT_FEAT_BH_PORT_RESET : +/* Applicable only for USB3.0 hub */ +if (hcd->speed !=HCD_USB3 ) { +dev_dbg (dummy_dev (dum_hcd), +"USB_PORT_FEAT_BH_PORT_RESET req not " +"supported for USB 2.0 roothub\n" ); + goto error; + } +/* FALLS THROUGH */ case USB_PORT_FEAT_RESET :/* if it's already enabled, disable */ - dum_hcd->port_status &= ~(USB_PORT_STAT_ENABLE +if (hcd->speed ==HCD_USB3 ) { + dum_hcd->port_status =0 ; + dum_hcd->port_status = + (USB_SS_PORT_STAT_POWER | +USB_PORT_STAT_CONNECTION | +USB_PORT_STAT_RESET ); + }else + dum_hcd->port_status &= ~(USB_PORT_STAT_ENABLE |USB_PORT_STAT_LOW_SPEED |USB_PORT_STAT_HIGH_SPEED );/*
@@ -1736,21 +2044,50 @@ static int dummy_hub_control (*/ dum_hcd->dum->devstatus &= (1 <<USB_DEVICE_SELF_POWERED ); +/* +* FIXME USB3.0: what is the correct reset signaling +* interval? Is it still 50msec as for HS? +*/ dum_hcd->re_timeout = jiffies +msecs_to_jiffies (50 );/* FALLS THROUGH */ default : -if ((dum_hcd->port_status & -USB_PORT_STAT_POWER ) !=0 ) { - dum_hcd->port_status |= (1 << wValue); -set_link_state (dum_hcd); - } +if (hcd->speed ==HCD_USB3 ) { +if ((dum_hcd->port_status & +USB_SS_PORT_STAT_POWER ) !=0 ) { + dum_hcd->port_status |= (1 << wValue); +set_ss_link_state (dum_hcd); + } + }else +if ((dum_hcd->port_status & +USB_PORT_STAT_POWER ) !=0 ) { + dum_hcd->port_status |= (1 << wValue); +set_link_state (dum_hcd); + } + } +break ; +case GetPortErrorCount: +if (hcd->speed !=HCD_USB3 ) { +dev_dbg (dummy_dev (dum_hcd), +"GetPortErrorCount req not " +"supported for USB 2.0 roothub\n" ); + goto error; + } +/* We'll always return 0 since this is a dummy hub */ + *(__le32 *) buf =cpu_to_le32 (0 ); +break ; +case SetHubDepth: +if (hcd->speed !=HCD_USB3 ) { +dev_dbg (dummy_dev (dum_hcd), +"SetHubDepth req not supported for " +"USB 2.0 roothub\n" ); + goto error; }break ; -default :dev_dbg (dummy_dev (dum_hcd),"hub control req%04x v%04x i%04x l%d\n" , typeReq, wValue, wIndex, wLength); +error:/* "protocol stall" on error */ retval = -EPIPE ; }
@@ -1769,7 +2106,10 @@ static int dummy_bus_suspend (struct usb_hcd *hcd)spin_lock_irq (&dum_hcd->dum->lock); dum_hcd->rh_state =DUMMY_RH_SUSPENDED ; -set_link_state (dum_hcd); +if (hcd->speed ==HCD_USB3 ) +set_ss_link_state (dum_hcd); +else +set_link_state (dum_hcd); hcd->state =HC_STATE_SUSPENDED ;spin_unlock_irq (&dum_hcd->dum->lock);return 0 ;
@@ -1787,7 +2127,10 @@ static int dummy_bus_resume (struct usb_hcd *hcd) rc = -ESHUTDOWN ; }else { dum_hcd->rh_state =DUMMY_RH_RUNNING ; -set_link_state (dum_hcd); +if (hcd->speed ==HCD_USB3 ) +set_ss_link_state (dum_hcd); +else +set_link_state (dum_hcd);if (!list_empty (&dum_hcd->urbp_list))mod_timer (&dum_hcd->timer, jiffies); hcd->state =HC_STATE_RUNNING ;
@@ -1811,6 +2154,7 @@ show_urb (char *buf, size_t size, struct urb *urb)case USB_SPEED_LOW : s ="ls" ;break ;case USB_SPEED_FULL : s ="fs" ;break ;case USB_SPEED_HIGH : s ="hs" ;break ; +case USB_SPEED_SUPER : s ="ss" ;break ;default : s ="?" ;break ; }; s; }), ep, ep ? (usb_pipein (urb->pipe) ? "in" : "out") : "",
@@ -1847,6 +2191,25 @@ show_urbs (struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR (urbs, S_IRUGO, show_urbs, NULL); +static int dummy_start_ss (struct dummy_hcd *dum_hcd) +{ +init_timer (&dum_hcd->timer); + dum_hcd->timer.function = dummy_timer; + dum_hcd->timer.data = (unsigned long )dum_hcd; + dum_hcd->rh_state =DUMMY_RH_RUNNING ; +INIT_LIST_HEAD (&dum_hcd->urbp_list); +dummy_hcd_to_hcd (dum_hcd)->power_budget =POWER_BUDGET ; +dummy_hcd_to_hcd (dum_hcd)->state =HC_STATE_RUNNING ; +dummy_hcd_to_hcd (dum_hcd)->uses_new_polling =1 ; +#ifdef CONFIG_USB_OTG +dummy_hcd_to_hcd (dum_hcd)->self.otg_port =1 ; +#endif +return 0 ; + +/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */ +return device_create_file (dummy_dev (dum_hcd), &dev_attr_urbs); +} +static int dummy_start (struct usb_hcd *hcd) {struct dummy_hcd *dum_hcd =hcd_to_dummy_hcd (hcd);
@@ -1856,6 +2219,9 @@ static int dummy_start(struct usb_hcd *hcd)* talk to one device (the slave side). Also appears in sysfs, * just like more familiar pci-based HCDs. */ +if (!usb_hcd_is_primary_hcd (hcd)) +return dummy_start_ss (dum_hcd); +spin_lock_init (&dum_hcd->dum->lock);init_timer (&dum_hcd->timer); dum_hcd->timer.function = dummy_timer;
@@ -1898,19 +2264,52 @@ static int dummy_setup(struct usb_hcd *hcd)if (usb_hcd_is_primary_hcd (hcd)) { the_controller.hs_hcd =hcd_to_dummy_hcd (hcd); the_controller.hs_hcd->dum = &the_controller; -/* Mark the first roothub as being USB 2.0. */ +/* +* Mark the first roothub as being USB 2.0. +* The USB 3.0 roothub will be registered later by +* dummy_hcd_probe() +*/ hcd->speed =HCD_USB2 ; hcd->self.root_hub->speed =USB_SPEED_HIGH ; + }else { + the_controller.ss_hcd =hcd_to_dummy_hcd (hcd); + the_controller.ss_hcd->dum = &the_controller; + hcd->speed =HCD_USB3 ; + hcd->self.root_hub->speed =USB_SPEED_SUPER ; }return 0 ; } +/* Change a group of bulk endpoints to support multiple stream IDs */ +int dummy_alloc_streams (struct usb_hcd *hcd,struct usb_device *udev, +struct usb_host_endpoint **eps,unsigned int num_eps, +unsigned int num_streams,gfp_t mem_flags) +{ +if (hcd->speed !=HCD_USB3 ) +dev_dbg (dummy_dev (hcd_to_dummy_hcd (hcd)), +"%s() - ERROR! Not supported for USB2.0 roothub\n" , + __func__); +return 0 ; +} + +/* Reverts a group of bulk endpoints back to not using stream IDs. */ +int dummy_free_streams (struct usb_hcd *hcd,struct usb_device *udev, +struct usb_host_endpoint **eps,unsigned int num_eps, +gfp_t mem_flags) +{ +if (hcd->speed !=HCD_USB3 ) +dev_dbg (dummy_dev (hcd_to_dummy_hcd (hcd)), +"%s() - ERROR! Not supported for USB2.0 roothub\n" , + __func__); +return 0 ; +} +static const struct hc_driver dummy_hcd = { .description = (char *) driver_name, .product_desc ="Dummy host controller" , .hcd_priv_size =sizeof (struct dummy_hcd ), - .flags =HCD_USB2 , + .flags =HCD_USB3 |HCD_SHARED , .reset = dummy_setup, .start = dummy_start,
@@ -1925,11 +2324,15 @@ static const struct hc_driver dummy_hcd = { .hub_control = dummy_hub_control, .bus_suspend = dummy_bus_suspend, .bus_resume = dummy_bus_resume, + + .alloc_streams = dummy_alloc_streams, + .free_streams = dummy_free_streams, };static int dummy_hcd_probe (struct platform_device *pdev) {struct usb_hcd *hs_hcd; +struct usb_hcd *ss_hcd;int retval;dev_info (&pdev->dev,"%s, driver " DRIVER_VERSION "\n" , driver_desc);
@@ -1941,8 +2344,27 @@ static int dummy_hcd_probe(struct platform_device *pdev) retval =usb_add_hcd (hs_hcd,0 ,0 );if (retval !=0 ) {usb_put_hcd (hs_hcd); - the_controller.hs_hcd =NULL ; +return retval; + } + + ss_hcd =usb_create_shared_hcd (&dummy_hcd, &pdev->dev, +dev_name (&pdev->dev), hs_hcd); +if (!ss_hcd) { + retval = -ENOMEM ; + goto dealloc_usb2_hcd; } + + retval =usb_add_hcd (ss_hcd,0 ,0 ); +if (retval) + goto put_usb3_hcd; + +return 0 ; + +put_usb3_hcd: +usb_put_hcd (ss_hcd); +dealloc_usb2_hcd: +usb_put_hcd (hs_hcd); + the_controller.hs_hcd = the_controller.ss_hcd =NULL ;return retval; }
@@ -1951,9 +2373,13 @@ static int dummy_hcd_remove (struct platform_device *pdev)struct dummy *dum; dum = (hcd_to_dummy_hcd (platform_get_drvdata (pdev)))->dum; +if (dum->ss_hcd) { +usb_remove_hcd (dummy_hcd_to_hcd (dum->ss_hcd)); +usb_put_hcd (dummy_hcd_to_hcd (dum->ss_hcd)); + }usb_remove_hcd (dummy_hcd_to_hcd (dum->hs_hcd));usb_put_hcd (dummy_hcd_to_hcd (dum->hs_hcd)); - the_controller.hs_hcd =NULL ; + the_controller.ss_hcd = the_controller.hs_hcd =NULL ;return 0 ; }
@@ -2027,7 +2453,7 @@ static int __init init (void) retval =platform_device_add (the_hcd_pdev);if (retval <0 ) goto err_add_hcd; -if (!the_controller.hs_hcd) { +if (!the_controller.hs_hcd || !the_controller.ss_hcd) {/* * The hcd was added successfully but its probe function failed * for some reason.
Signature · 5 lines
1.7.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: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi,
Quoted 23 lines · Tatyana Brokhman
This patch adds SS support to the dummy hcd module. It may be used to test SS device when no (SS) HW is available.
USB 3.0 hub includes 2 hubs - HS and SS ones.
This patch adds support for a SS hub in thedummy_hcdmodule. Thus, whendummy_hcdenabled it will register 2 root hubs (SS and HS).
A new module parameter was added to simulate a SuperSpeed connection. When a new device is connected it will enumerate via the HS hub by default. In order to simulate SuperSpeed connection set theis_super_speedmodule parameter to true.Signed-off-by Tatyana Brokhman <[email protected]>--- drivers/usb/gadget/dummy_hcd.c | 540 +++++++++++++++++++++++++++++++++++----- 1 files changed, 483 insertions(+), 57 deletions(-)drivers/usb/gadget/dummy_hcd.c +0
-0@@ -70,6 +70,15 @@ MODULE_DESCRIPTION (DRIVER_DESC);MODULE_AUTHOR ("David Brownell" );MODULE_LICENSE ("GPL" );
drivers/usb/gadget/dummy_hcd.c MODULE_DESCRIPTION (DRIVER_DESC); · line 81
Quoted 10 lines
drivers/usb/gadget/dummy_hcd.c +9
-0+struct dummy_hcd_module_parameters { +bool is_super_speed; +}; + +static struct dummy_hcd_module_parameters mod_data = { + .is_super_speed = false +}; +module_param_named (is_super_speed, mod_data.is_super_speed, bool,S_IRUGO ); +MODULE_PARM_DESC (is_super_speed,"true to simulate SuperSpeed connection" );
you shouldn't need this. You should always enable SuperSpeed for this driver.
Quoted 29 lines
drivers/usb/gadget/dummy_hcd.c +7
-1/*-------------------------------------------------------------------------*/ /* gadget side driver data structres */ @@ -188,6 +197,7 @@ struct dummy {* MASTER/HOST side support */ struct dummy_hcd *hs_hcd; +struct dummy_hcd *ss_hcd; };static inline struct dummy_hcd *hcd_to_dummy_hcd (struct usb_hcd *hcd)@@ -218,7 +228,10 @@ static inline struct dummy *ep_to_dummy (struct dummy_ep *ep)static inline struct dummy_hcd *gadget_to_dummy_hcd (struct usb_gadget *gadget) { struct dummy *dum = container_of(gadget, struct dummy, gadget); -return dum->hs_hcd; +if (dum->gadget.speed ==USB_SPEED_SUPER ) +return dum->ss_hcd; +else +return dum->hs_hcd; }static inline struct dummy *gadget_dev_to_dummy (struct device *dev)@@ -266,10 +279,88 @@ stop_activity (struct dummy *dum)/* driver now does any non-usb quiescing necessary */ } +/** +* set_ss_link_state() - Sets the current state of the SuperSpeed link
drivers/usb/gadget/dummy_hcd.c stop_activity (struct dummy *dum) · line 293
Quoted 10 lines
drivers/usb/gadget/dummy_hcd.c +10
-0+* @dum_hcd: pointer to the dummy_hcd structure to update the link +* state for +* +* This function updates the port_status according to the link +* state. The old status is saved befor updating. +* Note: this function should be called only for SuperSpeed +* master and the caller must hold the lock. +*/ +static void +set_ss_link_state (struct dummy_hcd *dum_hcd)
a significant part of this function is similar to the USB2.0 version set_link_state(), so it's better to phase out the similar parts to an internal function and use that on both set_*_link_state(). Add something like:
__set_link_state_by_speed(struct dummy_hcd *dum_hcd, enum
usb_device_speed speed);
then do all the similar parts there copying for speed, then just call that function on both set_ss_link_state() and set_link_state().
drivers/usb/gadget/dummy_hcd.c stop_activity (struct dummy *dum) · line 295
Quoted 2 lines
drivers/usb/gadget/dummy_hcd.c +2
-0+{ +struct dummy *dum = dum_hcd->dum;
add a blank line here
drivers/usb/gadget/dummy_hcd.c stop_activity (struct dummy *dum) · line 296
Quoted 1 line
drivers/usb/gadget/dummy_hcd.c +1
-0+if (dum->gadget.speed <USB_SPEED_SUPER )
this assumes USB_SPEED_SUPER has an assigned value bigger than the others which might not be true if someone changes the order of the enumeration. So it's better to use:
if (dum->gadget.speed != USB_SPEED_SUPER)
drivers/usb/gadget/dummy_hcd.c stop_activity (struct dummy *dum) · line 300
Quoted 4 lines
drivers/usb/gadget/dummy_hcd.c +4
-0+return ; + dum_hcd->active =0 ; +if ((dum_hcd->port_status &USB_SS_PORT_STAT_POWER ) ==0 ) + dum_hcd->port_status =0 ;
if one branch has {} all of them should have :-) You can fix it while re-factoring this code.
Quoted 11 lines
drivers/usb/gadget/dummy_hcd.c +11
-0+/* UDC suspend must cause a disconnect */ + else if (!dum->pullup || dum->udc_suspended) { + dum_hcd->port_status &= ~(USB_PORT_STAT_CONNECTION | + USB_PORT_STAT_ENABLE); + if ((dum_hcd->old_status & USB_PORT_STAT_CONNECTION) != 0) + dum_hcd->port_status |= + (USB_PORT_STAT_C_CONNECTION << 16); + } else { +/* device is connected and not suspended */ + dum_hcd->port_status |= (USB_PORT_STAT_CONNECTION | +USB_PORT_STAT_SPEED_5GBPS ) ;
drivers/usb/gadget/dummy_hcd.c stop_activity (struct dummy *dum) · line 322
Quoted 10 lines
drivers/usb/gadget/dummy_hcd.c +10
-0+if ((dum_hcd->old_status &USB_PORT_STAT_CONNECTION ) ==0 ) + dum_hcd->port_status |= + (USB_PORT_STAT_C_CONNECTION <<16 ); +if ((dum_hcd->port_status &USB_PORT_STAT_ENABLE ) ==1 && + (dum_hcd->port_status &USB_SS_PORT_LS_U0 ) ==1 && + dum_hcd->rh_state !=DUMMY_RH_SUSPENDED ) + dum_hcd->active =1 ; + } + +
only one blank line :-)
drivers/usb/gadget/dummy_hcd.c stop_activity (struct dummy *dum) · line 331
Quoted 9 lines
drivers/usb/gadget/dummy_hcd.c +9
-0+if ((dum_hcd->port_status &USB_PORT_STAT_ENABLE ) ==0 || + dum_hcd->active) + dum_hcd->resuming =0 ; + +/* if !connected or reset */ +if ((dum_hcd->port_status &USB_PORT_STAT_CONNECTION ) ==0 || + (dum_hcd->port_status &USB_PORT_STAT_RESET ) !=0 ) { +/* +* We're connected and not reseted (reset occured now),
'reseted' isn't proper spelling :-)
Quoted 20 lines
drivers/usb/gadget/dummy_hcd.c +20
-0+* and driver attached - disconnect! +*/ +if ((dum_hcd->old_status &USB_PORT_STAT_CONNECTION ) !=0 && + (dum_hcd->old_status &USB_PORT_STAT_RESET ) ==0 && + dum->driver) { +stop_activity (dum); +spin_unlock (&dum->lock); + dum->driver->disconnect (&dum->gadget); +spin_lock (&dum->lock); + } + }else if (dum_hcd->active != dum_hcd->old_active) { +if (dum_hcd->old_active && dum->driver->suspend) { +spin_unlock (&dum->lock); + dum->driver->suspend (&dum->gadget); +spin_lock (&dum->lock); + }else if (!dum_hcd->old_active && dum->driver->resume) { +spin_unlock (&dum->lock); + dum->driver->resume (&dum->gadget); +spin_lock (&dum->lock); + }
drivers/usb/gadget/dummy_hcd.c stop_activity (struct dummy *dum) · line 361
Quoted 10 lines
drivers/usb/gadget/dummy_hcd.c +6
-0+ } + + dum_hcd->old_status = dum_hcd->port_status; + dum_hcd->old_active = dum_hcd->active; +} +/* caller must hold lock */ static void set_link_state (struct dummy_hcd *dum_hcd) {struct dummy *dum = dum_hcd->dum;
add a blank line here.
drivers/usb/gadget/dummy_hcd.c static void dummy_timer(unsigned long _dum_hcd) · line 1581
Quoted 6 lines
drivers/usb/gadget/dummy_hcd.c +2
-0@@ -1371,6 +1577,10 @@ static void dummy_timer(unsigned long _dum_hcd)case USB_SPEED_HIGH : total =512 /*bytes*/ *13 /*packets*/ *8 /*uframes*/ ;break ; +case USB_SPEED_SUPER : +/* Bus speed is 500000 bytes/ms, so use a little less */
isn't it 500000 bits/ms ?
Signature · 1 line
balbi
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi
Quoted 8 lines
Quoted 8 lines
(quoted diff) +0
-0
b/drivers/usb/gadget/dummy_hcd.cindex bf7981d..c2731d3 100644drivers/usb/gadget/dummy_hcd.c +0
-0@@ -70,6 +70,15 @@ MODULE_DESCRIPTION (DRIVER_DESC); MODULE_AUTHOR ("David Brownell" );MODULE_LICENSE ("GPL" );
Quoted 13 lines
drivers/usb/gadget/dummy_hcd.c MODULE_DESCRIPTION (DRIVER_DESC);
Quoted 10 lines
drivers/usb/gadget/dummy_hcd.c +10
-0+struct dummy_hcd_module_parameters { +bool is_super_speed; +}; + +static struct dummy_hcd_module_parameters mod_data = { + .is_super_speed = false +}; +module_param_named (is_super_speed, mod_data.is_super_speed, bool, +S_IRUGO); MODULE_PARM_DESC(is_super_speed, "true to simulate +SuperSpeed connection");you shouldn't need this. You should always enable SuperSpeed for this driver.
You mean I don't need the module parameter? IMO it's the best way to enable HS connection. If driver->speed=USB_SPEED_SUPER than dummy_hcd will try to enumerate the device on the SS root hub and if the gadget didn't provide SS descriptors - it will fail. Just as it happened before. Finding out from dummy_hcd that the enumeration failed is very complicated (if even possible) and I'm not sure that is the right thing to do... If you connect a real device over SS port to xHCI and the device doesn't provide SS descriptors - the enumeration fails and it's ok. But if you connect the same device to a HS port - it should work properly. This is what I tried to simulate with this parameter.
Regarding the default value set to false, this of course can be changed. I just thought that at the moment most of the existing gadget drivers don't have SS descriptors so their default operation mode is HS.
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi,
Quoted 21 lines · Tanya Brokhman
Quoted 7 lines
Quoted 7 lines
(quoted diff) +0
-0
b/drivers/usb/gadget/dummy_hcd.cindex bf7981d..c2731d3 100644drivers/usb/gadget/dummy_hcd.c +0
-0@@ -70,6 +70,15 @@ MODULE_DESCRIPTION (DRIVER_DESC); MODULE_AUTHOR ("David Brownell" );MODULE_LICENSE ("GPL" );Quoted 13 lines
drivers/usb/gadget/dummy_hcd.c MODULE_DESCRIPTION (DRIVER_DESC);
Quoted 10 lines
drivers/usb/gadget/dummy_hcd.c +10
-0+struct dummy_hcd_module_parameters { +bool is_super_speed; +}; + +static struct dummy_hcd_module_parameters mod_data = { + .is_super_speed = false +}; +module_param_named (is_super_speed, mod_data.is_super_speed, bool, +S_IRUGO); MODULE_PARM_DESC(is_super_speed, "true to simulate +SuperSpeed connection");you shouldn't need this. You should always enable SuperSpeed for this driver.
Quoted 4 lines
You mean I don't need the module parameter? IMO it's the best way to enable HS connection. If driver->speed=USB_SPEED_SUPER than
dummy_hcdwill try to enumerate the device on the SS root hub and if the gadget didn't provide SS descriptors - it will fail. Just as it happened before. Finding out from
then it should hand the device over to the hs_hcd ;-) Meaning it would disconnect the device, switch to hs_hcd and reconnect :-)
Quoted 6 lines
dummy_hcdthat the enumeration failed is very complicated (if even possible) and I'm not sure that is the right thing to do... If you connect a real device over SS port to xHCI and the device doesn't provide SS descriptors - the enumeration fails and it's ok. But if you connect the same device to a HS port - it should work properly. This is what I tried to simulate with this parameter.
it doesn't just fails, it gives the device over to the shared_hcd :-)
Signature · 1 line
balbi
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 12 lines
Quoted 5 lines
Quoted 5 lines
drivers/usb/gadget/dummy_hcd.c MODULE_DESCRIPTION (DRIVER_DESC);
Quoted 5 lines
drivers/usb/gadget/dummy_hcd.c +5
-0+ +static struct dummy_hcd_module_parameters mod_data = { + .is_super_speed = false +}; +module_param_named(is_super_speed, mod_data.is_super_speed,bool,
Quoted 6 lines
Quoted 5 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+S_IRUGO); MODULE_PARM_DESC(is_super_speed, "true to simulate +SuperSpeed connection");you shouldn't need this. You should always enable SuperSpeed for this driver.
Quoted 8 lines
Quoted 5 lines
You mean I don't need the module parameter? IMO it's the best way to enable HS connection. If driver->speed=USB_SPEED_SUPER than
dummy_hcdwill try to enumerate the device on the SS root hub and if the gadget didn't provide SS descriptors - it will fail. Just as it happened before. Finding out fromthen it should hand the device over to the
hs_hcd;-) Meaning it would disconnect the device, switch tohs_hcdand reconnect :-)
Yes this will be the best solution :) But as I said, the enumeration occurs not in dummy_hcd thus I'm not sure how dummy_hcd can find out that it failed in order to reconnect the device to hs_hcd. And I'm not sure that dummy_hcd should care whether the enumeration succeeds or fails. It seems to me that this should be handled by upper levels. Shouldn't it?
But we're discussing a more general issue; do you remember what the usb30 spec sais about this? I mean when connecting a HS device to a SS port (over SS cable), should it still enumerate as a HS device? It seems to me that the answer is no but I'm not sure...
Quoted 11 lines
Quoted 5 lines
dummy_hcdthat the enumeration failed is very complicated (if even possible) and I'm not sure that is the right thing to do... If you connect a real device over SS port to xHCI and the device doesn't provide SS descriptors - the enumeration fails and it's ok. But ifyou
Quoted 2 lines
connect the same device to a HS port - it should work properly. This is what I tried to simulate with this parameter.
it doesn't just fails, it gives the device over to the
shared_hcd:-)
Hmmm.... I have v2.6.38 installed on my Linux-host at the moment and I just verified that when connecting a Gadget driver without SS descriptors over SS connection - the enumeration fails. Was this fixed in v2.6.39? It will take me some time to upgrade to v2.6.39 and verify but I have to do it any way so I'll give it a shot...
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
hi,
Quoted 18 lines · Tanya Brokhman
Quoted 18 lines
Quoted 5 lines
Quoted 5 lines
drivers/usb/gadget/dummy_hcd.c MODULE_DESCRIPTION (DRIVER_DESC);
Quoted 5 lines
drivers/usb/gadget/dummy_hcd.c +5
-0+ +static struct dummy_hcd_module_parameters mod_data = { + .is_super_speed = false +}; +module_param_named(is_super_speed, mod_data.is_super_speed,bool,
Quoted 11 lines
Quoted 5 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+S_IRUGO); MODULE_PARM_DESC(is_super_speed, "true to simulate +SuperSpeed connection");you shouldn't need this. You should always enable SuperSpeed for this driver.
You mean I don't need the module parameter? IMO it's the best way to enable HS connection. If driver->speed=USB_SPEED_SUPER than
dummy_hcdwill try to enumerate the device on the SS root hub and if the gadget didn't provide SS descriptors - it will fail. Just as it happened before. Finding out from
Quoted 5 lines
Quoted 2 lines
then it should hand the device over to the
hs_hcd;-) Meaning it would disconnect the device, switch tohs_hcdand reconnect :-)Yes this will be the best solution :) But as I said, the enumeration occurs not in
dummy_hcdthus I'm not sure howdummy_hcdcan find out that it failed
take a look at xhci-ring.c for an example :-)
see that it check whether the attached device is a USB3.0 device or USB2.0/1.1 device and chooses hcd or shared_hcd accordingly.
Quoted 3 lines
in order to reconnect the device to
hs_hcd. And I'm not sure thatdummy_hcdshould care whether the enumeration succeeds or fails. It seems to me that this should be handled by upper levels. Shouldn't it?
nope. If dummy_hcd was a SW xhci implementation then it should be taken care by upper layers, but since this is a complete SW non-standard Host interface, then we need to handle the whole thing.
Quoted 2 lines
But we're discussing a more general issue; do you remember what the usb30 spec sais about this? I mean when connecting a HS device to a SS port (over
not the exact wording of the Specs but it should work :-)
Quoted 2 lines
SS cable), should it still enumerate as a HS device? It seems to me that the answer is no but I'm not sure...
the USB3 host shouldn't enumerate but it has the shared_hcd which is USB2.0 compliant.
Quoted 8 lines
Quoted 8 lines
Quoted 4 lines
dummy_hcdthat the enumeration failed is very complicated (if even possible) and I'm not sure that is the right thing to do... If you connect a real device over SS port to xHCI and the device doesn't provide SS descriptors - the enumeration fails and it's ok. But ifyou
Quoted 2 lines
connect the same device to a HS port - it should work properly. This is what I tried to simulate with this parameter.
Quoted 8 lines
Quoted 2 lines
it doesn't just fails, it gives the device over to the
shared_hcd:-)Hmmm.... I have v2.6.38 installed on my Linux-host at the moment and I just verified that when connecting a Gadget driver without SS descriptors over SS connection - the enumeration fails. Was this fixed in v2.6.39? It will take me some time to upgrade to v2.6.39 and verify but I have to do it any way so I'll give it a shot...
Maybe Sarah can give more details on this one. Sarah, what happens if we attach USB2.0 device to USB3.0 roothub ?
Signature · 1 line
balbi
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Quoted 6 lines
You mean I don't need the module parameter? IMO it's the best way to enable HS connection. If driver->speed=USB_SPEED_SUPER than
dummy_hcdwill try to enumerate the device on the SS root hub and if the gadget didn't provide SS descriptors - it will fail. Just as it happened before. Finding out fromthen it should hand the device over to the
hs_hcd;-) Meaning it would disconnect the device, switch tohs_hcdand reconnect :-)
Quoted 9 lines
Quoted 3 lines
Yes this will be the best solution :) But as I said, the enumeration occurs not in
dummy_hcdthus I'm not sure howdummy_hcdcan find out that it failedtake a look at
xhci-ring.cfor an example :-)see that it check whether the attached device is a USB3.0 device or USB2.0/1.1 device and chooses hcd or
shared_hcdaccordingly.
I ran some more tests with xhci and I think (or hope :) ) I figured this out:
When connecting a gadget driver that is marked as SS device (the flag CONFIG_USB_GADGET_IS_SUPER_SPEED = true) to a SS port over SS cable - the enumeration fails if that gadget driver doesn't provide SS descriptors.
BUT: if I connect the same device via HS cable to SS port - the enumeration is successful. I think that this is the case where xhci-ring handles the device over to the HS hcd :) (By the way, I think that in xhci the shared_hcd is SS and the main_hcd is HS)
In conclusion it seems to me that the device speed is determined by 2 things:
1. the cable used
2. whether the device HW supports SS protocol. In our scenario it can since SS support is enabled in our udc. (We haven't released it yet.) So when a HS device is connected to a SS port, the xHCI checks it's speed and if necessary handles it over to the SS root hub. But this is done prior to the enumeration phase so if the device speed is SS but it has no SS descriptors - the enumeration will fail. The enumeration itself occurs not in xhci but in hub.c so the xhci isn't aware of the fact that it failed and doesn't handle this.
Since in dummy_hcd all of this is much simpler I think that the device speed should be determined by driver->speed and "which type of cable the connection was made over - SS or HS". The "cable type" is exactly what the module parameter is.
My familiarity with the Linux host isn't as good as I would like it to be (still working on that) so I might be wrong with my conclusions...
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 22 lines · Tanya Brokhman
I ran some more tests with xhci and I think (or hope :) ) I figured this out:
When connecting a gadget driver that is marked as SS device (the flagCONFIG_USB_GADGET_IS_SUPER_SPEED= true) to a SS port over SS cable - the enumeration fails if that gadget driver doesn't provide SS descriptors.
BUT: if I connect the same device via HS cable to SS port - the enumeration is successful. I think that this is the case where xhci-ring handles the device over to the HS hcd :) (By the way, I think that in xhci theshared_hcdis SS and themain_hcdis HS)In conclusion it seems to me that the device speed is determined by 2 things:
1. the cable used
2. whether the device HW supports SS protocol. In our scenario it can since SS support is enabled in our udc. (We haven't released it yet.) So when a HS device is connected to a SS port, the xHCI checks it's speed and if necessary handles it over to the SS root hub. But this is done prior to the enumeration phase so if the device speed is SS but it has no SS descriptors - the enumeration will fail. The enumeration itself occurs not in xhci but inhub.cso the xhci isn't aware of the fact that it failed and doesn't handle this.
Quoted 7 lines
Since in
dummy_hcdall of this is much simpler I think that the device speed should be determined bydriver->speedand "which type of cable the connection was made over - SS or HS". The "cable type" is exactly what the module parameter is.My familiarity with the Linux host isn't as good as I would like it to be (still working on that) so I might be wrong with my conclusions...
Your analysis is basically correct.
Alan Stern
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
In reply to Tanya BrokhmanQuoted 22 lines · Tanya Brokhman
Hi
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Quoted 6 lines
You mean I don't need the module parameter? IMO it's the best way to enable HS connection. If driver->speed=USB_SPEED_SUPER than
dummy_hcdwill try to enumerate the device on the SS root hub and if the gadget didn't provide SS descriptors - it will fail. Just as it happened before. Finding out fromthen it should hand the device over to the
hs_hcd;-) Meaning it would disconnect the device, switch tohs_hcdand reconnect :-)Quoted 9 lines
Quoted 3 lines
Yes this will be the best solution :) But as I said, the enumeration occurs not in
dummy_hcdthus I'm not sure howdummy_hcdcan find out that it failedtake a look at
xhci-ring.cfor an example :-)see that it check whether the attached device is a USB3.0 device or USB2.0/1.1 device and chooses hcd or
shared_hcdaccordingly.
Quoted 5 lines
I ran some more tests with xhci and I think (or hope :) ) I figured this out:
When connecting a gadget driver that is marked as SS device (the flagCONFIG_USB_GADGET_IS_SUPER_SPEED= true) to a SS port over SS cable - the enumeration fails if that gadget driver doesn't provide SS descriptors.
If you're connecting as a SuperSpeed device, you need to have SuperSpeed descriptors. You definitely won't pass the USB-IF compliance test if you don't have those descriptors. :) You need to be able to automatically fall back to high speed with high speed descriptors when necessary.
Quoted 4 lines
BUT: if I connect the same device via HS cable to SS port - the enumeration is successful. I think that this is the case where xhci-ring handles the device over to the HS hcd :) (By the way, I think that in xhci the
shared_hcdis SS and themain_hcdis HS)
Yes, main_hcd is the high speed portion of the roothub. It's registered first, so that during a system resume, the HS roothub gets the devices reset first, and any USB 3.0 devices that had erroneously connected on USB 2.0 can migrate over to the SuperSpeed terminations. (If you are a USB 2.0 device that also has the ability to work at USB 3.0, you don't change speeds after USB 2.0 connection unless you get a reset.) We had to register the USB 2.0 roothub first so that USB 2.0 devices would get reset first, otherwise persistent storage might fail for USB 3.0 devices.
Quoted 3 lines
In conclusion it seems to me that the device speed is determined by 2 things:
1. the cable used
Not necessarily the cable used. You can have a SuperSpeed cable and have both host and device be SuperSpeed capable, but signal noise could cause the SuperSpeed enumeration to fail.
Quoted 2 lines
2. whether the device HW supports SS protocol. In our scenario it can since SS support is enabled in our udc. (We haven't released it yet.)
What is a UDC?
Quoted 6 lines
So when a HS device is connected to a SS port, the xHCI checks it's speed and if necessary handles it over to the SS root hub. But this is done prior to the enumeration phase so if the device speed is SS but it has no SS descriptors - the enumeration will fail. The enumeration itself occurs not in xhci but in
hub.cso the xhci isn't aware of the fact that it failed and doesn't handle this.
The USB core might try to disable the device in that case, and the xHCI driver would see that.
Quoted 4 lines
Since in
dummy_hcdall of this is much simpler I think that the device speed should be determined bydriver->speedand "which type of cable the connection was made over - SS or HS". The "cable type" is exactly what the module parameter is.
I really don't understand this. You're going to have a module parameter for what type of cable is plugged in? How can you tell which one the user is going to use? What about the case where SuperSpeed enumeration fails and you have to fall back to high speed? It seems like you really need to handle both speeds and the speed fall back parameter in the same driver. Isn't there some other gadget driver that has a fall back to full or low speed when high speed enumeration fails?
Sarah Sharp
--
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
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 4 lines · Sarah Sharp
Quoted 2 lines
2. whether the device HW supports SS protocol. In our scenario it can since SS support is enabled in our udc. (We haven't released it yet.)
What is a UDC?
USB Device Controller. It's the device-side analog of a host controller.
Quoted 7 lines
Quoted 4 lines
Since in
dummy_hcdall of this is much simpler I think that the device speed should be determined bydriver->speedand "which type of cable the connection was made over - SS or HS". The "cable type" is exactly what the module parameter is.I really don't understand this. You're going to have a module parameter for what type of cable is plugged in?
It would be more accurate to say the module parameter will be used to force the connection to run at a lower speed than the maximum possible. This is kind of like what happens when you plug in a SuperSpeed device using a USB-2 cable -- the connection runs at a lower speed than it could have.
Quoted 2 lines
How can you tell which one the
user is going to use?
This isn't about actual cables or devices. dummy-hcd is an emulator; it presents as a host controller and a device controller both on the same system. This allows people to test gadget drivers without having any UDC hardware.
Quoted 2 lines
What about the case where SuperSpeed enumeration
fails and you have to fall back to high speed?
If SuperSpeed enumeration fails, say because the device doesn't have any SuperSpeed descriptors, xhci-hcd doesn't fall back to high speed, does it? dummy-hcd should behave the same way.
Quoted 4 lines
It seems like you really
need to handle both speeds and the speed fall back parameter in the same driver. Isn't there some other gadget driver that has a fall back to full or low speed when high speed enumeration fails?
That's a property of the gadget driver, not the UDC driver. dummy-hcd is a UDC driver (and an HCD too).
Alan Stern
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi,
(replying from another PC, not sure if formatting
will be broken, hopefully not)
Quoted 5 lines · Alan Stern
Quoted 5 lines
Quoted 4 lines
Since in
dummy_hcdall of this is much simpler I think that the device speed should be determined bydriver->speedand "which type of cable the connection was made over - SS or HS". The "cable type" is exactly what the module parameter is.
Quoted 8 lines
Quoted 2 lines
I really don't understand this. You're going to have a module parameter for what type of cable is plugged in?
It would be more accurate to say the module parameter will be used to force the connection to run at a lower speed than the maximum possible. This is kind of like what happens when you plug in a SuperSpeed device using a USB-2 cable -- the connection runs at a lower speed than it could have.
if it's something like that, for sure we can have the module parameter. But plugging a USB2 gadget/function to a USB3-capable UDC/HCD should work fine.
With Tatyana's patches, if we load a USB2 g_zero to dummy_hcd, enumeration will fail where it shouldn't. This has been my whole point ;-) Maybe I wasn't clear enough.
Quoted 6 lines
Quoted 2 lines
What about the case where SuperSpeed enumeration
fails and you have to fall back to high speed?If SuperSpeed enumeration fails, say because the device doesn't have any SuperSpeed descriptors, xhci-hcd doesn't fall back to high speed, does it? dummy-hcd should behave the same way.
it should at least. Isn't that what happens between EHCI/OHCI ? HS Chirp sequencing fails, then we fall back to FullSpeed.
Quoted 7 lines
Quoted 4 lines
It seems like you really
need to handle both speeds and the speed fall back parameter in the same driver. Isn't there some other gadget driver that has a fall back to full or low speed when high speed enumeration fails?That's a property of the gadget driver, not the UDC driver. dummy-hcd is a UDC driver (and an HCD too).
USB3.0 dummy_hcd should still enumerate USB2.0 gadget drivers.
Signature · 1 line
balbi
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 6 lines · Felipe Balbi
Quoted 5 lines
It would be more accurate to say the module parameter will be used to force the connection to run at a lower speed than the maximum possible. This is kind of like what happens when you plug in a SuperSpeed device using a USB-2 cable -- the connection runs at a lower speed than it could have.
Quoted 7 lines
if it's something like that, for sure we can have the module parameter. But plugging a USB2 gadget/function to a USB3-capable UDC/HCD should work fine.
With Tatyana's patches, if we load a USB2
g_zerotodummy_hcd, enumeration will fail where it shouldn't. This has been my whole point ;-) Maybe I wasn't clear enough.
I guess not. I thought Tatyana said she was working to fix that bug...
Quoted 9 lines
Quoted 6 lines
Quoted 2 lines
What about the case where SuperSpeed enumeration
fails and you have to fall back to high speed?If SuperSpeed enumeration fails, say because the device doesn't have any SuperSpeed descriptors, xhci-hcd doesn't fall back to high speed, does it? dummy-hcd should behave the same way.
it should at least. Isn't that what happens between EHCI/OHCI ? HS Chirp sequencing fails, then we fall back to FullSpeed.
That's a failure in initialization, not a failure in enumeration.
There are two reasons why the HS chirp might fail: the device doesn't support high speed operation or hardware errors prevent the chirp from working. With dummy-hcd there are no hardware errors (because there's no hardware).
As for whether or not the device supports high-speed or SuperSpeed operation, that's determined by the usb_gadget_driver->speed field. If the field doesn't specify SuperSpeed then dummy-hcd should connect the gadget to the USB-2 root hub rather than the USB-3 root hub. Isn't that what Tatyana's patch does? It contains a line saying:
dum->gadget.speed = driver->speed;
Quoted 9 lines
Quoted 7 lines
Quoted 4 lines
It seems like you really
need to handle both speeds and the speed fall back parameter in the same driver. Isn't there some other gadget driver that has a fall back to full or low speed when high speed enumeration fails?That's a property of the gadget driver, not the UDC driver. dummy-hcd is a UDC driver (and an HCD too).
USB3.0
dummy_hcdshould still enumerate USB2.0 gadget drivers.
Yes, certainly it should. If it doesn't, that's a bug, not a design error.
Alan Stern
--
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
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 8 lines
Quoted 2 lines
With Tatyana's patches, if we load a USB2
g_zerotodummy_hcd,enumeration
Quoted 1 line
will fail where it shouldn't. This has been my whole point ;-) Maybe
I wasn't
Quoted 1 line
clear enough.
I guess not. I thought Tatyana said she was working to fix that bug...
This bug is fixed with the module parameter. When dummy_hcd is loaded it registers 2 root hubs: HS & SS but unless the is_super_speed parameter is true, the device will be connected to the HS hub. This way when loading HS g_zero it enumerates under HS root hub successfully.
Note that if load SS gadget without setting is_super_speed=true for dummy hcd, it will also enumerate under HS hub! This is basically a way to test that SS devices are backward compatible.
Quoted 20 lines
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines
What about the case where SuperSpeed enumeration
fails and you have to fall back to high speed?If SuperSpeed enumeration fails, say because the device doesn't
have
Quoted 1 line
Quoted 1 line
any SuperSpeed descriptors, xhci-hcd doesn't fall back to high
speed,
Quoted 3 lines
Quoted 1 line
does it? dummy-hcd should behave the same way.
it should at least. Isn't that what happens between EHCI/OHCI ? HS
Chirp
Quoted 1 line
sequencing fails, then we fall back to FullSpeed.
That's a failure in initialization, not a failure in enumeration.
There are two reasons why the HS chirp might fail: the device doesn't support high speed operation or hardware errors prevent the chirp from working. With dummy-hcd there are no hardware errors (because there's no hardware).
Quoted 7 lines
As for whether or not the device supports high-speed or SuperSpeed operation, that's determined by the
usb_gadget_driver->speedfield. If the field doesn't specify SuperSpeed then dummy-hcd should connect the gadget to the USB-2 root hub rather than the USB-3 root hub. Isn't that what Tatyana's patch does? It contains a line saying:dum->gadget.speed = driver->speed;
You're right. This is exactly what is done with a small update: if is_super_speed=false the gadget will connect to a USB2 root hub even if driver->speed=USB_SPEED_SUPER. In that case dum->gadget.speed will be set to USB_SPEED_HIGH. The code that sets this now is:
if (mod_data.is_super_speed) dum->gadget.speed = driver->speed; else dum->gadget.speed = min((u8)USB_SPEED_HIGH, (u8)driver->speed); if (dum->gadget.speed < driver->speed) dev_dbg(udc_dev(dum), "This device can perform faster if" " you connect it to a " "SupeSpeed port...\n");
Quoted 7 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
It seems like you really
need to handle both speeds and the speed fall back parameter inthe same
Quoted 1 line
Quoted 1 line
Quoted 1 line
driver. Isn't there some other gadget driver that has a fall back
to
Quoted 2 lines
Quoted 2 lines
Quoted 1 line
full or low speed when high speed enumeration fails?
Quoted 9 lines
Quoted 1 line
Quoted 1 line
That's a property of the gadget driver, not the UDC driver. dummy-
hcd
Quoted 3 lines
Quoted 1 line
is a UDC driver (and an HCD too).
USB3.0
dummy_hcdshould still enumerate USB2.0 gadget drivers.Yes, certainly it should. If it doesn't, that's a bug, not a design error.
This version of dummy_hcd enumerates HS devices without any issues.
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi,
Quoted 9 lines · Tanya Brokhman
Quoted 8 lines
Quoted 2 lines
With Tatyana's patches, if we load a USB2
g_zerotodummy_hcd,enumeration
Quoted 1 line
will fail where it shouldn't. This has been my whole point ;-) Maybe
I wasn't
Quoted 1 line
clear enough.
I guess not. I thought Tatyana said she was working to fix that bug...
Quoted 7 lines
This bug is fixed with the module parameter. When
dummy_hcdis loaded it registers 2 root hubs: HS & SS but unless theis_super_speedparameter is true, the device will be connected to the HS hub. This way when loading HSg_zeroit enumerates under HS root hub successfully.
Note that if load SS gadget without setting is_super_speed=true for dummy hcd, it will also enumerate under HS hub! This is basically a way to test that SS devices are backward compatible.
but you also need to make sure that HS gadget enumerates on SS host. I don't agree that the module parameter is the only option.
Quoted 28 lines
Quoted 20 lines
Quoted 4 lines
Quoted 4 lines
Quoted 2 lines
What about the case where SuperSpeed enumeration
fails and you have to fall back to high speed?If SuperSpeed enumeration fails, say because the device doesn't
have
Quoted 1 line
Quoted 1 line
any SuperSpeed descriptors, xhci-hcd doesn't fall back to high
speed,
Quoted 3 lines
Quoted 1 line
does it? dummy-hcd should behave the same way.
it should at least. Isn't that what happens between EHCI/OHCI ? HS
Chirp
Quoted 1 line
sequencing fails, then we fall back to FullSpeed.
That's a failure in initialization, not a failure in enumeration.
There are two reasons why the HS chirp might fail: the device doesn't support high speed operation or hardware errors prevent the chirp from working. With dummy-hcd there are no hardware errors (because there's no hardware).
Quoted 7 lines
As for whether or not the device supports high-speed or SuperSpeed operation, that's determined by the
usb_gadget_driver->speedfield. If the field doesn't specify SuperSpeed then dummy-hcd should connect the gadget to the USB-2 root hub rather than the USB-3 root hub. Isn't that what Tatyana's patch does? It contains a line saying:dum->gadget.speed = driver->speed;
Quoted 8 lines
You're right. This is exactly what is done with a small update: if is_super_speed=false the gadget will connect to a USB2 root hub even if driver->speed=USB_SPEED_SUPER. In that case
dum->gadget.speedwill be set toUSB_SPEED_HIGH. The code that sets this now is:if (mod_data.is_super_speed) dum->gadget.speed = driver->speed; else dum->gadget.speed = min((u8)USB_SPEED_HIGH,
ok ok, I took a closer look at the original patches and you're changing drivers->speed to super before converting the gadget drivers to superspeed. That's what's making enumeration fail on all those guys.
Quoted 11 lines
Quoted 11 lines
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
It seems like you really
need to handle both speeds and the speed fall back parameter inthe same
Quoted 1 line
Quoted 1 line
Quoted 1 line
driver. Isn't there some other gadget driver that has a fall back
to
Quoted 3 lines
Quoted 3 lines
Quoted 1 line
full or low speed when high speed enumeration fails?
That's a property of the gadget driver, not the UDC driver. dummy-
hcd
Quoted 2 lines
Quoted 1 line
is a UDC driver (and an HCD too).
Quoted 7 lines
Quoted 5 lines
Quoted 1 line
USB3.0
dummy_hcdshould still enumerate USB2.0 gadget drivers.Yes, certainly it should. If it doesn't, that's a bug, not a design error.
This version of
dummy_hcdenumerates HS devices without any issues.
that's not what I saw, but then again, maybe you changed driver->speed to super and didn't provide superspeed descriptors.
Signature · 1 line
balbi
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi Felipe
Quoted 4 lines
Quoted 2 lines
This version of
dummy_hcdenumerates HS devices without any issues.that's not what I saw,
By "this version" I mean v12 and the one I just emailed, v13. Did you try them out? I did and all worked just fine...
Quoted 3 lines
but then again, maybe you changed
driver->speedto super and didn't provide superspeed descriptors.
Yes :) The driver->speed is updated in usb_composite_probe() if CONFIG_USB_GADGET_SUPERSPEED is defined.
So, are we ok with this solution? The module parameter I mean? Are you going to try the v13 in your branch? Please let me know how it goes and of course if you have any comments.
Thanks!
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi,
Quoted 10 lines · Tanya Brokhman
Quoted 3 lines
but then again, maybe you changed
driver->speedto super and didn't provide superspeed descriptors.Yes :) The
driver->speedis updated inusb_composite_probe()ifCONFIG_USB_GADGET_SUPERSPEEDis defined.So, are we ok with this solution? The module parameter I mean? Are you going to try the v13 in your branch? Please let me know how it goes and of course if you have any comments.
I think it still gives the possibility for failure. I would rather not take that until all gadget drivers are fixed. We can help you doing that and we only change driver->speed after all gadget drivers have their "sensible defaults" SuperSpeed descriptors.
What do you say ? Other than that, the module parameter is, like Alan Said, useful for debugging, so we might as well keep it.
Signature · 1 line
balbi
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi Felipe
Quoted 5 lines
Quoted 5 lines
Yes :) The
driver->speedis updated inusb_composite_probe()ifCONFIG_USB_GADGET_SUPERSPEEDis defined.So, are we ok with this solution? The module parameter I mean? Are you going to try the v13 in your branch? Please let me know how
Quoted 7 lines
it
Quoted 1 line
goes and of course if you have any comments.
I think it still gives the possibility for failure. I would rather not take that until all gadget drivers are fixed. We can help you doing that and we only change
driver->speedafter all gadget drivers have their "sensible defaults" SuperSpeed descriptors.
By "until all gadget drivers are fixed" you mean until all gadget drivers provide SS descriptors? This will take for ever...
I wasn't about to modify all gadget drivers and to add SS descriptors for them. I can add default values (as generate_ss_descriptors() did if you remember) but I don't think this is the right approach because as you said - different gadget drivers might have different SS descriptors and I don't feel confident enough to set these values. Nor do I have the ability to test each of the gadget drivers the way I would like to after this change. The only gadget driver I felt confident adding SS descriptors for is UASP, which I tested properly.
Actually if the CONFIG_USB_GADGET_SUPERSPEED is turned off, which is the default of it, the speed won't be updated and all these series won't be functional so I don't see any possibilities for failure in such configuration. Or am I missing something?
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 26 lines · Tanya Brokhman
Hi Felipe
Quoted 5 lines
Quoted 5 lines
Yes :) The
driver->speedis updated inusb_composite_probe()ifCONFIG_USB_GADGET_SUPERSPEEDis defined.So, are we ok with this solution? The module parameter I mean? Are you going to try the v13 in your branch? Please let me know how
Quoted 7 lines
it
Quoted 1 line
goes and of course if you have any comments.
I think it still gives the possibility for failure. I would rather not take that until all gadget drivers are fixed. We can help you doing that and we only change
driver->speedafter all gadget drivers have their "sensible defaults" SuperSpeed descriptors.By "until all gadget drivers are fixed" you mean until all gadget drivers provide SS descriptors? This will take for ever...
I wasn't about to modify all gadget drivers and to add SS descriptors for them. I can add default values (asgenerate_ss_descriptors()did if you remember) but I don't think this is the right approach because as you said - different gadget drivers might have different SS descriptors and I don't feel confident enough to set these values. Nor do I have the ability to test each of the gadget drivers the way I would like to after this change. The only gadget driver I felt confident adding SS descriptors for is UASP, which I tested properly.
Quoted 4 lines
Actually if the
CONFIG_USB_GADGET_SUPERSPEEDis turned off, which is the default of it, the speed won't be updated and all these series won't be functional so I don't see any possibilities for failure in such configuration. Or am I missing something?
dummy_hcd should work when CONFIG_USB_GADGET_SUPERSPEED is enabled, even if the usb_gadget_driver structure is initialized with the speed field set to USB_SPEED_HIGH. This will be true for all the standalone gadget drivers until they are updated.
Which leaves a question about the composite gadget framework. Should it be updated with SS support? Probably not until the various function drivers have all been updated.
Alan Stern
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 4 lines
Quoted 2 lines
Actually if the
CONFIG_USB_GADGET_SUPERSPEEDis turned off, which isthe
Quoted 1 line
default of it, the speed won't be updated and all these series won't
Quoted 8 lines
be
Quoted 2 lines
functional so I don't see any possibilities for failure in such configuration. Or am I missing something?
dummy_hcdshould work whenCONFIG_USB_GADGET_SUPERSPEEDis enabled, even if theusb_gadget_driverstructure is initialized with the speed field set toUSB_SPEED_HIGH. This will be true for all the standalone gadget drivers until they are updated.
It does.
Quoted 4 lines
Which leaves a question about the composite gadget framework. Should it be updated with SS support? Probably not until the various function drivers have all been updated.
As I mentioned, updating all of the gadget drivers will take a long time and I don't fill confident enough doing since I'm not familiar with all of them and don't have the ability to test each of them properly. I can add SS descriptors to f_mass_storage, g_zero if it helps and of course f_uasp already has them.
I'm a bit confused by this actually... We've been discussing this patch series for quite a while now and I got the impression that except for some minor comments you were all for excepting this. Was I wrong or am I misunderstanding the above?
In any case, I don't feel that adding SS support for the Gadget framework should be delayed until all gadget drivers add SS descriptors because this patch series will give the developers the ability to test these gadget drivers at SS. Also, several developers addressed me offline with questions on this series so I know people are using it in their work. And of course we do :)
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi,
Quoted 4 lines · Tanya Brokhman
Quoted 3 lines
Which leaves a question about the composite gadget framework. Should it be updated with SS support? Probably not until the various function drivers have all been updated.
Quoted 15 lines
As I mentioned, updating all of the gadget drivers will take a long time and I don't fill confident enough doing since I'm not familiar with all of them and don't have the ability to test each of them properly. I can add SS descriptors to
f_mass_storage,g_zeroif it helps and of coursef_uaspalready has them.
I'm a bit confused by this actually... We've been discussing this patch series for quite a while now and I got the impression that except for some minor comments you were all for excepting this. Was I wrong or am I misunderstanding the above?
In any case, I don't feel that adding SS support for the Gadget framework should be delayed until all gadget drivers add SS descriptors because this patch series will give the developers the ability to test these gadget drivers at SS. Also, several developers addressed me offline with questions on this series so I know people are using it in their work. And of course we do :)
just remove the hunk which changes composite.c speed field and it should all be ok :-)
Signature · 1 line
balbi
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 16 lines
Quoted 7 lines
As I mentioned, updating all of the gadget drivers will take a long time and I don't fill confident enough doing since I'm not familiar with all of them and don't have the ability to test each of them properly. I can add SS descriptors to
f_mass_storage,g_zeroif it helps and of coursef_uaspalready has them.
I'm a bit confused by this actually... We've been discussing this patch series for quite a while now and I got the impression thatQuoted 8 lines
except for some minor comments you were all for excepting this. Was I wrong or am I misunderstanding the above?
In any case, I don't feel that adding SS support for the Gadget framework should be delayed until all gadget drivers add SS descriptors because this patch series will give the developers the ability to test these gadget drivers at SS. Also, several developers addressed me offline with questions on this series so I know people are using it in their work. And of course we do :)
Quoted 3 lines
just remove the hunk which changes
composite.cspeed field and it should all be ok :-)
But that's why we added the feature flag. Isn't leaving it FALSE the same as removing the part that updates gadget speed? It is protected with #ifdef.
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 16 lines · Tanya Brokhman
Quoted 16 lines
Quoted 15 lines
As I mentioned, updating all of the gadget drivers will take a long time and I don't fill confident enough doing since I'm not familiar with all of them and don't have the ability to test each of them properly. I can add SS descriptors to
f_mass_storage,g_zeroif it helps and of coursef_uaspalready has them.
I'm a bit confused by this actually... We've been discussing this patch series for quite a while now and I got the impression that except for some minor comments you were all for excepting this. Was I wrong or am I misunderstanding the above?
In any case, I don't feel that adding SS support for the Gadget framework should be delayed until all gadget drivers add SS descriptors because this patch series will give the developers the ability to test these gadget drivers at SS. Also, several developers addressed me offline with questions on this series so I know people are using it in their work. And of course we do :)
Quoted 6 lines
Quoted 3 lines
just remove the hunk which changes
composite.cspeed field and it should all be ok :-)But that's why we added the feature flag. Isn't leaving it FALSE the same as removing the part that updates gadget speed? It is protected with #ifdef.
you mean the module parameter ? This will mean that users will have to remember another module parameter otherwise it will not work in some situations :-)
the module should work without that parameter :-)
Signature · 1 line
balbi
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 10 lines
Quoted 2 lines
But that's why we added the feature flag. Isn't leaving it FALSE the same as removing the part that updates gadget speed? It is protected
with #ifdef.
you mean the module parameter ? This will mean that users will have to remember another module parameter otherwise it will not work in some situations :-)
the module should work without that parameter :-)
No, I'm afraid we're talking about different things here.
As far as dummy_hcd is concerned:Dummy_hcd has a new module parameter that should be set to true if the developer wishes the gadget driver to be connected to a SS root hub. Since at the moment most of the gadget drivers woun't work at SS connection (lack of SS descriptors) the default of this parameter is true and thus the connected gadget driver will be enumerated over a HS root hub. Users don't have to remember t set anything in order to be able to work with dummy_hcd and the existing gadget drivers just as they did up until now.
We did add a new feature flag (CONFIG_USB_GADGET_SUPERSPEED) that is set during compilation. If that flag is defined, then (and only then!) will the driver->speed be set to SS by composite_bind. Please keep in mind the following:
1. if CONFIG_USB_GADGET_SUPERSPEED=true, existing gadget drivers are still functional with dummy_hcd since as I already mentioned, they will be enumerated through HS root hub and thus the gadget.speed will be set to HS. This is true for all gadget drivers, including the once that don't define SS descriptors.
2. if CONFIG_USB_GADGET_SUPERSPEED=false (which is the default) then all the code that is added by this patch series will never be executed since driver->speed won't be updated (and will remain HS). This is basically a way to disable SS support in the gadget framework.
Hope this clears the confusion :)
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi,
Quoted 21 lines · Tanya Brokhman
Quoted 10 lines
Quoted 2 lines
But that's why we added the feature flag. Isn't leaving it FALSE the same as removing the part that updates gadget speed? It is protected
with #ifdef.
you mean the module parameter ? This will mean that users will have to remember another module parameter otherwise it will not work in some situations :-)
the module should work without that parameter :-)
No, I'm afraid we're talking about different things here.
As far asdummy_hcdis concerned:Dummy_hcdhas a new module parameter that should be set to true if the developer wishes the gadget driver to be connected to a SS root hub. Since at the moment most of the gadget drivers woun't work at SS connection (lack of SS descriptors) the default of this parameter is true and thus the connected gadget driver will be enumerated over a HS root hub. Users don't have to remember t set anything in order to be able to work withdummy_hcdand the existing gadget drivers just as they did up until now.
Quoted 3 lines
We did add a new feature flag (
CONFIG_USB_GADGET_SUPERSPEED) that is set during compilation. If that flag is defined, then (and only then!) will thedriver->speedbe set to SS bycomposite_bind. Please keep in mind the
and that's the only thing I'm asking you to remove :-)
we should be to compile dummy_hcd in SuperSpeed and still have high-speed gadget drivers :-)
Quoted 6 lines
following:
1. ifCONFIG_USB_GADGET_SUPERSPEED=true, existing gadget drivers are still functional withdummy_hcdsince as I already mentioned, they will be enumerated through HS root hub and thus the gadget.speed will be set to HS. This is true for all gadget drivers, including the once that don't define SS descriptors.
only due the module parameter, right ?
Signature · 1 line
balbi
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi Felipe,
Quoted 14 lines
Quoted 4 lines
No, I'm afraid we're talking about different things here. As far as
dummy_hcdis concerned:Dummy_hcdhas a new module parameter that should be set to true ifthe
Quoted 4 lines
developer wishes the gadget driver to be connected to a SS root hub. Since at the moment most of the gadget drivers woun't work at SS connection (lack of SS descriptors) the default of this parameter is true and thus the connected gadget driver will be enumerated over a
HS
Quoted 2 lines
root hub. Users don't have to remember t set anything in order to be able to work with
dummy_hcdand the existing gadget drivers just asthey did up until now.
Quoted 1 line
Quoted 7 lines
Quoted 2 lines
We did add a new feature flag (
CONFIG_USB_GADGET_SUPERSPEED) that is set during compilation. If that flag is defined, then (and onlythen!)
Quoted 2 lines
will the
driver->speedbe set to SS bycomposite_bind. Please keep in mind theand that's the only thing I'm asking you to remove :-)
You want to remove the following change from in composite.c:
@@ -1386,6 +1604,9 @@ int usb_composite_probe(struct usb_composite_driver *driver,
driver->iProduct = driver->name;
composite_driver.function = (char *) driver->name; composite_driver.driver.name = driver->name;
+#ifdef CONFIG_USB_GADGET_SUPERSPEED
+ composite_driver.speed = USB_SPEED_SUPER; #endif /*
+CONFIG_USB_GADGET_SUPERSPEED */
composite = driver;
composite_gadget_bind = bind;
Right? I'm sorry, but I really don't understand why... :( Removing it is the same as not defining CONFIG_USB_GADGET_SUPERSPEED.
And if we do remove it: suppose you do have a SS gadget driver you wish to test now with dummy_hcd. For example the f_uasp we released. In order to be able to do so, you'll have to add the above manually in your repository. Otherwise even if the dummy_hcd module parameter is_super_speed=true - the gadget will enumerate over HS root hub since the driver speed will remain HS.
Quoted 3 lines
we should be to compile
dummy_hcdin SuperSpeed and still have high- speed gadget drivers :-)
But this is the case right now. Or do you mean that you want to load (not compile) the dummy_hcd with is_super_speed=1 and still be able to enumerate HS gadgets?
Quoted 9 lines
Quoted 4 lines
following:
1. ifCONFIG_USB_GADGET_SUPERSPEED=true, existing gadget drivers are still functional withdummy_hcdsince as I already mentioned, they will be enumerated through HS root hub and thus the gadget.speed willbe set to HS.
Quoted 2 lines
This is true for all gadget drivers, including the once that don't define SS descriptors.
only due the module parameter, right ?
Due to the module parameter default value being FALSE, yes.
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi,
Quoted 34 lines · Tanya Brokhman
Quoted 13 lines
Quoted 3 lines
No, I'm afraid we're talking about different things here. As far as
dummy_hcdis concerned:Dummy_hcdhas a new module parameter that should be set to true ifthe
Quoted 4 lines
developer wishes the gadget driver to be connected to a SS root hub. Since at the moment most of the gadget drivers woun't work at SS connection (lack of SS descriptors) the default of this parameter is true and thus the connected gadget driver will be enumerated over a
HS
Quoted 2 lines
root hub. Users don't have to remember t set anything in order to be able to work with
dummy_hcdand the existing gadget drivers just asthey did up until now.
Quoted 1 line
Quoted 7 lines
Quoted 2 lines
We did add a new feature flag (
CONFIG_USB_GADGET_SUPERSPEED) that is set during compilation. If that flag is defined, then (and onlythen!)
Quoted 2 lines
will the
driver->speedbe set to SS bycomposite_bind. Please keep in mind theand that's the only thing I'm asking you to remove :-)
You want to remove the following change from in
composite.c:(quoted diff) +3
-0@@ -1386,6 +1604,9 @@ int usb_composite_probe(struct usb_composite_driver *driver, driver->iProduct = driver->name; composite_driver.function = (char *) driver->name; composite_driver.driver.name = driver->name; +#ifdef CONFIG_USB_GADGET_SUPERSPEED + composite_driver.speed = USB_SPEED_SUPER; #endif /* +CONFIG_USB_GADGET_SUPERSPEED */ composite = driver; composite_gadget_bind = bind;
Quoted 2 lines
Right? I'm sorry, but I really don't understand why... :( Removing it is the same as not defining
CONFIG_USB_GADGET_SUPERSPEED.
we still want to build a SuperSpeed dummy_hcd but have HS gadget drivers :-)
Quoted 6 lines
Quoted 2 lines
we should be to compile
dummy_hcdin SuperSpeed and still have high- speed gadget drivers :-)But this is the case right now. Or do you mean that you want to load (not compile) the
dummy_hcdwith is_super_speed=1 and still be able to enumerate HS gadgets?
that too.
Quoted 11 lines
Quoted 9 lines
Quoted 4 lines
following:
1. ifCONFIG_USB_GADGET_SUPERSPEED=true, existing gadget drivers are still functional withdummy_hcdsince as I already mentioned, they will be enumerated through HS root hub and thus the gadget.speed willbe set to HS.
Quoted 2 lines
This is true for all gadget drivers, including the once that don't define SS descriptors.
only due the module parameter, right ?
Due to the module parameter default value being FALSE, yes.
Ok, so let's take your approach but change the speed in the gadget driver structure, put your ifdef somewhere like here:
drivers/usb/gadget/composite.c +4 -0
@@ -1224,7 +1224,11 @@ composite_resume(struct usb_gadget *gadget)/*-------------------------------------------------------------------------*/ static struct usb_gadget_driver composite_driver = { +#ifdef CONFIG_USB_GADGET_SUPERSPEED + .speed =USB_SPEE_SUPER , +#else .speed =USB_SPEED_HIGH , +#endif .unbind = composite_unbind,
Signature · 1 line
balbi
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi Felipe,
Quoted 14 lines
Quoted 14 lines
You want to remove the following change from in
composite.c:(quoted diff) +3
-0@@ -1386,6 +1604,9 @@ int usb_composite_probe(struct usb_composite_driver *driver, driver->iProduct = driver->name; composite_driver.function = (char *) driver->name; composite_driver.driver.name = driver->name; +#ifdef CONFIG_USB_GADGET_SUPERSPEED + composite_driver.speed = USB_SPEED_SUPER; #endif /* +CONFIG_USB_GADGET_SUPERSPEED */ composite = driver; composite_gadget_bind = bind;
Quoted 6 lines
Quoted 2 lines
Right? I'm sorry, but I really don't understand why... :( Removing it is the same as not defining
CONFIG_USB_GADGET_SUPERSPEED.we still want to build a SuperSpeed
dummy_hcdbut have HS gadget drivers
:-)
But we do! I'm sorry, I'm getting a bit frustrated from not understanding what bothers you here...
The above change in usb_composite_probe() doesn't prevent HS gadgets from working with SS dummy_hcd.
Here is an example of the tests I ran on this patch series:
In my build CONFIG_USB_GADGET_SUPERSPEED=true so composite_driver.speed = USBSPEED_SUPER.
1)
$> modprobe g_zeroG_zero was enumerated over HS root hub as a HS device. I ran our HS test suite (from the UT framework) to test its functionality. It includes (HS) descriptors verification, connect/disconnect and bulk in/out tests.
2)
$> modprobe dummy_hcd is_super_speed=1
$> modprobe g_zero
In this case the enumeration fails since g_zero didn't provide SS descriptors!
I prepared another build, in which I used our generate_ss_descriptors() to automaticly generate SS descriptors for g_zero gadget. CONFIG_USB_GADGET_SUPERSPEED is still true:
3)
$> modprobe g_zeroG_zero was enumerated over HS root hub as a HS device although it has SS descriptors. All HS UT that I described above passed
4)
$> modprobe dummy_hcd is_super_speed=1
$> modprobe g_zeroG_zero enumerated over SS root hub as a SS device. I verified that it's functional with the SS test suite. It also verifies (SS) descriptors, connect/disconnect and bulk in/out tests.
Please give me an example of what WOUN'T work with the above change.
Quoted 11 lines
Quoted 2 lines
Quoted 2 lines
we should be to compile
dummy_hcdin SuperSpeed and still havehigh-
Quoted 6 lines
Quoted 1 line
speed gadget drivers :-)
But this is the case right now. Or do you mean that you want to load (not
compile) thedummy_hcdwith is_super_speed=1 and still be able to enumerate HS gadgets?that too.
Well you can if at compile time you don't set CONFIG_USB_GADGET_SUPERSPEED to true.
Quoted 25 lines
Quoted 8 lines
Quoted 8 lines
Quoted 6 lines
following:
1. ifCONFIG_USB_GADGET_SUPERSPEED=true, existing gadget drivers are still functional withdummy_hcdsince as I already mentioned, they will be enumerated through HS root hub and thus the gadget.speed willbe set to HS.
Quoted 1 line
This is true for all gadget drivers, including the once that
don't
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
define SS descriptors.
only due the module parameter, right ?
Due to the module parameter default value being FALSE, yes.
Ok, so let's take your approach but change the speed in the gadget driver structure, put your ifdef somewhere like here:
(quoted diff) +0
-0
b/drivers/usb/gadget/composite.cindex 1ba4bef..d02d6e8 100644drivers/usb/gadget/composite.c +0
-1@@ -1224,7 +1224,11 @@ composite_resume(struct usb_gadget *gadget) /*- -----------------------------------------------------------------------
drivers/usb/gadget/composite.c composite_resume(struct usb_gadget *gadget) /*- · line 1232
Quoted 10 lines
drivers/usb/gadget/composite.c +4
-1-*/ static struct usb_gadget_driver composite_driver = { +#ifdef CONFIG_USB_GADGET_SUPERSPEED + .speed =USB_SPEE_SUPER , +#else .speed =USB_SPEED_HIGH , +#endif .unbind = composite_unbind,
I have no problem updating static struct usb_gadget_driver composite_driver as you suggested but it seems the same as updating it @ usb_composite_probe()...
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi,
Quoted 32 lines · Tanya Brokhman
Quoted 32 lines
Quoted 7 lines
Quoted 7 lines
Quoted 5 lines
following:
1. ifCONFIG_USB_GADGET_SUPERSPEED=true, existing gadget drivers are still functional withdummy_hcdsince as I already mentioned, they will be enumerated through HS root hub and thus the gadget.speed willbe set to HS.
Quoted 1 line
This is true for all gadget drivers, including the once that
don't
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
define SS descriptors.
only due the module parameter, right ?
Due to the module parameter default value being FALSE, yes.
Ok, so let's take your approach but change the speed in the gadget driver structure, put your ifdef somewhere like here:
(quoted diff) +0
-0
b/drivers/usb/gadget/composite.cindex 1ba4bef..d02d6e8 100644drivers/usb/gadget/composite.c +4
-2@@ -1224,7 +1224,11 @@ composite_resume(struct usb_gadget *gadget) /*- ----------------------------------------------------------------------- -*/ static struct usb_gadget_driver composite_driver = { +#ifdef CONFIG_USB_GADGET_SUPERSPEED + .speed =USB_SPEE_SUPER , +#else .speed =USB_SPEED_HIGH , +#endif
Quoted 6 lines
drivers/usb/gadget/composite.c composite_resume(struct usb_gadget *gadget) · line 1233
Quoted 2 lines
drivers/usb/gadget/composite.c +0
-0.unbind = composite_unbind,I have no problem updating static struct
usb_gadget_drivercomposite_driveras you suggested but it seems the same as updating it @usb_composite_probe()...
still, you will have two places poking at the same field. It's better to keep it at once, update only that and we will take your approach.
Signature · 1 line
balbi
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi Felipe
Quoted 15 lines
Quoted 10 lines
Quoted 10 lines
---
drivers/usb/gadget/composite.c +4
-1-*/ static struct usb_gadget_driver composite_driver = { +#ifdef CONFIG_USB_GADGET_SUPERSPEED + .speed =USB_SPEE_SUPER , +#else .speed =USB_SPEED_HIGH , +#endifQuoted 5 lines
Quoted 2 lines
.unbind =
composite_unbind,I have no problem updating static struct
usb_gadget_drivercomposite_driveras you suggested but it seems the same as updating
Quoted 6 lines
it
Quoted 1 line
@
usb_composite_probe()...still, you will have two places poking at the same field. It's better to keep it at once, update only that and we will take your approach.
Ok so just to make sure I understand you correctly:
You want me to remove the modification made to usb_composite_probe() and instead add:
static struct usb_gadget_driver composite_driver = {
+#ifdef CONFIG_USB_GADGET_SUPERSPEED
+ .speed = USB_SPEE_SUPER,
+#else
.speed = USB_SPEED_HIGH,
+#endif
.unbind = composite_unbind,
And then you'll be ok with change? Or is there anything else?
If this is it then I'm relieved :) and of course will update the code.
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi,
Quoted 11 lines · Tanya Brokhman
Ok so just to make sure I understand you correctly:
You want me to remove the modification made tousb_composite_probe()and instead add:
static structusb_gadget_drivercomposite_driver= {drivers/usb/gadget/composite.c +3
-0+#ifdef CONFIG_USB_GADGET_SUPERSPEED + .speed = USB_SPEE_SUPER, +#else .speed =
USB_SPEED_HIGH,
+#endif
.unbind =composite_unbind,
Quoted 3 lines
And then you'll be ok with change? Or is there anything else?
If this is it then I'm relieved :) and of course will update the code.
yeah, that's all. Just be sure not to introduce the typo I introduced (missed D in SPEED) :-)
Then I'll hold on to those patches for 2.6.41 merge window.
Signature · 1 line
balbi
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
In reply to Tanya BrokhmanQuoted 11 lines · Tanya Brokhman
Ok so just to make sure I understand you correctly:
You want me to remove the modification made tousb_composite_probe()and instead add:
static structusb_gadget_drivercomposite_driver= {drivers/usb/gadget/composite.c +3
-0+#ifdef CONFIG_USB_GADGET_SUPERSPEED + .speed = USB_SPEE_SUPER, +#else .speed =
USB_SPEED_HIGH,
+#endif
.unbind =composite_unbind,
Quoted 3 lines
And then you'll be ok with change? Or is there anything else?
If this is it then I'm relieved :) and of course will update the code.
I have looked this over more carefully. It turns out that both of you have misunderstood the purpose of CONFIG_USB_GADGET_DUALSPEED (and by extension, CONFIG_USB_GADGET_SUPERSPEED). In fact, the existing Kconfig file is also wrong.
The _only_ reason for CONFIG_USB_GADGET_DUALSPEED is so that gadget drivers can use conditional compilation to avoid including the high-speed descriptors when the UDC doesn't support high-speed operation. That's all. This means that the CONFIG_USB_GAGDET_DUALSPEED option does not need to be user-controllable in Kconfig. It should default to N, and UDC drivers that support high speed should select it.
The same should be true of CONFIG_USB_GADGET_HIGHSPEED. It should not be user-controllable. It should default to N, and UDC drivers that support SuperSpeed operation (after these patches, only dummy-hcd) should select it.
There remains the other question, about whether composite_driver.speed should be set to USB_SPEED_SUPER. I think the matter can be settled at runtime. Iterate through all the function drivers; if all of them support SuperSpeed and CONFIG_USB_GADGET_SUPERSPEED is enabled then set composite_driver.speed to USB_SPEED_SUPER. Otherwise, if all of them support high speed and CONFIG_USB_GADGET_DUALSPEED is enabled then set composite_driver.speed to USB_SPEED_HIGH. Otherwise set it to USB_SPEED_FULL.
Alan Stern
--
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
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 5 lines · Alan Stern
I have looked this over more carefully. It turns out that both of you have misunderstood the purpose of
CONFIG_USB_GADGET_DUALSPEED(and by extension,CONFIG_USB_GADGET_SUPERSPEED). In fact, the existingKconfigfile is also wrong.
Quoted 7 lines
The _only_ reason for
CONFIG_USB_GADGET_DUALSPEEDis so that gadget drivers can use conditional compilation to avoid including the high-speed descriptors when the UDC doesn't support high-speed operation. That's all. This means that theCONFIG_USB_GAGDET_DUALSPEEDoption does not need to be user-controllable inKconfig. It should default to N, and UDC drivers that support high speed should select it.
In other words, we should merge the following patch and the new SuperSpeed support should follow the same pattern.
Alan Stern
---------------------------------------------------------------------
This patch (as1468) changes the Kconfig definition for USB_GADGET_DUALSPEED. This option is determined entirely by which device controller drivers are to be built, through Select statements; it does not need to be (and should not be) configurable by the user.
Also, the "default n" line is superfluous -- everything defaults to N.
---
drivers/usb/gadget/Kconfig | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/usb/gadget/Kconfig +1 -4
@@ -597,13 +597,10 @@ config USB_DUMMY_HCD endchoice +# Selected by UDC drivers that support high-speed operation. config USB_GADGET_DUALSPEED bool depends on USB_GADGET - default n - help - Means that gadget drivers should include extra descriptors - and code to handle dual-speed controllers. # # USB Gadget Drivers
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi Alan,
Quoted 24 lines
This patch (as1468) changes the
Kconfigdefinition forUSB_GADGET_DUALSPEED. This option is determined entirely by which device controller drivers are to be built, through Select statements; it does not need to be (and should not be) configurable by the user.Also, the "default n" line is superfluous -- everything defaults to N.
Signed-off-by Alan Stern <[email protected]>---
drivers/usb/gadget/Kconfig | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)Index: usb-2.6/drivers/usb/gadget/Kconfig
===================================================================drivers/usb/gadget/Kconfig +1
-0@@ -597,13 +597,10 @@ config USB_DUMMY_HCD endchoice +# Selected by UDC drivers that support high-speed operation.
drivers/usb/gadget/Kconfig config USB_DUMMY_HCD · line 606
Quoted 10 lines
drivers/usb/gadget/Kconfig +0
-4config USB_GADGET_DUALSPEED bool depends on USB_GADGET - default n - help - Means that gadget drivers should include extra descriptors - and code to handle dual-speed controllers. # # USB Gadget Drivers
I was making the same change for SS and I think that if you're about to send this patch to Greg, it might need a small addition:
At the moment dummy_hcd supports high_speed so I think if this option is no longer configurable by user you should set this flag when dummy_hcd is selected:
config USB_DUMMY_HCD
tristate
depends on USB_GADGET_DUMMY_HCD
default USB_GADGET
select USB_GADGET_SELECTED
select USB_GADGET_DUALSPEED
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 6 lines · Tanya Brokhman
I was making the same change for SS and I think that if you're about to send this patch to Greg, it might need a small addition:
At the momentdummy_hcdsupportshigh_speedso I think if this option is no longer configurable by user you should set this flag whendummy_hcdis selected:
Quoted 6 lines
config
USB_DUMMY_HCD
tristate
depends onUSB_GADGET_DUMMY_HCD
defaultUSB_GADGET
selectUSB_GADGET_SELECTED
selectUSB_GADGET_DUALSPEED
Right now USB_GADGET_DUALSPEED is selected under USB_GADGET_DUMMY_HCD, which is the right place for it, I think. Same as all the other UDC drivers.
Alan Stern
Felipe Balbi
Acked-byRe: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
In reply to Alan SternHi,
Quoted 8 lines · Alan Stern
This patch (as1468) changes the
Kconfigdefinition forUSB_GADGET_DUALSPEED. This option is determined entirely by which device controller drivers are to be built, through Select statements; it does not need to be (and should not be) configurable by the user.Also, the "default n" line is superfluous -- everything defaults to N.
Signed-off-by Alan Stern <[email protected]>
this patch makes a lot of sense. FWIW:
Quoted 25 lines
---
drivers/usb/gadget/Kconfig | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)Index: usb-2.6/drivers/usb/gadget/Kconfig
===================================================================drivers/usb/gadget/Kconfig +1
-4@@ -597,13 +597,10 @@ config USB_DUMMY_HCD endchoice +# Selected by UDC drivers that support high-speed operation. config USB_GADGET_DUALSPEED bool depends on USB_GADGET - default n - help - Means that gadget drivers should include extra descriptors - and code to handle dual-speed controllers. # # USB Gadget Drivers
Signature · 1 line
balbi
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
In reply to Alan SternHi Alan,
Quoted 13 lines
I have looked this over more carefully. It turns out that both of you have misunderstood the purpose of
CONFIG_USB_GADGET_DUALSPEED(and by extension,CONFIG_USB_GADGET_SUPERSPEED). In fact, the existingKconfigfile is also wrong.The _only_ reason for
CONFIG_USB_GADGET_DUALSPEEDis so that gadget drivers can use conditional compilation to avoid including the high-speed descriptors when the UDC doesn't support high-speed operation. That's all. This means that theCONFIG_USB_GAGDET_DUALSPEEDoption does not need to be user-controllable inKconfig. It should default to N, and UDC drivers that support high speed should select it.
Quoted 4 lines
The same should be true of
CONFIG_USB_GADGET_HIGHSPEED. It should not be user-controllable. It should default to N, and UDC drivers that support SuperSpeed operation (after these patches, only dummy-hcd) should select it.
Ok, agreed. Thanks for the clarification. I saw your patch, I'll update mine in the same way.
Quoted 5 lines
There remains the other question, about whether composite_driver.speed should be set to
USB_SPEED_SUPER. I think the matter can be settled at runtime. Iterate through all the function drivers; if all of them support SuperSpeed andCONFIG_USB_GADGET_SUPERSPEEDis enabled then set composite_driver.speed toUSB_SPEED_SUPER.
Not sure how to verify this. I need to know whether the driver that is registered with the UDC is SS or not. This is before the function drivers are binded to it. So how can I verify at that point that the function drivers that will bind to this driver will provide SS descriptors? (I'm sorry, I don't have the ability to view the code at the moment and due to the time differences between us I don't want to leave this question for tomorrow and loose another day...)
Quoted 7 lines
Otherwise, if all of them
support high speed andCONFIG_USB_GADGET_DUALSPEEDis enabled then set composite_driver.speed toUSB_SPEED_HIGH. Otherwise set it toUSB_SPEED_FULL.Alan Stern
Thanks,
Tanya Brokhman
Signature · 2 lines
Sent by an consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 15 lines · Brokhman Tatyana
Hi Alan,
Quoted 13 lines
I have looked this over more carefully. It turns out that both of you have misunderstood the purpose of
CONFIG_USB_GADGET_DUALSPEED(and by extension,CONFIG_USB_GADGET_SUPERSPEED). In fact, the existingKconfigfile is also wrong.The _only_ reason for
CONFIG_USB_GADGET_DUALSPEEDis so that gadget drivers can use conditional compilation to avoid including the high-speed descriptors when the UDC doesn't support high-speed operation. That's all. This means that theCONFIG_USB_GAGDET_DUALSPEEDoption does not need to be user-controllable inKconfig. It should default to N, and UDC drivers that support high speed should select it.
Quoted 7 lines
Quoted 4 lines
The same should be true of
CONFIG_USB_GADGET_HIGHSPEED. It should not be user-controllable. It should default to N, and UDC drivers that support SuperSpeed operation (after these patches, only dummy-hcd) should select it.Ok, agreed. Thanks for the clarification. I saw your patch, I'll update mine in the same way.
Good. If Felipe doesn't object to my patch, I'll send it to Greg.
Quoted 6 lines
Quoted 5 lines
There remains the other question, about whether composite_driver.speed should be set to
USB_SPEED_SUPER. I think the matter can be settled at runtime. Iterate through all the function drivers; if all of them support SuperSpeed andCONFIG_USB_GADGET_SUPERSPEEDis enabled then set composite_driver.speed toUSB_SPEED_SUPER.
Quoted 7 lines
Not sure how to verify this. I need to know whether the driver that is registered with the UDC is SS or not. This is before the function drivers are binded to it. So how can I verify at that point that the function drivers that will bind to this driver will provide SS descriptors? (I'm sorry, I don't have the ability to view the code at the moment and due to the time differences between us I don't want to leave this question for tomorrow and loose another day...)
I'm not sure about this either. I have never used the composite framework so I'm not familiar with its details. This has to be decided before the composite gadget driver registers with the UDC driver ... and surely that can't happen until all the function drivers have registered with the composite driver? After all, the gadget can't be enumerated until all the function drivers are registered.
Maybe this logic can be put in usb_add_function()? That routine already deals with issues involving device speed and available descriptors.
Alan Stern
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
composite_driver.speed to USB_SPEED_SUPER.
Quoted 11 lines
Quoted 10 lines
Not sure how to verify this. I need to know whether the driver that is registered with the UDC is SS or not. This is before the function drivers
are binded to it. So how can I verify at that point that the function drivers that will bind to this driver will provide SS descriptors? (I'm sorry, I don't have the ability to view the code at the moment and due to the time differences between us I don't want to leave this question
for tomorrow and loose another day...)
Quoted 3 lines
I'm not sure about this either. I have never used the composite framework so I'm not familiar with its details. This has to be decided before the composite gadget driver registers with the UDC driver ...
Right, but at this point there is no way of knowing what function drivers will bind to it and what descriptors they will provide. Most of the function drivers allocate their descriptors at bind() that occurs after the UDC already registers.
Quoted 3 lines
and surely that can't happen until all the function drivers have registered with the composite driver? After all, the gadget can't be enumerated until all the function drivers are registered.
Right, but it doesn't mean that the composite driver can't register with the UDC until all the function drivers are registered. Actually, the composite driver binds when no function driver has yet registered with it.
Quoted 3 lines
Maybe this logic can be put in
usb_add_function()? That routine already deals with issues involving device speed and available descriptors.
That's too late. The composite driver is registered by the time usb_add_function() is called.
Tanya Brokhman
Signature · 8 lines
Sent by an consultant 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-usb" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 13 lines · Brokhman Tatyana
composite_driver.speed to
USB_SPEED_SUPER.Quoted 11 lines
Quoted 10 lines
Not sure how to verify this. I need to know whether the driver that is registered with the UDC is SS or not. This is before the function drivers
are binded to it. So how can I verify at that point that the function drivers that will bind to this driver will provide SS descriptors? (I'm sorry, I don't have the ability to view the code at the moment and due to the time differences between us I don't want to leave this question
for tomorrow and loose another day...)
Quoted 7 lines
Quoted 3 lines
I'm not sure about this either. I have never used the composite framework so I'm not familiar with its details. This has to be decided before the composite gadget driver registers with the UDC driver ...
Right, but at this point there is no way of knowing what function drivers will bind to it and what descriptors they will provide. Most of the function drivers allocate their descriptors at
bind()that occurs after the UDC already registers.
Well, there must be an appropriate spot to do this.
It looks like you need to add a "max_speed" field to struct usb_composite_driver. Each driver will initialize this to the highest speed it supports, and it must guarantee that the necessary descriptors are available.
Since these structures are passed to usb_composite_probe() before the gadget driver is registered, the necessary calculations can be done there.
Alan Stern
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi Alan, Felipe,
Quoted 20 lines
Quoted 3 lines
composite_driver.speed to
USB_SPEED_SUPER.Quoted 2 lines
Quoted 2 lines
Not sure how to verify this. I need to know whether the driver
that is
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
registered with the UDC is SS or not. This is before the function drivers
are binded to it. So how can I verify at that point that thefunction
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
drivers that will bind to this driver will provide SS descriptors? (I'm sorry, I don't have the ability to view the code at the
moment and
Quoted 6 lines
Quoted 6 lines
Quoted 3 lines
due to the time differences between us I don't want to leave this question
for tomorrow and loose another day...)I'm not sure about this either. I have never used the composite framework so I'm not familiar with its details. This has to be
decided
Quoted 1 line
Quoted 1 line
before the composite gadget driver registers with the UDC driver
...
Quoted 8 lines
Quoted 1 line
Right, but at this point there is no way of knowing what function
drivers
Quoted 2 lines
will bind to it and what descriptors they will provide. Most of the function drivers allocate their descriptors at
bind()that occursafter
Quoted 1 line
the UDC already registers.
Well, there must be an appropriate spot to do this.
Unfortunately in the current implementation there isn't. We must set the driver speed at usb_composite_probe().
The (not full) call stack for composite driver registration is:
1. usb_composite_probe()
2. usb_gadget_probe_driver()
3. composite_bind() - here the device descriptor is updated (fields such as bMaxPacketSize0, idVendor, etc)
4. the gadgets "bind" function is called. For example for g_zero it's zero_bind(). Only at this point will the function driver register it's configurations and for each registered config - add the appropriate functions.
So as you can see, whether the gadget driver supports/or not SS can be determined only at the end of the registration sequence, whether as far as UDC is concerned, we need to set the correct driver speed at the very beginning - at usb_composite_probe().
Felipe - please correct me if I'm mistaken. Is there a way to find out at usb_composite_probe() if the registered function driver will support SS?
Quoted 4 lines
It looks like you need to add a "
max_speed" field to structusb_composite_driver. Each driver will initialize this to the highest speed it supports, and it must guarantee that the necessary descriptors are available.
I also thought of that. This can be done...
Just to make sure we're on the same page:
We can add a "max_sup_speed" field to struct usb_composite_driver. Each of the Gadget drivers will set this field prior to calling usb_composite_probe(). Then, in usb_composite_probe(), we'll update the composite_driver.speed as follows:
composite_driver.speed = min(composite_driver.speed,driver->max_sup_speed);
Of course for SS we'll update the composite_driver.speed @ static struct usb_gadget_driver composite_driver, as we agreed with Felipe.
How does that sound? Felipe - it seems to me that these should cover your hesitations about updating the driver speed :)
Now that I think about it, the above will be true for HS as well. I mean the current speed of composite_driver is set always to HS but if there is a function driver that supports only FS then the above will update composite_driver.speed to FS.
Best regards,
Tanya Brokhman
Consultant for Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Quoted 10 lines · Tanya Brokhman
Quoted 8 lines
Quoted 1 line
Right, but at this point there is no way of knowing what function
drivers
Quoted 2 lines
will bind to it and what descriptors they will provide. Most of the function drivers allocate their descriptors at
bind()that occursafter
Quoted 1 line
the UDC already registers.
Well, there must be an appropriate spot to do this.
Unfortunately in the current implementation there isn't.
Sure there is. You describe a good possibility later on in your email...
Quoted 12 lines
Quoted 4 lines
It looks like you need to add a "
max_speed" field to structusb_composite_driver. Each driver will initialize this to the highest speed it supports, and it must guarantee that the necessary descriptors are available.I also thought of that. This can be done...
Just to make sure we're on the same page:
We can add a "max_sup_speed" field to structusb_composite_driver. Each of the Gadget drivers will set this field prior to callingusb_composite_probe(). Then, inusb_composite_probe(), we'll update the composite_driver.speed as follows:
Quoted 2 lines
composite_driver.speed = min(composite_driver.speed,
driver->max_sup_speed);
Just call it max_speed. You can mention in the kerneldoc that it is the maximum speed supported by the driver.
Quoted 10 lines
Of course for SS we'll update the composite_driver.speed @ static struct
usb_gadget_drivercomposite_driver, as we agreed with Felipe.How does that sound? Felipe - it seems to me that these should cover your hesitations about updating the driver speed :)
Now that I think about it, the above will be true for HS as well. I mean the current speed of
composite_driveris set always to HS but if there is a function driver that supports only FS then the above will update composite_driver.speed to FS.
That's right. The same solution will work for both cases.
Alan Stern
RE: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
Hi Alan,
Quoted 8 lines
Quoted 8 lines
I also thought of that. This can be done...
Just to make sure we're on the same page:
We can add a "max_sup_speed" field to structusb_composite_driver. Each of
the Gadget drivers will set this field prior to callingusb_composite_probe(). Then, inusb_composite_probe(), we'll update the composite_driver.speed as follows:
Quoted 5 lines
Quoted 2 lines
composite_driver.speed = min(composite_driver.speed,
driver->max_sup_speed);Just call it
max_speed. You can mention in the kerneldoc that it is the maximum speed supported by the driver.
No problem. I understand that you agree to this approach?
I was going to wait for Felipe to comment but he'll be out of reach for several days so I'll post a new patch set on Sunday.
Thanks for you help!
Tanya Brokhman
Signature · 2 lines
Sent by an consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
In reply to Alan SternHi,
Quoted 33 lines · Alan Stern
Quoted 26 lines · Tanya Brokhman
Hi Felipe
Quoted 5 lines
Quoted 5 lines
Yes :) The
driver->speedis updated inusb_composite_probe()ifCONFIG_USB_GADGET_SUPERSPEEDis defined.So, are we ok with this solution? The module parameter I mean? Are you going to try the v13 in your branch? Please let me know how
Quoted 7 lines
it
Quoted 1 line
goes and of course if you have any comments.
I think it still gives the possibility for failure. I would rather not take that until all gadget drivers are fixed. We can help you doing that and we only change
driver->speedafter all gadget drivers have their "sensible defaults" SuperSpeed descriptors.By "until all gadget drivers are fixed" you mean until all gadget drivers provide SS descriptors? This will take for ever...
I wasn't about to modify all gadget drivers and to add SS descriptors for them. I can add default values (asgenerate_ss_descriptors()did if you remember) but I don't think this is the right approach because as you said - different gadget drivers might have different SS descriptors and I don't feel confident enough to set these values. Nor do I have the ability to test each of the gadget drivers the way I would like to after this change. The only gadget driver I felt confident adding SS descriptors for is UASP, which I tested properly.Quoted 4 lines
Actually if the
CONFIG_USB_GADGET_SUPERSPEEDis turned off, which is the default of it, the speed won't be updated and all these series won't be functional so I don't see any possibilities for failure in such configuration. Or am I missing something?
Quoted 8 lines
dummy_hcdshould work whenCONFIG_USB_GADGET_SUPERSPEEDis enabled, even if theusb_gadget_driverstructure is initialized with the speed field set toUSB_SPEED_HIGH. This will be true for all the standalone gadget drivers until they are updated.Which leaves a question about the composite gadget framework. Should it be updated with SS support? Probably not until the various function drivers have all been updated.
We can add support for all the USB3 standard requests, just don't change the driver->speed field until all gadget drivers are fixed.
Signature · 1 line
balbi
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
In reply to Felipe BalbiQuoted 24 lines · Felipe Balbi
hi,
Quoted 21 lines · Tanya Brokhman
Quoted 20 lines
Quoted 5 lines
Quoted 5 lines
drivers/usb/gadget/dummy_hcd.c MODULE_DESCRIPTION (DRIVER_DESC);
Quoted 5 lines
drivers/usb/gadget/dummy_hcd.c +5
-0+ +static struct dummy_hcd_module_parameters mod_data = { + .is_super_speed = false +}; +module_param_named(is_super_speed, mod_data.is_super_speed,bool,
Quoted 11 lines
Quoted 5 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+S_IRUGO); MODULE_PARM_DESC(is_super_speed, "true to simulate +SuperSpeed connection");you shouldn't need this. You should always enable SuperSpeed for this driver.
You mean I don't need the module parameter? IMO it's the best way to enable HS connection. If driver->speed=USB_SPEED_SUPER than
dummy_hcdwill try to enumerate the device on the SS root hub and if the gadget didn't provide SS descriptors - it will fail. Just as it happened before. Finding out fromthen it should hand the device over to the
hs_hcd;-) Meaning it would disconnect the device, switch tohs_hcdand reconnect :-)
Quoted 7 lines
Quoted 2 lines
Yes this will be the best solution :) But as I said, the enumeration occurs not in
dummy_hcdthus I'm not sure howdummy_hcdcan find out that it failedtake a look at
xhci-ring.cfor an example :-)see that it check whether the attached device is a USB3.0 device or USB2.0/1.1 device and chooses hcd or
shared_hcdaccordingly.
Yes, that's based on what the port speed registers report. The host controller will detect either a connect on the SuperSpeed terminations and set the SuperSpeed speed accordingly. I'm not sure how it detects whether the device is a high speed device. I think it has something to do with the LPF signaling, but I'm not a link layer expert.
Quoted 4 lines
Quoted 3 lines
in order to reconnect the device to
hs_hcd. And I'm not sure thatdummy_hcdshould care whether the enumeration succeeds or fails. It seems to me that this should be handled by upper levels. Shouldn't it?
Quoted 11 lines
nope. If
dummy_hcdwas a SW xhci implementation then it should be taken care by upper layers, but since this is a complete SW non-standard Host interface, then we need to handle the whole thing.Quoted 2 lines
But we're discussing a more general issue; do you remember what the usb30 spec sais about this? I mean when connecting a HS device to a SS port (over
not the exact wording of the Specs but it should work :-)
Quoted 2 lines
SS cable), should it still enumerate as a HS device? It seems to me that the answer is no but I'm not sure...
If you look at Figure 7-13 in the USB 3.0 spec, you'll see that the device is supposed to try to detect SuperSpeed terminations, but if that times out, then it goes to the "SuperSpeed disabled" state, and falls back to the USB 2.0 bus connection.
Quoted 2 lines
the USB3 host shouldn't enumerate but it has the
shared_hcdwhich is USB2.0 compliant.
Felipe, technically the xHCI host controller handles all device speeds. There are no companion controllers in an xHCI host controller. The hcd and shared_hcd is just an abstraction to make the roothub look like an external USB 3.0 hub to the USB core.
External USB 3.0 devices show up as two separate devices -- a USB 3.0 hub and a USB 2.0 hub. The xHCI host controller originally just showed as a USB 3.0 hub that could handle all speeds, but when we needed to add support for external USB 3.0 hubs, that simplification broke the USB core's assumption that roothubs and external hubs act the same way. So we changed the xHCI driver to register to usb_hcd structures for one PCI device.
Basically you should just think of the xHCI host as taking care of all devices plugged into it.
Quoted 11 lines
Quoted 11 lines
Quoted 10 lines
Quoted 4 lines
dummy_hcdthat the enumeration failed is very complicated (if even possible) and I'm not sure that is the right thing to do... If you connect a real device over SS port to xHCI and the device doesn't provide SS descriptors - the enumeration fails and it's ok. But ifyou
Quoted 2 lines
connect the same device to a HS port - it should work properly. This is what I tried to simulate with this parameter.
it doesn't just fails, it gives the device over to the
shared_hcd:-)
Quoted 8 lines
Quoted 5 lines
Hmmm.... I have v2.6.38 installed on my Linux-host at the moment and I just verified that when connecting a Gadget driver without SS descriptors over SS connection - the enumeration fails. Was this fixed in v2.6.39? It will take me some time to upgrade to v2.6.39 and verify but I have to do it any way so I'll give it a shot...
Maybe Sarah can give more details on this one. Sarah, what happens if we attach USB2.0 device to USB3.0 roothub ?
It gets enumerated under xHCI as a USB 2.0 device. With 2.6.39 and later, you'll see it ends up under the "Linux Foundation 2.0 root hub", but if you look at iManufacturer under that hub's description, you'll see it's an xHCI roothub. With kernels before 2.6.39, it will end up under the "Linux Foundation 3.0 root hub".
Sarah Sharp
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
In reply to Felipe BalbiQuoted 7 lines · Felipe Balbi
Quoted 7 lines
Quoted 6 lines
Review
Quoted 3 lines
(quoted diff) +3
-0+module_param_named(is_super_speed, mod_data.is_super_speed, bool, +S_IRUGO); MODULE_PARM_DESC(is_super_speed, "true to simulate +SuperSpeed connection");you shouldn't need this. You should always enable SuperSpeed for this driver.
Quoted 7 lines
Quoted 4 lines
You mean I don't need the module parameter? IMO it's the best way to enable HS connection. If driver->speed=USB_SPEED_SUPER than
dummy_hcdwill try to enumerate the device on the SS root hub and if the gadget didn't provide SS descriptors - it will fail. Just as it happened before. Finding out fromthen it should hand the device over to the
hs_hcd;-) Meaning it would disconnect the device, switch tohs_hcdand reconnect :-)
No. That doesn't happen with real devices, so there's no reason dummy-hcd should do it.
Quoted 8 lines
Quoted 6 lines
dummy_hcdthat the enumeration failed is very complicated (if even possible) and I'm not sure that is the right thing to do... If you connect a real device over SS port to xHCI and the device doesn't provide SS descriptors - the enumeration fails and it's ok. But if you connect the same device to a HS port - it should work properly. This is what I tried to simulate with this parameter.it doesn't just fails, it gives the device over to the
shared_hcd:-)
It does not. xhci-hcd does not keep track of whether or not enumeration succeeds, and it doesn't do anything special when enumeration fails.
Alan Stern
--
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
Re: [PATCH v12 7/8] usb: Adding SuperSpeed support to dummy_hcd
In reply to Felipe BalbiQuoted 8 lines · Felipe Balbi
Quoted 8 lines
drivers/usb/gadget/dummy_hcd.c +0
-0@@ -70,6 +70,15 @@ MODULE_DESCRIPTION (DRIVER_DESC);MODULE_AUTHOR ("David Brownell" );MODULE_LICENSE ("GPL" );
Quoted 12 lines
drivers/usb/gadget/dummy_hcd.c MODULE_DESCRIPTION (DRIVER_DESC); · line 81
Quoted 9 lines
drivers/usb/gadget/dummy_hcd.c +9
-0+struct dummy_hcd_module_parameters { +bool is_super_speed; +}; + +static struct dummy_hcd_module_parameters mod_data = { + .is_super_speed = false +}; +module_param_named (is_super_speed, mod_data.is_super_speed, bool,S_IRUGO ); +MODULE_PARM_DESC (is_super_speed,"true to simulate SuperSpeed connection" );you shouldn't need this. You should always enable SuperSpeed for this driver.
I would say the opposite and go even farther. It's good to have a way to force a SuperSpeed gadget to run at high speed, and it would also be good to have a way to force a high-speed gadget to run at full speed.
A module parameter seems to be the simplest way of doing this.
Quoted 4 lines
drivers/usb/gadget/dummy_hcd.c stop_activity (struct dummy *dum) · line 331
Quoted 2 lines
drivers/usb/gadget/dummy_hcd.c +2
-0+/* +* We're connected and not reseted (reset occured now), 'reseted' isn't proper spelling :-)
Neither is "occured".
Quoted 8 lines
drivers/usb/gadget/dummy_hcd.c static void dummy_timer(unsigned long _dum_hcd) · line 1581
Quoted 6 lines
drivers/usb/gadget/dummy_hcd.c +2
-0@@ -1371,6 +1577,10 @@ static void dummy_timer(unsigned long _dum_hcd)case USB_SPEED_HIGH : total =512 /*bytes*/ *13 /*packets*/ *8 /*uframes*/ ;break ; +case USB_SPEED_SUPER : +/* Bus speed is 500000 bytes/ms, so use a little less */ isn't it 500000 bits/ms ?
SuperSpeed is 5 billion bits/s or 5 million bits/ms. The physical layer encodes each data byte using 10 bits, therefore the bus speed is 500000 bytes/ms.
Alan Stern
--
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
PATCH v12 8/8 usb:gadget: coding style fixes
In reply to Tatyana Brokhman--- drivers/usb/gadget/composite.c | 20 +++++++++++---- drivers/usb/gadget/dummy_hcd.c | 52 ++++++++++++++++++++++++++++++---------- 2 files changed, 54 insertions(+), 18 deletions(-)
drivers/usb/gadget/composite.c +15 -5
@@ -629,11 +629,21 @@ static int set_config(struct usb_composite_dev *cdev,INFO (cdev,"%s speed config #%d: %s\n" , ({char *speed;switch (gadget->speed) { -case USB_SPEED_LOW : speed ="low" ;break ; -case USB_SPEED_FULL : speed ="full" ;break ; -case USB_SPEED_HIGH : speed ="high" ;break ; -case USB_SPEED_SUPER : speed ="super" ;break ; -default : speed ="?" ;break ; +case USB_SPEED_LOW : + speed ="low" ; +break ; +case USB_SPEED_FULL : + speed ="full" ; +break ; +case USB_SPEED_HIGH : + speed ="high" ; +break ; +case USB_SPEED_SUPER : + speed ="super" ; +break ; +default : + speed ="?" ; +break ; } ; speed; }), number, c ? c->label :"unconfigured" );if (!c)
drivers/usb/gadget/dummy_hcd.c +39 -13
68 lines not on this page · raw message
Signature · 5 lines
1.7.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.