USB3 Vendor Request

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

cross mob
LiMa_282146
Level 4
Level 4
First like given

Hi,

   

Would you have some example code that shows how to implement a Vendor Request in the FX3?

   

Thanks

0 Likes
20 Replies
Anonymous
Not applicable

At this moment we don't have FX3 example project for vendor request. Sorry for the inconvenience.

   

Regards,

   

Anand

0 Likes
LiMa_282146
Level 4
Level 4
First like given

Hi,

   

I was able to modify the UVC firmware example so that vendor requests could be handled. The UVC example makes use of class requests  to control operation of the FX3 and this very similar to how vendor requests are handled. I’ve described below the steps necessary to implement  a simple vendor request for the FX3. The vendor request out transfer sends data to the FX3 while the vendor request in transfer reads this data back but multiplied by 2.  In some case code comments have been removed to allow easier reading.The steps to implement vendor requests in the FX3  are:

   

 

   

Add separate thread in the CyFxApplicationDefine function to deal with the vendor requests

   

 

   

ptr2 = CyU3PMemAlloc (VndReq_EP0_THREAD_STACK);

   

retThrdCreate = CyU3PThreadCreate (&vndAppEP0Thread,

   

                       "31:Vendor EP0 Thread",     

   

                       VndReqEP0Thread_Entry,      

   

                       0,                          

   

                       ptr2,                       

   

                       VndReq_EP0_THREAD_STACK,    

   

                       VndReq_EP0_THREAD_PRIORITY, 

   

                       VndReq_EP0_THREAD_PRIORITY, 

   

                       CYU3P_NO_TIME_SLICE,        

   

                       CYU3P_AUTO_START            

   

                       );

   

 

   

/* Check the return code */

   

if (retThrdCreate != 0)

   

{

   

    /* Application cannot continue */

   

    /* Loop indefinitely */

   

    while(1);

   

}

   

 

   

Create thread handling function called in this case VndReqEP0Thread_Entry. This function will carry out the vendor request actions.

   

 

   

void

   

VndReqEP0Thread_Entry (

   

        uint32_t input)

   

{

   

 

   

    uint32_t flag;

   

    uint16_t readcount;

   

    uint8_t i;

   

  

   

    CyU3PReturnStatus_t apiRetStatus;

   

  

   

    for (;;)

   

    {

   

        /* Check for Vendor request event */

   

        if (CyU3PEventGet (&glFxVREQEvent, (CY_FX_VREQ_RD | CY_FX_VREQ_WR) ,

   

                           CYU3P_EVENT_OR_CLEAR, &flag,

   

                           CYU3P_WAIT_FOREVER) == CY_U3P_SUCCESS)

   

        {

   

            /* Check for Vendor request upload event */

   

            if (flag & CY_FX_VREQ_RD)

   

            {

   

               

   

            // multiply download data by 2

   

                     for (i = 0; i < 16; i++)

   

                     Ep0_OutData = Ep0_InData * 2;

   

                               

   

                     apiRetStatus = CyU3PUsbSendEP0Data(16, Ep0_OutData);

   

                     if (apiRetStatus != CY_U3P_SUCCESS)

   

                     {

   

                       /* Error handling */

   

                       CyU3PDebugPrint (4, "EP0 Send Data Failed, Error Code = %d\n",apiRetStatus);

   

                     }

   

            }

   

             /* Check for Vendor request download event */

   

            else if (flag & CY_FX_VREQ_WR)

   

            apiRetStatus = CyU3PUsbGetEP0Data(16, Ep0_InData, &readcount);

   

                if (apiRetStatus != CY_U3P_SUCCESS)

   

                {

   

                  /* Error handling */

   

                  CyU3PDebugPrint (4, "EP0 Get Data Failed, Error Code = %d\n",apiRetStatus);

   

                }

   

        }

   

 

   

        /* Relinguish the thread */

   

        CyU3PThreadRelinquish ();

   

    }

   

}

   

 

   

 

   

Modify the USB setup call back function (CyFxBulkLpApplnUSBSetupCB) to get the vendor requests and create the event flags

   

 

   

/* Callback to handle the USB Setup Requests */

   

CyBool_t

   

CyFxBulkLpApplnUSBSetupCB (

   

        uint32_t setupdat0, /* SETUP Data 0 */

   

        uint32_t setupdat1  /* SETUP Data 1 */

   

    )

   

