I'm not sure if it's worth discussing this any farther, since the 
controller hardware probably won't support it, but ...

On Wed, 6 Aug 2003, David Brownell wrote:

> Alan Stern wrote:
> 
> > A related issue has to do with setting the HALT feature when the host
> > tries to read/write too much.  The premature end of a bulk-in transfer can
> > be indicated by a short or zero-length packet.  But you recommend avoiding
> > ZLPs, and if the total transfer length is divisible by the packet size
> > then there won't be a short packet.  The correct thing to do is to halt
> > the endpoint when the slave receives an excess IN PID.  But we don't want
> 
> The device will be NAKing in such cases, when the host asks for a packet
> and there's no data.  Avoiding ZLPs is mostly a practical matter for protocols,
> since not all hardware handles them ... if you're working with hardware that
> handles them, and with a device protocol where the host will read them, by all
> means write a ZLP to the host.  It "ought to work" just fine.
> 
> Sending an automagic STALL response to the host would be wrong; the controller
> driver can't even know if an IN is "excess" or just "early" (before the
> gadget driver had quite finished preparing the data).
> 
> Example:  if the host writes READ_10, the gadget driver will read that and
> start processing it.  The host will usually try to read the data bytes next,
> but the gadget might not be able to write any until a disk delivers the data.
> It would be incorrect to STALL ... but it's very correct to NAK.

The controller can know when to STALL if the gadget driver tells it, by 
setting a bit flag in the usb_request, meaning: HALT the endpoint if the 
host tries to read/write any more once this request is finished.

However, for my purposes a ZLP will probably do as well.

> > to halt if there is no excess IN request, because in that case the host
> > shouldn't have to clear the halt.  That means there has to be a way to set
> > the state of a bulk endpoint so that it responds to the host by halting
> > but otherwise remains running, a "conditionally halted" state.  And of 
> > course, the gadget needs to be able to take the endpoint out of this state 
> > back to its normal running state.
> 
> Again, seems like NAK is the answer.  And the way to make the gadget stop
> NAKing is to provide some data for it to deliver to the host:   submit
> a request to that IN endpoint, with its data buffer.
> 
> If a STALL is the right response, then halt the endpoint.  Otherwise the
> only non-error responses are to NAK, or to provide the requested DATA.

What if STALL is only temporarily the right response?  That is, the gadget 
doesn't have any more data to send until the host gives it another 
command.  If the host tries to read more data, it should receive a STALL.  
If it doesn't but sends a new command, then more data will be available 
so a STALL is inappropriate -- and the host shouldn't have to clear one 
if it didn't try to read any excess.

> > Similar reasoning applies to OUT transfers.  We don't want the controller
> > to ACK (and store in its FIFO) excess data that the gadget can't accept;  
> > we want it to stall.  In fact, to avoid races it would be good to add an
> > extra flag bit to struct usb_request, saying that as soon as the request
> > finishes normally the endpoint should be placed in this "conditional-halt"  
> > state.  (For bulk-in requests such a flag isn't necessary because we
> > aren't racing the hardware, but it would be nice to have.)
> 
> This case is a lot harder.  The symmetrical answer is that the device
> NAKs the OUT transfer (or, at high speed, the PING) until you issue a
> read ... but it seems like the people designing hardware don't often
> support that flow control model.  (Likely because it increases latencies,
> and isn't actually necessary.)
> 
> So hardware is usually set up to accept OUT data whenever the endpoint
> is enabled and its FIFO has space.  So if the host managed to find time
> to get the data to that "streaming" endpoint, it'll be there when your
> gadget driver finds time to process it.
> 
> When you're writing a gadget driver this should all be transparent unless
> the device protocol is mis-designed.  But you'll need to know that for
> both IN and OUT transfers, data might still sit in endpoint FIFOs after
> your write (or read, respectively) transfer complete() callback.  Lots
> of driver frameworks act in that same way.

What happens if the host has sent all the data the gadget driver wants,
and is still sending more, has filled the FIFO, and is continuing to send
data?  It will wait while the gadget NAKs.  But the gadget driver won't
know what's going on and hence won't be able to HALT the endpoint, thereby
telling the host that the gadget won't accept any more.

Probably the only answer to these problems will be to let the host timeout 
the transfer.

Alan Stern



-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to