STALL handshake in Control-OUT transaction

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
TaKu_282151
Level 2
Level 2
        Hi, In Control-OUT tansaction, please tell me how to send the STALL to the host after reading all EP0 data. I'd like to determine the result(ACK/STALL) by depending on the received data.   
0 Likes
17 Replies
LiMa_282146
Level 4
Level 4
First like given

Hi,

   

Take a look at the cyfxbulklpautoenum example where  setup requests are handled by the users firmware, with unknown requests setting the stall condition.

   

Sodafarl

0 Likes
TaKu_282151
Level 2
Level 2

Thank you for your reply.

   

 

   

If the handshake result is decided in setup stage, the suggested sample illustrates the method to send STALL.

   

 

   

However, I'd like to know how to send STALL after CyU3PUsbGetEP0Data() call.

   

Because, in some case, the result(ACK or STALL) depends on the received data in data stage.

0 Likes
LiMa_282146
Level 4
Level 4
First like given

Hi,

   

If you look at the bit of code describing the Get Configuration request if the attempt to get the data is unsuccessfull  then the status variable is set to reflect this

   

/* Return the current selected configuration. */
        case CY_U3P_USB_SC_GET_CONFIGURATION:
            glEp0Buffer[0] = glUsbConfiguration;
            status = CyU3PUsbSendEP0Data (wLength, glEp0Buffer);
            break;

   

 

   

Later on when the code comes to decide on the handshake  a stall is set if status was not successful

   

/* If there has been an error, stall EP0 to fail the transaction. */
    if ((isHandled != CyTrue) || (status != CY_U3P_SUCCESS))
    {
        /* This is an unhandled setup command. Stall the EP. */
        CyU3PUsbStall (0, CyTrue, CyFalse);
    }
    else
    {
        CyU3PUsbAckSetup ();
    }
 

   

From this the status phase of a control transfer happens after the data phase (in or out) so I think you should be able to handle the setup request, look at the data and then return a stall or an ack. In the above example the device is returning data over endpoint 0 but it should be the same for the device receiving data.

   

Sodafarl

0 Likes
TaKu_282151
Level 2
Level 2

Hi,

   

in FX3APIGuide(Rev1.0),  6.3.7 CyU3PUSBSetupCb_t

   

Described that :

   

The handling of each setup request will involve one and only one of the following API calls.
•  CyU3PUsbSendEP0Data
•  CyU3PUsbGetEP0Data
•  CyU3PUsbAckSetup
•  CyU3PUsbStall

   

 

   

So, after CyU3PUsbGetEP0Data() call, ACK is sent automatically.

   

 

   

I tested CyU3PUsbStall() call after CyU3PUsbGetEPData(),

   

but, on the host PC, the control transfer API returns success.

   

 

   

Is it the limitation of FX3? I think it is not convenience...

0 Likes
LiMa_282146
Level 4
Level 4
First like given

Hi,

   

I modified the CyFxBulkLpApplnUSBSetupCB function to handle my own vendor commands. If a vendor command is detected within CyFxBulkLpApplnUSBSetupCB it calls my function to handle the vendor requests.
If this vendor function returns false the CyFxBulkLpApplnUSBSetupCB sets the stall bit. I modified one of my vendor commands to check the downloaded payload data and if the value of the first byte  was 2 the vendor function returned false. I tried this code using Cypress Control center and if the payload data contained the value 2 I got the error message
CONTROL OUT transfer failed with Error Code:997
So I think this works. I understand  that the  APIGuide is saying only one type of API call is allowed, however this appears to be different from the example code that Cypress show handling the setup request in firmware where you send data using CyU3PUsbSendEP0Data and if this is not successful you can use the CyU3PUsbStall function

When you registered the callback function CyFxBulkLpApplnUSBSetupCB was fast enumeration set to false see below

CyU3PUsbRegisterSetupCallback(CyFxBulkLpApplnUSBSetupCB, CyFalse);

   

Sodafarl

0 Likes
TaKu_282151
Level 2
Level 2

Hi,

   

I  modified USBBulkLoopAutoEnum example to handle the vendor requets,

   

