* Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS
@ 2024-06-14 22:31 Andrey Konovalov
2024-06-15 2:12 ` Alan Stern
0 siblings, 1 reply; 12+ messages in thread
From: Andrey Konovalov @ 2024-06-14 22:31 UTC (permalink / raw)
To: Alan Stern; +Cc: USB list
Hi Alan,
I'm working on implementing a USB proxy that uses libusb on one side
and Raw Gadget on the other. The idea is to pass all requests received
from the host via Raw Gadget to the proxied device via libusb and
report back the responses.
However, I've stumbled upon an issue with non-0-length control
requests that get stalled by the proxied device.
To pass an OUT control request to the device via libusb I need to
first retrieve the data for the request from the host. And with Raw
Gadget I can do that via USB_RAW_IOCTL_EP0_READ, which internally
calls usb_ep_queue, waits for its completion, and copies the data to
userspace.
But the problem is that once I retrieve the data, the request is
automatically acked. Thus, if the proxied device stalls the request,
it's already too late to stall it via Raw Gadget.
AFAIU, GadgetFS works the same way.
Is there a way to work around this? If this requires a change is Raw
Gadget, that is fine. But I'm wondering if this is possible to do at
all with the USB Gadget API: AFAIU, we have to either stall or
retrieve the data; we cannot do both.
If this is indeed impossible, perhaps you know if there's a way to
directly use usbfs to separately submit the control request header to
the proxied device to figure out if it wants to stall? And only then
retrieve the data from the host via Raw Gadget if the device doesn't
stall.
Thank you!
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS
2024-06-14 22:31 Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS Andrey Konovalov
@ 2024-06-15 2:12 ` Alan Stern
2024-06-15 20:49 ` Andrey Konovalov
0 siblings, 1 reply; 12+ messages in thread
From: Alan Stern @ 2024-06-15 2:12 UTC (permalink / raw)
To: Andrey Konovalov; +Cc: USB list
On Sat, Jun 15, 2024 at 12:31:12AM +0200, Andrey Konovalov wrote:
> Hi Alan,
>
> I'm working on implementing a USB proxy that uses libusb on one side
> and Raw Gadget on the other. The idea is to pass all requests received
> from the host via Raw Gadget to the proxied device via libusb and
> report back the responses.
>
> However, I've stumbled upon an issue with non-0-length control
> requests that get stalled by the proxied device.
>
> To pass an OUT control request to the device via libusb I need to
> first retrieve the data for the request from the host. And with Raw
> Gadget I can do that via USB_RAW_IOCTL_EP0_READ, which internally
> calls usb_ep_queue, waits for its completion, and copies the data to
> userspace.
>
> But the problem is that once I retrieve the data, the request is
> automatically acked. Thus, if the proxied device stalls the request,
> it's already too late to stall it via Raw Gadget.
>
> AFAIU, GadgetFS works the same way.
>
> Is there a way to work around this? If this requires a change is Raw
> Gadget, that is fine. But I'm wondering if this is possible to do at
> all with the USB Gadget API: AFAIU, we have to either stall or
> retrieve the data; we cannot do both.
Yeah, this is a known weakness of the Gadget API. There's no way to do
it at present.
> If this is indeed impossible, perhaps you know if there's a way to
> directly use usbfs to separately submit the control request header to
> the proxied device to figure out if it wants to stall? And only then
> retrieve the data from the host via Raw Gadget if the device doesn't
> stall.
usbfs allows the user to send a complete transfer, not a partial one
(i.e., just the SETUP transaction). Besides, it's not possible for a
device to stall a SETUP packet -- the USB-2.0 spec requires devices to
respond to SETUP with ACK every time (section 8.5.3) -- so this approach
won't solve the problem anyway. And even if it did, you'd still have to
handle the situation where the proxy device accepts the SETUP packet and
the data but then stalls during the Status stage of the transfer.
There has been a patch posted to support UDC drivers that don't
automatically acknowledge non-zero-length control-OUT transfers. But
the patch hasn't been merged, and even if it were, all the existing UDC
drivers would still need to be updated.
Sorry, but the kernel just doesn't provide any way to do this.
Alan Stern
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS
2024-06-15 2:12 ` Alan Stern
@ 2024-06-15 20:49 ` Andrey Konovalov
2024-06-16 2:33 ` Alan Stern
0 siblings, 1 reply; 12+ messages in thread
From: Andrey Konovalov @ 2024-06-15 20:49 UTC (permalink / raw)
To: Alan Stern; +Cc: USB list, Paul Elder
On Sat, Jun 15, 2024 at 4:12 AM Alan Stern <stern@rowland.harvard.edu> wrote:
>
> Yeah, this is a known weakness of the Gadget API. There's no way to do
> it at present.
Ack.
> usbfs allows the user to send a complete transfer, not a partial one
> (i.e., just the SETUP transaction). Besides, it's not possible for a
> device to stall a SETUP packet -- the USB-2.0 spec requires devices to
> respond to SETUP with ACK every time (section 8.5.3) -- so this approach
> won't solve the problem anyway. And even if it did, you'd still have to
> handle the situation where the proxy device accepts the SETUP packet and
> the data but then stalls during the Status stage of the transfer.
Ah, so dealing with this on the usbfs side is impossible.
> There has been a patch posted to support UDC drivers that don't
> automatically acknowledge non-zero-length control-OUT transfers. But
> the patch hasn't been merged, and even if it were, all the existing UDC
> drivers would still need to be updated.
This series below is the one you're referring to, right?
https://lore.kernel.org/linux-kernel/20190124030228.19840-1-paul.elder@ideasonboard.com/
Do you know why it wasn't merged? (CC Paul). There are no comments on
the latest version I managed to find.
Also, just to check my understanding: with that series in place and
assuming the UDC drivers are updated, a gadget driver would need to
first do usb_ep_queue with the proper length and explicit_status ==
true to get the data for the control OUT request, and then either do
usb_ep_queue again with length 0 to ack or do usb_ep_set_halt to
stall?
Thank you!
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS
2024-06-15 20:49 ` Andrey Konovalov
@ 2024-06-16 2:33 ` Alan Stern
2024-06-16 22:42 ` Andrey Konovalov
2024-06-19 1:44 ` Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS Paul Elder
0 siblings, 2 replies; 12+ messages in thread
From: Alan Stern @ 2024-06-16 2:33 UTC (permalink / raw)
To: Andrey Konovalov; +Cc: USB list, Paul Elder
On Sat, Jun 15, 2024 at 10:49:46PM +0200, Andrey Konovalov wrote:
> On Sat, Jun 15, 2024 at 4:12 AM Alan Stern <stern@rowland.harvard.edu> wrote:
> > There has been a patch posted to support UDC drivers that don't
> > automatically acknowledge non-zero-length control-OUT transfers. But
> > the patch hasn't been merged, and even if it were, all the existing UDC
> > drivers would still need to be updated.
>
> This series below is the one you're referring to, right?
>
> https://lore.kernel.org/linux-kernel/20190124030228.19840-1-paul.elder@ideasonboard.com/
Yes, that's it. I'm impressed that you were able to find it; I had lost
track of it.
> Do you know why it wasn't merged? (CC Paul). There are no comments on
> the latest version I managed to find.
I guess Felipe Balbi (the USB Gadget maintainer at the time) just wasn't
very interested in fixing the problem.
> Also, just to check my understanding: with that series in place and
> assuming the UDC drivers are updated, a gadget driver would need to
> first do usb_ep_queue with the proper length and explicit_status ==
> true to get the data for the control OUT request, and then either do
> usb_ep_queue again with length 0 to ack or do usb_ep_set_halt to
> stall?
Yes, that's how it worked. Alternatively, if the gadget driver didn't
set explicit_status in the control-OUT request then the UDC core would
automatically call usb_ep_queue again with a 0-length transfer to send
the status. That way existing gadget drivers would continue to work
after the UDC drivers were updated, and updated UDC drivers wouldn't
have to worry about doing an automatic acknowledge only some of the
time.
Note that in order to avoid breaking things during the transition
period, it would also be necessary to add a flag to the usb_gadget
structure, indicating that the UDC driver has been updated to support
explicit_status.
Alan Stern
PS: There's another weakness in the Gadget API which you might possibly
run across in your project. It's less likely to arise because it
involves lengthy delays.
Say there's a control transfer with delayed status, and the gadget
driver delays for so long that the host times out the transfer. Then
the host starts a new control transfer before the gadget driver queues
its status reply. Since the Gadget API doesn't have any way to indicate
which control transfer a usb_request was meant for, the reply that was
meant for the old transfer would get sent to the host, and the host
would think it was a reply to the new transfer.
This problem could be solved by adding a unique ID tag to each
usb_request, and passing the transfer ID as an extra argument to the
gadget driver's setup() callback. That would explicitly indicate which
transfer a request was meant for. But doing this would also require
updating every function driver and every UDC driver. Probably not worth
the effort, considering how unlikely it is that the situation will ever
arise.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS
2024-06-16 2:33 ` Alan Stern
@ 2024-06-16 22:42 ` Andrey Konovalov
2024-06-17 2:10 ` Alan Stern
2024-06-19 1:44 ` Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS Paul Elder
1 sibling, 1 reply; 12+ messages in thread
From: Andrey Konovalov @ 2024-06-16 22:42 UTC (permalink / raw)
To: Alan Stern; +Cc: USB list, Paul Elder
On Sun, Jun 16, 2024 at 4:33 AM Alan Stern <stern@rowland.harvard.edu> wrote:
>
> > This series below is the one you're referring to, right?
> >
> > https://lore.kernel.org/linux-kernel/20190124030228.19840-1-paul.elder@ideasonboard.com/
>
> Yes, that's it. I'm impressed that you were able to find it; I had lost
> track of it.
Luckily, it was one of the first google results on the topic :)
> > Do you know why it wasn't merged? (CC Paul). There are no comments on
> > the latest version I managed to find.
>
> I guess Felipe Balbi (the USB Gadget maintainer at the time) just wasn't
> very interested in fixing the problem.
Ok, I see.
> > Also, just to check my understanding: with that series in place and
> > assuming the UDC drivers are updated, a gadget driver would need to
> > first do usb_ep_queue with the proper length and explicit_status ==
> > true to get the data for the control OUT request, and then either do
> > usb_ep_queue again with length 0 to ack or do usb_ep_set_halt to
> > stall?
>
> Yes, that's how it worked. Alternatively, if the gadget driver didn't
> set explicit_status in the control-OUT request then the UDC core would
> automatically call usb_ep_queue again with a 0-length transfer to send
> the status. That way existing gadget drivers would continue to work
> after the UDC drivers were updated, and updated UDC drivers wouldn't
> have to worry about doing an automatic acknowledge only some of the
> time.
>
> Note that in order to avoid breaking things during the transition
> period, it would also be necessary to add a flag to the usb_gadget
> structure, indicating that the UDC driver has been updated to support
> explicit_status.
Ack, thank you for explaining!
I've been collecting different kinds of non-critical issues and
inconsistencies within the Gadget subsystem I hit while testing Raw
Gadget. It's unlikely I'll get to working on them in the foreseeable
future, but it's good to know what needs fixing should the need arise.
So far, I have:
- Allow stalling non-0-length control OUT transfers
(https://github.com/xairy/raw-gadget/issues/71);
- Contain USB_GADGET_DELAYED_STATUS within composite framework
(https://github.com/xairy/raw-gadget/issues/70);
- Support isochronous transfers in Dummy HCD/UDC
(https://github.com/xairy/raw-gadget/issues/72);
- Fix dwc2 issuing disconnect instead of reset
(https://github.com/xairy/raw-gadget/issues/48);
- dwc3 doesn't support low speed, even through a comment says every
UDC must (https://github.com/xairy/raw-gadget/issues/41#issuecomment-1783022764).
> PS: There's another weakness in the Gadget API which you might possibly
> run across in your project. It's less likely to arise because it
> involves lengthy delays.
>
> Say there's a control transfer with delayed status, and the gadget
> driver delays for so long that the host times out the transfer. Then
> the host starts a new control transfer before the gadget driver queues
> its status reply. Since the Gadget API doesn't have any way to indicate
> which control transfer a usb_request was meant for, the reply that was
> meant for the old transfer would get sent to the host, and the host
> would think it was a reply to the new transfer.
>
> This problem could be solved by adding a unique ID tag to each
> usb_request, and passing the transfer ID as an extra argument to the
> gadget driver's setup() callback. That would explicitly indicate which
> transfer a request was meant for. But doing this would also require
> updating every function driver and every UDC driver. Probably not worth
> the effort, considering how unlikely it is that the situation will ever
> arise.
Ah, good to know! My experience confirms that this is unlikely: I
haven't hit this issue in practice yet.
P.S. By the way, I've been lately using the dwc3-based UDC built into
one of my ThinkPad laptops for testing gadget drivers. I had to switch
a hidden BIOS option to enable it (which was not straightforward), but
it's nice to avoid dealing with external boards. I've written an
article about this, in case you're interested:
https://xairy.io/articles/thinkpad-xdci.
Thank you!
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS
2024-06-16 22:42 ` Andrey Konovalov
@ 2024-06-17 2:10 ` Alan Stern
2024-06-17 6:29 ` Greg KH
0 siblings, 1 reply; 12+ messages in thread
From: Alan Stern @ 2024-06-17 2:10 UTC (permalink / raw)
To: Andrey Konovalov; +Cc: USB list, Paul Elder
On Mon, Jun 17, 2024 at 12:42:56AM +0200, Andrey Konovalov wrote:
> I've been collecting different kinds of non-critical issues and
> inconsistencies within the Gadget subsystem I hit while testing Raw
> Gadget. It's unlikely I'll get to working on them in the foreseeable
> future, but it's good to know what needs fixing should the need arise.
>
> So far, I have:
>
> - Allow stalling non-0-length control OUT transfers
> (https://github.com/xairy/raw-gadget/issues/71);
> - Contain USB_GADGET_DELAYED_STATUS within composite framework
> (https://github.com/xairy/raw-gadget/issues/70);
> - Support isochronous transfers in Dummy HCD/UDC
> (https://github.com/xairy/raw-gadget/issues/72);
As it happens, I wrote a patch (meant mainly for testing, not production
use) that implemented a start at isochronous support in dummy-hcd. It
was far from complete, but it could be expanded.
However, it's another thing I have lost track of. It may have been
posted to linux-usb at one point, but that would have been quite some
time ago. Probably before well lore.kernel.org existed. (I vaguely
remember working on it before moving to my current home, which means
in 2008 or earlier.)
Alan Stern
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS
2024-06-17 2:10 ` Alan Stern
@ 2024-06-17 6:29 ` Greg KH
2024-06-17 15:02 ` Partial isochronous support for dummy-hcd [was: Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS] Alan Stern
0 siblings, 1 reply; 12+ messages in thread
From: Greg KH @ 2024-06-17 6:29 UTC (permalink / raw)
To: Alan Stern; +Cc: Andrey Konovalov, USB list, Paul Elder
On Sun, Jun 16, 2024 at 10:10:33PM -0400, Alan Stern wrote:
> However, it's another thing I have lost track of. It may have been
> posted to linux-usb at one point, but that would have been quite some
> time ago. Probably before well lore.kernel.org existed. (I vaguely
> remember working on it before moving to my current home, which means
> in 2008 or earlier.)
I think lore is populated with all of the linux-usb mailing list
archives, but we might have missed from before when there was -user and
-devel versions of the list.
If needed, I can try to dig up my older archives from cold storage and
get Konstantin to import them.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 12+ messages in thread
* Partial isochronous support for dummy-hcd [was: Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS]
2024-06-17 6:29 ` Greg KH
@ 2024-06-17 15:02 ` Alan Stern
0 siblings, 0 replies; 12+ messages in thread
From: Alan Stern @ 2024-06-17 15:02 UTC (permalink / raw)
To: Greg KH; +Cc: Andrey Konovalov, USB list, Paul Elder
On Mon, Jun 17, 2024 at 08:29:12AM +0200, Greg KH wrote:
> On Sun, Jun 16, 2024 at 10:10:33PM -0400, Alan Stern wrote:
> > However, it's another thing I have lost track of. It may have been
> > posted to linux-usb at one point, but that would have been quite some
> > time ago. Probably before well lore.kernel.org existed. (I vaguely
> > remember working on it before moving to my current home, which means
> > in 2008 or earlier.)
>
> I think lore is populated with all of the linux-usb mailing list
> archives, but we might have missed from before when there was -user and
> -devel versions of the list.
>
> If needed, I can try to dig up my older archives from cold storage and
> get Konstantin to import them.
No need -- I found a copy of it on an old backup drive. It probably got
left behind when I switched my system over from using 32-bit userspace
to 64 bits.
For the record, the patch is appended below. The file on the backup
drive was dated May 2006 (before the 2.6.17 kernel was released!); the
original work may have been even earlier.
Alan Stern
Index: usb/drivers/usb/gadget/dummy_hcd.c
===================================================================
--- usb.orig/drivers/usb/gadget/dummy_hcd.c
+++ usb/drivers/usb/gadget/dummy_hcd.c
@@ -84,6 +84,9 @@ struct dummy_ep {
struct usb_gadget *gadget;
const struct usb_endpoint_descriptor *desc;
struct usb_ep ep;
+ int iso_desc_num;
+ int iso_status;
+ int interval_left;
unsigned halted : 1;
unsigned already_seen : 1;
unsigned setup_stage : 1;
@@ -808,6 +811,7 @@ usb_gadget_register_driver (struct usb_g
dum->gadget.ep0 = &dum->ep [0].ep;
dum->ep [0].ep.maxpacket = 64;
+ dum->ep [0].setup_stage = 1;
list_del_init (&dum->ep [0].ep.ep_list);
INIT_LIST_HEAD(&dum->fifo_req.queue);
@@ -1017,8 +1021,7 @@ static int dummy_urb_enqueue (
list_add_tail (&urbp->urbp_list, &dum->urbp_list);
urb->hcpriv = urbp;
- if (usb_pipetype (urb->pipe) == PIPE_CONTROL)
- urb->error_count = 1; /* mark as a new urb */
+ urb->error_count = 0;
/* kick the scheduler, it'll do the rest */
if (!timer_pending (&dum->timer))
@@ -1056,13 +1059,44 @@ static int
transfer (struct dummy *dum, struct urb *urb, struct dummy_ep *ep, int limit)
{
struct dummy_request *req;
+ struct usb_iso_packet_descriptor *iso;
+ int to_host;
+
+ to_host = usb_pipein (urb->pipe);
+ iso = NULL;
+ if (usb_pipetype (urb->pipe) == PIPE_ISOCHRONOUS)
+ iso = &urb->iso_frame_desc [ep->iso_desc_num];
top:
+ /* isochronous transfers go through even without a responder */
+ if (iso && list_empty (&ep->queue)) {
+ int limit2 = limit;
+ int maxlen = ep->ep.maxpacket;
+
+ while (maxlen <= limit2) {
+ limit2 -= maxlen;
+ if (to_host)
+ ep->iso_status = iso->status = -EPROTO;
+ else {
+ iso->status = 0;
+ iso->actual_length = iso->length;
+ urb->actual_length += iso->length;
+ }
+ ++iso;
+ if (++ep->iso_desc_num >= urb->number_of_packets) {
+ maybe_set_status (urb, ep->iso_status);
+ break;
+ }
+ }
+ return limit;
+ }
+
/* if there's no request queued, the device is NAKing; return */
list_for_each_entry (req, &ep->queue, queue) {
unsigned host_len, dev_len, len;
- int is_short, to_host;
+ int is_short;
int rescan = 0;
+ int ustatus;
/* 1..N packets of ep->ep.maxpacket each ... the last one
* may be short (including zero length).
@@ -1071,24 +1105,22 @@ top:
* (length mod maxpacket zero, and 'zero' flag); they always
* terminate reads.
*/
- host_len = urb->transfer_buffer_length - urb->actual_length;
+ host_len = (iso ? iso->length : urb->transfer_buffer_length -
+ urb->actual_length);
dev_len = req->req.length - req->req.actual;
len = min (host_len, dev_len);
/* FIXME update emulated data toggle too */
- to_host = usb_pipein (urb->pipe);
if (unlikely (len == 0))
is_short = 1;
else {
char *ubuf, *rbuf;
/* not enough bandwidth left? */
- if (limit < ep->ep.maxpacket && limit < len)
+ if (limit < ep->ep.maxpacket && limit < host_len)
break;
len = min (len, (unsigned) limit);
- if (len == 0)
- break;
/* use an extra pass for the final short packet */
if (len > ep->ep.maxpacket) {
@@ -1098,15 +1130,15 @@ top:
is_short = (len % ep->ep.maxpacket) != 0;
/* else transfer packet(s) */
- ubuf = urb->transfer_buffer + urb->actual_length;
+ ubuf = urb->transfer_buffer + (iso ?
+ iso->offset : urb->actual_length);
rbuf = req->req.buf + req->req.actual;
if (to_host)
memcpy (ubuf, rbuf, len);
else
memcpy (rbuf, ubuf, len);
- ep->last_io = jiffies;
- limit -= len;
+ limit -= (iso ? ep->ep.maxpacket : len);
urb->actual_length += len;
req->req.actual += len;
}
@@ -1119,21 +1151,18 @@ top:
* need to emulate such data-in-flight. so we only show part
* of the URB_SHORT_NOT_OK effect: completion status.
*/
+ ustatus = 0;
if (is_short) {
if (host_len == dev_len) {
req->req.status = 0;
- maybe_set_status (urb, 0);
} else if (to_host) {
req->req.status = 0;
if (dev_len > host_len)
- maybe_set_status (urb, -EOVERFLOW);
- else
- maybe_set_status (urb,
- (urb->transfer_flags
- & URB_SHORT_NOT_OK)
- ? -EREMOTEIO : 0);
- } else if (!to_host) {
- maybe_set_status (urb, 0);
+ ustatus = -EOVERFLOW;
+ else if (urb->transfer_flags &
+ URB_SHORT_NOT_OK)
+ ustatus = -EREMOTEIO;
+ } else {
if (host_len > dev_len)
req->req.status = -EOVERFLOW;
else
@@ -1147,10 +1176,25 @@ top:
req->req.status = 0;
if (urb->transfer_buffer_length == urb->actual_length
&& !(urb->transfer_flags
- & URB_ZERO_PACKET)) {
- maybe_set_status (urb, 0);
+ & URB_ZERO_PACKET))
+ ; /* URB is done */
+ else if (!iso)
+ ustatus = 1; /* URB continues */
+ }
+
+ if (iso) {
+ iso->actual_length = len;
+ iso->status = ustatus;
+ if (ustatus) {
+ ep->iso_status = ustatus;
+ ++urb->error_count;
}
+ ++iso;
+ if (++ep->iso_desc_num >= urb->number_of_packets)
+ maybe_set_status (urb, ep->iso_status);
}
+ else if (ustatus <= 0)
+ maybe_set_status (urb, ustatus);
/* device side completion --> continuable */
if (req->req.status != -EINPROGRESS) {
@@ -1309,10 +1353,6 @@ restart:
if (ep->already_seen)
continue;
ep->already_seen = 1;
- if (ep == &dum->ep [0] && urb->error_count) {
- ep->setup_stage = 1; /* a new urb */
- urb->error_count = 0;
- }
if (ep->halted && !ep->setup_stage) {
/* NOTE: must not be iso! */
dev_dbg (dummy_dev(dum), "ep %s halted, urb %p\n",
@@ -1323,7 +1363,7 @@ restart:
/* FIXME make sure both ends agree on maxpacket */
/* handle control requests */
- if (ep == &dum->ep [0] && ep->setup_stage) {
+ if (ep->setup_stage) {
struct usb_ctrlrequest setup;
int value = 1;
struct dummy_ep *ep2;
@@ -1483,7 +1523,7 @@ restart:
if (value >= 0) {
/* no delays (max 64KB data stage) */
limit = 64*1024;
- goto treat_control_like_bulk;
+ goto treat_like_bulk;
}
/* error, see below */
}
@@ -1504,25 +1544,24 @@ restart:
limit = total;
switch (usb_pipetype (urb->pipe)) {
case PIPE_ISOCHRONOUS:
- /* FIXME is it urb->interval since the last xfer?
- * use urb->iso_frame_desc[i].
- * complete whether or not ep has requests queued.
- * report random errors, to debug drivers.
+ /* FIXME: report random errors, to debug drivers.
*/
+ if (--ep->interval_left > 0)
+ break;
+ ep->interval_left = urb->interval;
limit = max (limit, periodic_bytes (dum, ep));
- maybe_set_status (urb, -ENOSYS);
- break;
+ goto treat_like_bulk;
case PIPE_INTERRUPT:
- /* FIXME is it urb->interval since the last xfer?
- * this almost certainly polls too fast.
- */
+ if (--ep->interval_left > 0)
+ break;
+ ep->interval_left = urb->interval;
limit = max (limit, periodic_bytes (dum, ep));
/* FALLTHROUGH */
// case PIPE_BULK: case PIPE_CONTROL:
default:
- treat_control_like_bulk:
+ treat_like_bulk:
ep->last_io = jiffies;
total = transfer (dum, urb, ep, limit);
break;
@@ -1536,8 +1575,13 @@ return_urb:
urb->hcpriv = NULL;
list_del (&urbp->urbp_list);
kfree (urbp);
- if (ep)
- ep->already_seen = ep->setup_stage = 0;
+ if (ep) {
+ ep->already_seen = 0;
+ ep->iso_desc_num = 0;
+ ep->iso_status = 0;
+ if (ep == &dum->ep [0])
+ ep->setup_stage = 1;
+ }
spin_unlock (&dum->lock);
usb_hcd_giveback_urb (dummy_to_hcd(dum), urb, NULL);
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS
2024-06-16 2:33 ` Alan Stern
2024-06-16 22:42 ` Andrey Konovalov
@ 2024-06-19 1:44 ` Paul Elder
2024-06-19 1:46 ` Alan Stern
2024-06-20 12:57 ` Andrey Konovalov
1 sibling, 2 replies; 12+ messages in thread
From: Paul Elder @ 2024-06-19 1:44 UTC (permalink / raw)
To: Alan Stern; +Cc: Andrey Konovalov, USB list
On Sat, Jun 15, 2024 at 10:33:28PM -0400, Alan Stern wrote:
> On Sat, Jun 15, 2024 at 10:49:46PM +0200, Andrey Konovalov wrote:
> > On Sat, Jun 15, 2024 at 4:12 AM Alan Stern <stern@rowland.harvard.edu> wrote:
> > > There has been a patch posted to support UDC drivers that don't
> > > automatically acknowledge non-zero-length control-OUT transfers. But
> > > the patch hasn't been merged, and even if it were, all the existing UDC
> > > drivers would still need to be updated.
> >
> > This series below is the one you're referring to, right?
> >
> > https://lore.kernel.org/linux-kernel/20190124030228.19840-1-paul.elder@ideasonboard.com/
>
> Yes, that's it. I'm impressed that you were able to find it; I had lost
> track of it.
>
> > Do you know why it wasn't merged? (CC Paul). There are no comments on
> > the latest version I managed to find.
>
> I guess Felipe Balbi (the USB Gadget maintainer at the time) just wasn't
> very interested in fixing the problem.
So that's why we never continued with merging it...
Is it time to dust it off and try to upstream it again? :)
Paul
>
> > Also, just to check my understanding: with that series in place and
> > assuming the UDC drivers are updated, a gadget driver would need to
> > first do usb_ep_queue with the proper length and explicit_status ==
> > true to get the data for the control OUT request, and then either do
> > usb_ep_queue again with length 0 to ack or do usb_ep_set_halt to
> > stall?
>
> Yes, that's how it worked. Alternatively, if the gadget driver didn't
> set explicit_status in the control-OUT request then the UDC core would
> automatically call usb_ep_queue again with a 0-length transfer to send
> the status. That way existing gadget drivers would continue to work
> after the UDC drivers were updated, and updated UDC drivers wouldn't
> have to worry about doing an automatic acknowledge only some of the
> time.
>
> Note that in order to avoid breaking things during the transition
> period, it would also be necessary to add a flag to the usb_gadget
> structure, indicating that the UDC driver has been updated to support
> explicit_status.
>
> Alan Stern
>
> PS: There's another weakness in the Gadget API which you might possibly
> run across in your project. It's less likely to arise because it
> involves lengthy delays.
>
> Say there's a control transfer with delayed status, and the gadget
> driver delays for so long that the host times out the transfer. Then
> the host starts a new control transfer before the gadget driver queues
> its status reply. Since the Gadget API doesn't have any way to indicate
> which control transfer a usb_request was meant for, the reply that was
> meant for the old transfer would get sent to the host, and the host
> would think it was a reply to the new transfer.
>
> This problem could be solved by adding a unique ID tag to each
> usb_request, and passing the transfer ID as an extra argument to the
> gadget driver's setup() callback. That would explicitly indicate which
> transfer a request was meant for. But doing this would also require
> updating every function driver and every UDC driver. Probably not worth
> the effort, considering how unlikely it is that the situation will ever
> arise.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS
2024-06-19 1:44 ` Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS Paul Elder
@ 2024-06-19 1:46 ` Alan Stern
2024-06-20 12:57 ` Andrey Konovalov
1 sibling, 0 replies; 12+ messages in thread
From: Alan Stern @ 2024-06-19 1:46 UTC (permalink / raw)
To: Paul Elder; +Cc: Andrey Konovalov, USB list
On Wed, Jun 19, 2024 at 10:44:15AM +0900, Paul Elder wrote:
> On Sat, Jun 15, 2024 at 10:33:28PM -0400, Alan Stern wrote:
> > On Sat, Jun 15, 2024 at 10:49:46PM +0200, Andrey Konovalov wrote:
> > > On Sat, Jun 15, 2024 at 4:12 AM Alan Stern <stern@rowland.harvard.edu> wrote:
> > > > There has been a patch posted to support UDC drivers that don't
> > > > automatically acknowledge non-zero-length control-OUT transfers. But
> > > > the patch hasn't been merged, and even if it were, all the existing UDC
> > > > drivers would still need to be updated.
> > >
> > > This series below is the one you're referring to, right?
> > >
> > > https://lore.kernel.org/linux-kernel/20190124030228.19840-1-paul.elder@ideasonboard.com/
> >
> > Yes, that's it. I'm impressed that you were able to find it; I had lost
> > track of it.
> >
> > > Do you know why it wasn't merged? (CC Paul). There are no comments on
> > > the latest version I managed to find.
> >
> > I guess Felipe Balbi (the USB Gadget maintainer at the time) just wasn't
> > very interested in fixing the problem.
>
> So that's why we never continued with merging it...
>
> Is it time to dust it off and try to upstream it again? :)
You certainly could try. But be sure to add a supports_explicit_status
flag to the usb_gadget structure.
Alan Stern
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS
2024-06-19 1:44 ` Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS Paul Elder
2024-06-19 1:46 ` Alan Stern
@ 2024-06-20 12:57 ` Andrey Konovalov
2024-06-21 7:12 ` Paul Elder
1 sibling, 1 reply; 12+ messages in thread
From: Andrey Konovalov @ 2024-06-20 12:57 UTC (permalink / raw)
To: Paul Elder; +Cc: Alan Stern, USB list
On Wed, Jun 19, 2024 at 3:44 AM Paul Elder <paul.elder@ideasonboard.com> wrote:
>
> > > This series below is the one you're referring to, right?
> > >
> > > https://lore.kernel.org/linux-kernel/20190124030228.19840-1-paul.elder@ideasonboard.com/
> >
> > Yes, that's it. I'm impressed that you were able to find it; I had lost
> > track of it.
> >
> > > Do you know why it wasn't merged? (CC Paul). There are no comments on
> > > the latest version I managed to find.
> >
> > I guess Felipe Balbi (the USB Gadget maintainer at the time) just wasn't
> > very interested in fixing the problem.
>
> So that's why we never continued with merging it...
>
> Is it time to dust it off and try to upstream it again? :)
Thank would be awesome! :)
If you get around to it, I can add Raw Gadget integration on top and test it.
Do you know, what would be the better board to get with an MUSB UDC
for testing? Ideally, something that supports the mainline kernel.
Thanks!
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS
2024-06-20 12:57 ` Andrey Konovalov
@ 2024-06-21 7:12 ` Paul Elder
0 siblings, 0 replies; 12+ messages in thread
From: Paul Elder @ 2024-06-21 7:12 UTC (permalink / raw)
To: Andrey Konovalov; +Cc: Alan Stern, USB list
On Thu, Jun 20, 2024 at 02:57:34PM +0200, Andrey Konovalov wrote:
> On Wed, Jun 19, 2024 at 3:44 AM Paul Elder <paul.elder@ideasonboard.com> wrote:
> >
> > > > This series below is the one you're referring to, right?
> > > >
> > > > https://lore.kernel.org/linux-kernel/20190124030228.19840-1-paul.elder@ideasonboard.com/
> > >
> > > Yes, that's it. I'm impressed that you were able to find it; I had lost
> > > track of it.
> > >
> > > > Do you know why it wasn't merged? (CC Paul). There are no comments on
> > > > the latest version I managed to find.
> > >
> > > I guess Felipe Balbi (the USB Gadget maintainer at the time) just wasn't
> > > very interested in fixing the problem.
> >
> > So that's why we never continued with merging it...
> >
> > Is it time to dust it off and try to upstream it again? :)
>
> Thank would be awesome! :)
>
> If you get around to it, I can add Raw Gadget integration on top and test it.
>
> Do you know, what would be the better board to get with an MUSB UDC
> for testing? Ideally, something that supports the mainline kernel.
The one that I used last time was a Pandaboard ES, but also it was 4.18
back then so it's got a lot of dust...
Paul
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2024-06-21 7:13 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-14 22:31 Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS Andrey Konovalov
2024-06-15 2:12 ` Alan Stern
2024-06-15 20:49 ` Andrey Konovalov
2024-06-16 2:33 ` Alan Stern
2024-06-16 22:42 ` Andrey Konovalov
2024-06-17 2:10 ` Alan Stern
2024-06-17 6:29 ` Greg KH
2024-06-17 15:02 ` Partial isochronous support for dummy-hcd [was: Re: Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS] Alan Stern
2024-06-19 1:44 ` Stalling non-0-length OUT control requests in Raw Gadget/GadgetFS Paul Elder
2024-06-19 1:46 ` Alan Stern
2024-06-20 12:57 ` Andrey Konovalov
2024-06-21 7:12 ` Paul Elder
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox