Hello,
I am writing my own USB 2.0 full-speed “device” driver for a STM32F072 microcontroller, but seem to be a bit confused about how / whether the host can abort the Data Stage of an EP0 Control-Write transfer. That is, while the device is waiting for the host to send the required data (for example, during a Set Report Control Transfer request), is the Host "allowed to" abort the process by sending an IN transaction (to start the Status Stage) before the host has sent the device all the expected data ? I know the host can abort the transfer by sending a new Setup request (I can handle this), but I am interested in whether I have to handle the host sending an IN "prematurely".
In Jan Axelson's "USB Complete 4th Edition" on page 96 in "Tips For Successful Enumeration", she says "Be ready to abandon a control transfer or end it early. ....... On receiving an OUT token packet ...... the device must assume the host is beginning the status stage of the transfer even if the device hasn’t sent all of the requested data in the data stage." Jan is obviously talking about a Control-Read here, but does the equivalent apply for a Control-Write ?
In the copy of the USB Spec Rev 2.0 I have, in section 8.5.3 near figure 8-37 it indicates that during a Control-Write it is the arrival of an IN transaction that causes the transition from the Data Stage to the Status Stage. To me this implies that the transition can occur at any point during the data stage, and thus an IN transaction must be accepted at any point during the Data Stage, and cause the data stage (and thus the whole Control-Write transfer) to abort ?
But if this is so, it seems to lead me to a bunch of other problems. It means I cannot have the IN (device out) endpoint set to transmit NAK while I am receiving the Data Stage, as I have to accept the IN transaction to know that the host wants to abort. And what reply do I give to the IN transaction, given that on my target hardware (STM32F072) the reply has to be sitting in the IN (device out) buffer ready to go before the IN arrives ? The only option would seem to be a Zero-Length-Packet (?), but according to the spec that would be telling the host the request completed successfully, which it didn't, because the host didn't send all the required data... ? Maybe instead of NAK'ing the IN endpoint I should STALL it, but what if the Host sends all the data then issues the IN Status Request before I get the endpoint un-STALL-ed, that would be telling the host the request definitely failed, when probably my code just hasn’t had time to process it yet ? And in any case, on my target hardware my code can’t tell when a STALL response is sent, so my code wouldn't know the host has decided to abort the whole transfer...
It seems I'm missing something important here... I hope someone with a clearer understanding of this detail can explain the correct approach to me.
(Yes I know ST offer USB drivers for the STM32s, but there are reasons why I want / need to roll my own on this project)
Thank you for any advice anyone can offer,
mai-au.
Further to my concern above, I now see that under “Control Write Requests with a Data Stage” on page 123 of Jan’s “USB Complete 4th Edition” she says “2. …… The endpoint must also ACK a new Setup Packet ….. and should return a ZLP in response to an IN token packet, which indicates the host is ending the transfer early”. But this troubles me, because returning a ZLP normally indicates the Setup request has been completed successfully, which it hasn’t. It is also unclear to me if this only applies before any data OUT packets have been sent by the host (i.e. before the data stage has started) ? What about when we are part-way through the Data stage, with one or more data packets having been sent by the host but one or more still to come ? Is the host allowed to abort in the middle of this by suddenly sending an IN packet, and if so, what response should the target give in this circumstance ?
Once again, thank you for any advice anyone can offer,
mai-au.