Why doesn't scheduling buffers for the next usb receive event work for the first packet?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Why doesn't scheduling buffers for the next usb receive event work for the first packet?

720 Views
lh_dan
Contributor III

I am using CW10.2, MQX 4.0.0.

I added functionality to to the MQX USB Device HID driver to receive data on a HID OUT Endpoint.  I used example code from the CDC driver to do this.  AN4345.pdf is one example.  And it works pretty well.  The sample code for the receive callback is the following:

if((event_type == USB_APP_DATA_RECEIVED)&&(start_transactions == TRUE))

{

     BytesToBeCopied = dp_rcv->data_size;

     for(index = 0; index < BytesToBeCopied; index++)

     {

          g_curr_recv_buf[index] = dp_rcv->data_ptr[index];

     }

     /* Schedule buffer for next receive event */

     USB_Class_CDC_Recv_Data(handle, DIC_BULK_OUT_ENDPOINT, g_curr_recv_buf, DIC_BULK_OUT_ENDP_PACKET_SIZE);

}

Copying the data_ptr to the local buffer only seems to be needed for the first packet received.  After that the copy is not needed because the USB_Class_CDC_Recv_Data() call passes the g_curr_recv_buf pointer into the MQX driver to receive the data.  So it seems to me that the USB_Class_CDC_Recv_Data() call should be able to be made before the first received packet (say after the enumeration event callback) and then the copy would not be needed.  However when I did this, the callback for the first packet is not called at all.  Is there a reason this doesn't work?  Am I required to copy the data everytime even though the data in g_curr_recv_buf & dp_rcv->data_ptr is equal after the first packet?

Labels (1)
Tags (2)
0 Kudos
3 Replies

471 Views
matthewkendall
Contributor V

The buffer you receive the first time the callback is called is allocated down in the depths of the USB stack (allocated on enumeration, unused after the first receive, and freed on disconnection is my understanding, but it is not documented). If the buffer is truly unused within the stack after this first receive you could potentially keep using it (i.e. pass it back to USB_Class_CDC_Recv and not even have g_curr_recv_buf) but the problems with this approach are that we don't know this is true, and don't (officially) know the size of this buffer. So you really have to use your own after the first reception.

If you want to follow the example code closely, the simplest way to avoid the copy is to compare g_curr_recv_buf and dp_rcv->data_ptr. If they are equal, don't bother with the copy. For the copy itself, use memcpy(), it will likely be faster than the loop in the example.

0 Kudos

471 Views
lh_dan
Contributor III

Matthew,

Thanks for the response.  I guess what I was looking for was any documention or information from freescale on the expected behavior because how this works seems odd.  My implemention copies dp_rcv->data_ptr to my local buffer everytime (using memcpy) even though I also call a USB_Class_CDC_Recv_Data equivalent with my local buffer after the first packet is received.  It would be nice if freescale cleaned this up in future MQX versions.

0 Kudos

471 Views
lh_dan
Contributor III

One other thing.  It would be great if we could find out the size of that initial buffer that the stack is using.  We have a vender specific usb protocol that could send packets larger than 64 bytes.  The first packet is not being received correctly until USB_Class_CDC_Recv_Data can be called with a larger buffer.  Right now we work around this by sending a dummy packet that is less than 64bytes just so we can allocate the larger buffer.  This works but is definitely a hack.

0 Kudos