but,  ControlOUT transfer always successes.

   

(However, if wLength > 32, setup handler returns CyFalse immmediately and  ControlCenter shows error 997).

   

 

   

 

   

There is a piece of the setup handler, colored lines are my additional code.

   


/* Callback to handle the USB setup requests. */
CyBool_t
CyFxBulkLpApplnUSBSetupCB (
        uint32_t setupdat0, /* SETUP Data 0 */
        uint32_t setupdat1  /* SETUP Data 1 */
    )
{
    CyBool_t isHandled = CyTrue;
    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;

    uint8_t  bRequest, bReqType;
    uint8_t  bType, bTarget;
    uint16_t wValue, wIndex, wLength;

    /* Decode the fields from the setup request. */
    bReqType = (setupdat0 & CY_U3P_USB_REQUEST_TYPE_MASK);
    bType    = (bReqType & CY_U3P_USB_TYPE_MASK);
    bTarget  = (bReqType & CY_U3P_USB_TARGET_MASK);
    bRequest = ((setupdat0 & CY_U3P_USB_REQUEST_MASK) >> CY_U3P_USB_REQUEST_POS);
    wValue   = ((setupdat0 & CY_U3P_USB_VALUE_MASK)   >> CY_U3P_USB_VALUE_POS);
    wIndex   = ((setupdat1 & CY_U3P_USB_INDEX_MASK)   >> CY_U3P_USB_INDEX_POS);
    wLength  = ((setupdat1 & CY_U3P_USB_LENGTH_MASK)  >> CY_U3P_USB_LENGTH_POS);

    /* Currently there are no vendor / class request that we handle.
     * Stall EP0 or return CyFalse. */

    if ( (bReqType & 0x80) == 0 && bType == CY_U3P_USB_VENDOR_RQT && wLength >= 1 ){
        wLength = (wLength + 15) & ~15;
            /* in CyU3PGetEP0Data(), count number should be a multiple of 16 bytes. (see cyu3usb.h)
             *    This violation causes an argument error.
             */

        if( wLength > sizeof(glEp0Buffer) )
            return CyFalse;
        if( CyU3PUsbGetEP0Data(wLength, glEp0Buffer, NULL) != CY_U3P_SUCCESS )
            return CyFalse;

        if( glEp0Buffer[0] != 2 ){
            CyU3PUsbAckSetup();
            return CyTrue;
        }else{
            CyU3PUsbStall(0x00, CyTrue, CyFalse);
               
/* Note: There is no change to behavior even if removing CyU3PUsbStall() from here. */
            return CyFalse;
                /* Note: There is no change to behavior even if it returns CyTrue here instead of CyFalse. */
        }
    }

    if (bType != CY_U3P_USB_STANDARD_RQT)
    {
        return CyFalse;
    }

   

                                       (skip following code..)

0 Likes
LiMa_282146
Level 4
Level 4
First like given

Hi,

   

I pasted your code into the USBBulkLoopAutoEnum with no other changes and the control transfer fails if I send the value 2 in the payload data with error code 997. With any other value the control transfer is susscessful. I am running this on a 32 bit Windows XP machine.  I changed the value to 3 and compiled again and this time the control transfer failed on the value 3. I''ve attached the compiled .img file if you would like to try this - fails on 3

   

Sodafarl

0 Likes
LiMa_282146
Level 4
Level 4
First like given

File attached for stall on vendor request - change extension to .img

0 Likes
TaKu_282151
Level 2
Level 2

Hi,

   

I'm using 32bit Windows7.

   

So, I'll test by Windows Xp, too.

0 Likes
TaKu_282151
Level 2
Level 2

Hi,

   

I tested on WindowsXp, but result is not changes.

   

May the SDK Version differ? I'm using Ver 1.0.0.

   

 

   

Could you give me your compiled .img file?

0 Likes
lock attach
Attachments are accessible only for community members.
LiMa_282146
Level 4
Level 4
First like given

Hi,

   

 

   

I tried to send this file before but I'll attach it again. I am also using SDK version 1.0.0

0 Likes
TaKu_282151
Level 2
Level 2

Hi,

   

Thank you for sending the file.

   

 

   

I found that this problem occurs at only USB2.0(HS), not in USB3.0(SS).

   

For both of your .img file and my .img file, at USB3.0, sending 0x03 causes error 997,

   

but at USB2.0, transfer always succeeds.

0 Likes
Anonymous
Not applicable

That is strange. By any chance did you hook up a CATC trace to capture what is happening at the USB bus level?

   

Regards,

   

Anand

0 Likes
TaKu_282151
Level 2
Level 2

Hi,

   

Sorry, I don't have an USB 2.0 or 3.0 analyzer.

   

But I check with an USB 1.0 analyzer in full-speed connection,

   

then, FX3 sends ACK response in status phase.

   

And, in case of calling CyU3PUsbStall() only ( without calling CyU3PGetEP0Data() ),

   

FX3 sends STALL response in data phase (not in status phase).

0 Likes
Anonymous
Not applicable

Hello,

   

if've the same problem with CyU3PUsbGetEP0Data and CyU3PUsbStall.

   

 

   

Is there any example without the issue?

   

I write on UART continously the string given in example "Data tracker: buffers sent: %d.\r\n".
Now if I call the function

   

status = CyU3PUsbGetEP0Data(4096, glEp0Buffer, NULL);

   

there is no more output on UART.

   

My code:

   

[...]

   

uint8_t glEp0Buffer[4096]; //length has to be multiple of 16 bytes

   

[...]

   

switch(vReq) {

   

    case VR_WRITE:
        CyU3PDebugPrint(2, "write\r\n");
        status = CyU3PUsbGetEP0Data(4096, glEp0Buffer, NULL);
        if(CY_U3P_SUCCESS == status ) {
            CyU3PDebugPrint(2, "success\r\n");
        }
        else {
            if(status == CY_U3P_ERROR_BAD_ARGUMENT)
                CyU3PDebugPrint(2, "CY_U3P_ERROR_BAD_ARGUMENT%x\r\n", status );
            else
            CyU3PDebugPrint(2, "error%x\r\n", status );
            CyU3PUsbStall (0, CyTrue, CyFalse);
        }
        break;
    case VR_READ:
        CyU3PDebugPrint(2, "read\r\n");
        status = CyU3PUsbSendEP0Data(4096, glEp0Buffer);
        if(CY_U3P_SUCCESS == status ) {
            CyU3PDebugPrint(2, "success\r\n");
        }
        else {
            CyU3PDebugPrint(2, "error%x\r\n", status );
        }
        break;
    case CY_U3P_USB_TARGET_ENDPT:
        if(wValue == CY_U3P_USBX_FS_EP_HALT) {
            /* Clear stall on the endpoint. */
            CyU3PUsbStall (wIndex, CyFalse, CyTrue);
        }
        break;
}
[...]

0 Likes
Anonymous
Not applicable

On FX3, it is not really possible to stall the status phase of a control transfer after the data phase is completed. This is because the firmware has no control on when the status phase happens and we may end up trying to stall the EP after the status phase is completed. (Essentially, stalling the status phase is a hit or miss operation. It may or may not work depending on how fast you do the stall and how much time the host gives you between data and status). 

    This is why we are documenting that you can use only one of the four APIs (UsbAckSetup, SendEp0Data, GetEp0Data and UsbStall) in response to a control request. Once you have used GetEp0Data to get the data, you cannot call UsbStall to stall the request.
0 Likes
Anonymous
Not applicable

 CY_U3P_USB_VENDOR_RQT:厂商请求

   
    CY_U3P_USB_STANDARD_RQT:USB标准请求    
我要是直接发送CY_U3P_USB_VENDOR_RQT类型的请求就可以,但我要是先发送一个CY_U3P_USB_STANDARD_RQT类型的请求(非USB规定的那十几种标准请求)会返回错误(正常情况下会反回错误,因为没有对这个标准请求进行处理),但我再发送CY_U3P_USB_VENDOR_RQT类型的请求还会反回错误,知道为啥不    
0 Likes