{

   

     uint8_t setupReqType, setupReq;

   

    CyU3PReturnStatus_t apiRetStatus;

   

    CyBool_t vndHandleReq = CyFalse;

   

      

   

    /* Obtain Request Type and Request */

   

    setupReqType = (uint8_t)(setupdat0 & CY_FX_USB_SETUP_REQ_TYPE_MASK);

   

    setupReq = (uint8_t)((setupdat0 & CY_FX_USB_SETUP_REQ_MASK) >> 8);

   

       

   

    /* Check for user vendor request */

   

    if (setupReq == CY_FX_VND_REQ1)

   

     {

   

        /* Vendor requests are handled in the application */

   

        vndHandleReq = CyTrue;

   

     

   

        /* Check for vendor request upload */

   

        if (setupReqType == CY_FX_USB_VND_GET_REQ_TYPE)

   

        {

   

                      

   

          apiRetStatus = CyU3PEventSet(&glFxVREQEvent,CY_FX_VREQ_RD,CYU3P_EVENT_OR);

   

          if (apiRetStatus != CY_U3P_SUCCESS)

   

          {

   

            /* Error handling */

   

            CyU3PDebugPrint (4, "Get Vendor Request Event Failed, Error Code = %d\n",apiRetStatus);

   

          }

   

                     }

   

                     /* Check for vendor request download */

   

                     else if (setupReqType == CY_FX_USB_VND_SET_REQ_TYPE)

   

                     apiRetStatus = CyU3PEventSet(&glFxVREQEvent,CY_FX_VREQ_WR,CYU3P_EVENT_OR);

   

          if (apiRetStatus != CY_U3P_SUCCESS)

   

          {

   

             /* Error handling */

   

             CyU3PDebugPrint (4, "Set Vendor Request Event Failed, Error Code = %d\n",apiRetStatus);

   

          }

   

                               

   

Rest of user code follows on from here

   

 

   

Update the  main .h file to include the user vendor requests; event flags variables and variables associated with the new thread.

   

 

   

#define VndReq_EP0_THREAD_STACK       (0x0800)    /* Thread stack size */

   

#define VndReq_EP0_THREAD_PRIORITY    (8)         /* Thread priority */

   

 

   

#define CY_FX_VREQ_RD        (1 << 0)                                  /* rd event flag */

   

#define CY_FX_VREQ_WR        (1 << 1)                                 /* wr event flag */

   

#define CY_FX_VND_REQ1                    (uint8_t)(0xB1) /* Vendor request */

   

#define CY_FX_USB_VND_SET_REQ_TYPE    (uint8_t)(0x40) /* Download */

   

#define CY_FX_USB_VND_GET_REQ_TYPE  (uint8_t)(0xC0) /* Upload */

   

 

   

Add memory buffers to store Ep0 vendor in and out data and event and flag variables.

   

These are added to the main source code file

   

 

   

static CyU3PThread BulkLpAppThread, vndAppEP0Thread;

   

static CyU3PEvent glFxVREQEvent;  // vendor request event flags

   

static uint8_t Ep0_InData[16];   // ep0 in data buffer

   

static uint8_t Ep0_OutData[16];  // ep0 out data buffer

   

void VndReqEP0Thread_Entry (uint32_t);  /* Declaration for the thread entry function */

   

 

   

That’s it.

   

 

   

Sodafarl

0 Likes
Anonymous
Not applicable

Hi !

If I make a application by CyAPI.

How can I send and receive datas byEP0?

Could you give me an example?

0 Likes

Hello,

Please follow up with your query on the below thread..

https://community.cypress.com/thread/37050

Best regards,

Srinath S

0 Likes
Anonymous
Not applicable

Thanks for sharing the code here.

   

Cheers,

   

Anand

0 Likes
Anonymous
Not applicable

Hi Sodafarl,

   

May I know do you need to modify descriptor for supporting vendor request?

   

Wallace

0 Likes
LiMa_282146
Level 4
Level 4
First like given

Hi,

   

You won't need to modify the descriptor  as vendor requests are carried by control endpoint 0 which is always present in a USB device. The example code should work as it is. I think the only thing I forgot in the example code was to declare ptr2 as a pointer in the  CyFxApplicationDefine function.

   

Sodafarl

0 Likes
Anonymous
Not applicable

 Hi sodafarl,

   

Thank you for replying.

   

BR, Wallace

0 Likes
leda_289486
Level 5
Level 5
10 sign-ins 5 sign-ins 100 replies posted

Hi,

   

I understand that used driver on PC side (host) is UVC.

   

How do you transmit the vendor command from PC application to transfer it via UVC driver ?

   

Best Regards,

   

DamL.

0 Likes
LiMa_282146
Level 4
Level 4
First like given

Hi,

   

I used the UVC example firmware to understand how setup requests were being handled by the firmware.
I then modified the code -see above - to deal with vendor requests instead of UVC class requests.
The new vendor request functions were then added to the auto Bulk Loop example firmware compiled and downloaded using the Control Centre application. The new firmware used the standard Cypress USB 3 driver so
I was able to use the Control Centre to check the vendor requests were working.

   

Sodafarl

0 Likes
leda_289486
Level 5
Level 5
10 sign-ins 5 sign-ins 100 replies posted

Hi,

   

thank you for your answer. So you don't use UVC driver on PC side. That's what I didn't understand in your previous posts.

   

I guess it is possible to transmit Vendor-Command through UVC driver from PC side but this requires the device descriptor to be changed. As you said that It didn't need to be changed from your sample code I was making this mistake.

   

Best Regards,

   

DamL

0 Likes
Anonymous
Not applicable

 Hi,

   

First of all, thank you for sharing the Vendor Request code example. 

   

I've merged it into my application, but have been having problems with reading bytes from device. The 

   

apiRetStatus = CyU3PUsbSendEP0Data(16, Ep0_OutData);

   

call always returns error code 69 (CY_U3P_ERROR_TIMEOUT) after about 3-5 seconds. I use Control Centre Application to initiate the transaction over EP0. Do you have any ideas why this call timesout? 

   

Many thank!

   

OlegS

0 Likes
LiMa_282146
Level 4
Level 4
First like given

Hi,

   

Are you able to write bytes out to the device?  Do you write bytes out to the device before trying to read bytes back in?

   

Have you tried reading bytes in before sending bytes out to the device - it might be sending bytes to the device that is causing the FX3 to timeout. I tried the code again and it workded fine. How is the Cypress Control Panel application setup to perform the Vendor request. For a Vendor requets to read bytes it should be

   

Direction IN Req Type Vendor  Target Device

   

Req Code your request code

   

Sodafarl

0 Likes
Anonymous
Not applicable

 Hi Sodafarl,

   

I recreated a project using cyfxbulklpauto example. I had to make a small change to your code and add txApiRetStatus = CyU3PEventCreate(&glFxVREQEvent); to CyFxBulkLpApplnInit (void) so the flags are initialized. BY the way, I'm using Beta 3 SDK and testing on USB 2.0 port.

   

After the compiling and loading code using Control Centre device re-enumerates and I'm using Control Centre application to Write and Read.

   

First I try writing to a device using Control Panel and Set the following:

   

Bytes To Transfer=16

   

Direction=Out

   

Req Type=Vendor

   

Target=Device

   

Req Code=0xB1 (per example)

   

The Control Panel returns:

   

   

CONTROL OUT transfer 

   

CONTROL OUT transfer failed with Error Code:997

   

and the FX3 debug:

   

EP0 Get Data Failed, Error Code = 69

   

Reading from device has similar behavior:

   

   

CONTROL IN transfer 

   

CONTROL IN transfer failed with Error Code:997

   

and FX3: EP0 Send Data Failed, Error Code = 69

   

In both IN and OUT cases the FX3 code end-up in VndReqEP0Thread and Request and RequestType being parsed to correct values and event is generated, but the CyU3PUsbSendEP0Data() and CyU3PUsbGetEP0Data() always timing out for me. The header file suggests that error code 69 could be EP0 DMA related (returned in case of DMA failure (EP0 DMA channel) but I can't seem to find anything on it yet.

   

Many thanks for your help with this. Please let me know if you spot anything in the steps I'm doing to test.

   

Regards,

   

OlegS

0 Likes
Anonymous
Not applicable

 Hi Sodafarl,

   

Interesting, the code works well when FX3 dev board is connected to USB3.0 and I'm able to do IN and OUT Vendor requests just fine, but not when connected to USB2.0 bus.

   

Hi Anand,

   

I'm playing with Vendor Request example Sodafarl has kindly provided and I'm able to do IN and OUT transaction when FX3 Dev board is connected to USB3.0 host. However, when FX3 Dev board is connected to USB2.0 host, the Control Center returns: CONTROL OUT transfer failed with Error Code:997 and FX3 CyU3PUsbSendEP0Data() and CyU3PUsbGetEP0Data() calls always return error 69 for me. Please see above messages for details of my setup.

   

I would appreciate any suggestions or recommendations on why the CyU3PUsbSendEP0Data() and CyU3PUsbGetEP0Data() do not seem to process the EP0Data when EP0 request is sent onUSB2.0 bus?

   

 

   

Many thanks,

   

OlegS

0 Likes
Anonymous
Not applicable

 Hello,

   

I'm bumping this thread up so it does not end-up at the bottom unanswered.

   

Regards,

   

OlegS

0 Likes
Anonymous
Not applicable

Hi olegs,

   

I encounterd a similiar situration like you did.

   

when FX3 Dev board is connected to USB2.0 host, the Control Center returns: CONTROL OUT transfer failed with Error Code:997

   

Have you figured this out? Can you kindly advise?

   

Thank a lot

0 Likes
Anonymous
Not applicable

For vendor requests in control panel must be selected control endpoint, req. type. "vendor", target "device", req. code field must be filled with vendor request code.

   

In control panel error 997 is usually visible if is selected direction "out", is clicked transfer data button and is sent to FX3, but firmware does not read data from endpoint (using CyU3PUsbGetEP0Data; for zero length packets most likely should be called CyU3PUsbAckSetup). Or if is selected direction "in", clicked transfer data button, but firmware does not send data to endpoint (using CyU3PUsbSendEP0Data).

   

Tested using USB 2.0 and with above mentioned commands errors 997 are not displayed.

   

Regarding error 69 (decimal), I think that it means timeout.

0 Likes
Anonymous
Not applicable

Hi!

You said control panel I didn't find?

What's that?

Where I can find it out?

Thank you!

0 Likes
Anonymous
Not applicable

For anyone still reading, I put the CyU3PUsbGetEP0Data() function call in the USB event callback, and ensured that there were no debug statements before it. If these precautions are not made, the host may timeout in the time it takes to start the thread or display debug messages.

0 Likes