Control IN transfer fails when the response size is multiple of packet size.

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

cross mob
lock attach
Attachments are accessible only for community members.
TaKu_282151
Level 2
Level 2

Hi,

   

FX3 Control IN request fails when the response size is:

   
        
  • multilpe of the packet size (64, 128, 192.. for HS, 512, 1024, 1536.. for SS)
  •     
  • smaller than wLength (if response size equals wLength, no problems occur)
  •    
   

The error occurs in PC side (ex, Control Center shows error 997)

   

but in the firmware side, CyU3PUsbSendEP0Data() returns no error.

   

 

   

I guess, in this situation, the last ZLP may be lost.

   

In Setup Request callback, calling additional CyU3PUsbSendEP0Data() with 0 bytes length

   

hides this problem,  like this:

   

 CyU3PUsbSendEP0Data( bytes, buf );

   

if( (bytes % glPacketSize) == 0 )

   

    CyU3PUsbSendEP0Data(0, buf);

   

This workaround code is Appropriate?

   

 

   

 I attach test project.

   

This firmware accepts Vendor-IN Request, and response [wValue] bytes.

   

If wIndex is 1, the workaround is enabled.

   

 

   

Regards.

0 Likes
15 Replies
Anonymous
Not applicable
        Are you trying to read (from pc side) less than what is committed by the firmware? If yes, the psec does not allow that. You can read more than what is committed by firmware but not less.   
0 Likes
TaKu_282151
Level 2
Level 2

>Are you trying to read (from pc side) less than what is committed by the firmware?

   

No.

   

In PC side,  I simply call ControlTransfer Read API (ex.CyUSB.CyControlEndPoint.Read).

   

But the firmware is trying to send less than what is required from the PC.

   

 

   

I understand that the USB device can send fewer size data than wLength

   

in Control-IN transaction.

   

In this situation, if the transmitting size is multiple of packet size,

   

the transfer is not completed.

   

 

   

Regards.
 

0 Likes
TaKu_282151
Level 2
Level 2

Let me apologize I had misunderstanding that CyU3PUsbSendEP0Data() API should be called only once

   

in each control-transfer transaction.

   

But this API can be called two or more times, and the programmer shall create the last ZLP explicitly.

   

 

   

Regards.

0 Likes
Anonymous
Not applicable

 Hi,

   

 

   

Is the issue fixed? I did not understand the issue clearly. What do you mean by terms response size? I understand packet size and wLength. Also, since it is control transfer, when you say packet size, it is 64 byte (max) for EP0 in case of HS; and 512 bytes (max) for EP0 in case of SS. Please clarify as to what is teh MaxPacketsize used for EP0 and what you mean by reposne size?

   

 

   

Regards,

   

Gayathri

0 Likes
TaKu_282151
Level 2
Level 2

Hi,

   

I use the term "packet size" as "MaxPacketSize used for EP0", like you say.

   

But "response size" does not means "wLength".

   

I use this term as "total bytes of the data that USB device will send in the data phase".

   

(Of cause, the maximum size is limited by wLength)

   

 

   

When this "response size" is smaller than wLength, the last packet of sending data must be SLP or ZLP.

   

But FX3 API Guide says in senction 6.3.3.19 CyU3PUsbSendEP0Data:

   

Multiple calls of this function can be made to respond to a single control request as long as each call sends an integral number of full packets to the host.

   

I understand this sentence means "CyU3PUsbSendEP0Data API does not append the last ZLP for termination".

   

Is this right?

   

 

   

Regards.

0 Likes
Anonymous
Not applicable

 Hi,

   

 

   

Yes that is what it means. 

   

 

   

Regards,

   

Gayathri

0 Likes
Anonymous
Not applicable

 Hi,

   

 

   

If your actual data that devcie has to send is less < wLength, and the actual data is it is a multiple of maxPacketSize, then a ZLP should be explicitly sent using SendEpoData API.

   

 

   

Regards,

   

Gayathri

0 Likes
Anonymous
Not applicable
        Hi, is this workaround also relevant in the bootloader API of cypress? Thanks, lumpi   
0 Likes
Anonymous
Not applicable
        Hi, does anybody know how it is with the IN transfer in case of bootloader SDK of FX3? Thanks, lumpi   
0 Likes
Anonymous
Not applicable

Yes Lumpi.

   

Regards,

   

sai krishna.

0 Likes
Anonymous
Not applicable

Hi Sai Krishna,

   

are there any code snippets or example code of bootloader how to implement the ZLP?

   

I believe just adding an additional call of

   

 

   

    if (eDataIn == u32Stage)
    {
        if ((u32Address + pEp0->wLen) < CY_FX3_BOOT_ITCM_END)
        {
            myMemCopy(pEp0->pData, (IS_U8 *)u32Address , u16Len);
        }

        CyFx3BootUsbAckSetup ();
        nRet = CyFx3BootUsbDmaXferData (0x80, (IS_U32)pEp0->pData, pEp0->wLen, USB_DMA_XFER_TIMEOUT_EP0_IN);
        if (nRet != CY_U3P_SUCCESS)
        {
            /* USB DMA Transfer failed. Stall the Endpoint. */
            return nRet;
        }

        if ((pEp0->wLen % g_u32UsbPktSize) == 0)
        {
            nRet = CyFx3BootUsbDmaXferData (0x80, (IS_U32)pEp0->pData, 0, USB_DMA_XFER_TIMEOUT_EP0_IN);
            if (nRet != CY_U3P_SUCCESS)
            {
                /* USB DMA Transfer failed. Stall the Endpoint. */
                return nRet;
            }
        }
    }
 

   

regards,

   

lumpi

0 Likes
Anonymous
Not applicable

Hi,

   

is the ZLP functionality in bootloader working fine when I implement it as I described in previous post?

   

is there an example how to add the ZLP functionality in new bootloader firmware release? Can I get it?

   

regards,

   

lumpi

0 Likes
Anonymous
Not applicable

Hi,

   

is the ZLP functionality in bootloader working fine when I implement it as I described in previous post?

   

is there an example how to add the ZLP functionality in new bootloader firmware release? Can I get it?

   

regards,

   

lumpi

0 Likes
Anonymous
Not applicable

Hi Lumpi,

The issue described in first post is relevant to CyU3PUsbSendEP0Data(). I am not sure that it's characteristic also to bootloader's CyFx3BootUsbDmaXferData function. You should test this first. I remember playing with bootloader about a year ago and then its functions behaved different from application ones - at least I was not able to get single control transfer working with splitting it into multiple calls of CyFx3BootUsbDmaXferData.

Anyway, terminating ZLP is needed only if you return less data from device than the host requested. In your example you do not check this. It's very common for host applications to initiate transfers that are multiple to packet size. And these transfers work with Cypress bootloader.  With your modification, you will send extra ZLP that is not needed/expected.

But why should you return less data than host requests? I see, this can happen only while returning descriptors. And even then only if host tries to get the whole descriptor without asking/checking its length first. Hopefully the descriptors are not multiple to packet size. In vendor requests, when host asks for too much data, you can just fail the request, like the original Cypress bootloader does.

BTW, Cypress has promised to release FX3 API sources in next SDK release. Then it will be  easy to study what the functions actually do and change/fix them according your needs.

Br,
Kalev 

0 Likes
Anonymous
Not applicable

FYI,

   

The same bug still exists in SDK 1.3 FX3 API default setup request handler. For example hosts fail to read 64-byte string (incl. serial number) descriptors in FS/HS mode.

   

Br,

   

Kalev

0 Likes