Re: Linux USB file storage gadget with new UDC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 3 Jul 2013, Victor Yeo wrote:

> Hi,
> 
> > I can't tell what's going on in your log.  Look at the
> > FSG_STATE_CONFIG_CHANGE case in handle_exception().  Here's the code:
> >
> >                 rc = do_set_config(fsg, new_config);
> >                 if (fsg->ep0_req_tag != exception_req_tag)
> >                         break;
> >                 if (rc != 0)                    // STALL on errors
> >                         fsg_set_halt(fsg, fsg->ep0);
> >                 else                            // Complete the status stage
> >                         ep0_queue(fsg);
> >                 break;
> >
> > It calls do_set_config().  After that, fsg->ep0_req_tag should be equal
> > to exception_req_tag and rc should be equal to 0.  Therefore the code
> > will call ep0_queue(), which calls usb_ep_queue().
> 
> I found out from printk, the fsg->ep0_req_tag and exception_req_tag
> are not equal,

Than either there is a bug in the UDC (or the UDC driver), or else the 
host doesn't wait for the Set-Config request to complete before sending 
the next request.  What were the values of fsg->ep0_req_tag and 
exception_req_tag?

By searching through the code in file_storage.c, you can easily see
that fsg->ep0_req_tag gets set in only one place: the first line of
fsg_setup().  It is a counter -- it goes up by one every time a new
SETUP packet is received, marking the start of a new control transfer.

You can also see that handle_exception() sets exception_req_tag to
the value of fsg->exception_req_tag, and raise_exception() sets
fsg->exception_req_tag to the value of fsg->ep0_req_tag.  This means
that exception_req_tag holds the counter value as of the time the
exception started.

If the values are different, it means that another control transfer 
started (fsg_setup() was called) between the time when the original 
exception was raised and the time when it was handled.  If the UDC is 
working correctly, the only way for this to happen is if the host sends 
another control request without waiting for the first one to finish.

>  and rc is 0. In standard_setup_req(), case
> USB_REQ_SET_CONFIGURATION, once i add the following code
> 
> if (w_value == 0)
>         fsg->config = 0;
> 
> just before the break; statement, the "Device Descriptor
> Test-Addressed State"  can pass. It seems that Get-Config request from
> host cannot wait, so i have to return the latest config value in
> response to the request.

Almost certainly, the problem is that the UDC told the host that the
Set-Config request was finished before it should have.  The host
thought the request was finished, so it sent the next request -- the
Get-Config -- but the gadget driver was still carrying out the
Set-Config.

> In fact, the "Device Descriptor Test-Addressed State" sometimes
> passes, sometimes fails after my modification. What is the reason of
> DELAYED_STATUS in USB_REQ_SET_CONFIGURATION, and the use of
> handle_exception() to call do_set_config()?

DELAYED_STATUS tells fsg_setup() not to call ep0_queue().  It means
that the request isn't finished yet, so the status isn't known.  The 
status will be reported later, when the request is finished.

handle_exception() is used for things that cannot be carried out in
interrupt context.  fsg_setup() runs in an interrupt handler, so it
can't call do_set_config() or do_set_interface() -- those routines need
to run in process context.  Therefore the USB_REQ_SET_CONFIGURATION
code raises an exception; when the fsg thread handles the exception, it
calls do_set_config().

When your UDC driver calls the gadget driver's .setup() function, how
does it handle the return value?

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux