cancel
Showing results for 
Search instead for 
Did you mean: 

Why is USBD CDC Data OUT Receive callback passed RxLength as a pointer instead of as a value?

Miles1
Associate III

Regarding the definition of the Receive callback in usbd_cdc.h:

typedef struct _USBD_CDC_Itf    
{    
  // ...   
  int8_t (* Receive)(uint8_t *Buf, uint32_t *Len);    
  // ...
} USBD_CDC_ItfTypeDef; 

Passing length as a pointer implies that the callback is supposed to edit this value, but I don't see where the USB library makes use of a modified RxLength (maybe the ECM and RNDIS USB libraries expect this to be edited in the callback, but that's still unclear). For basic CDC operation:

  • Are we even supposed to edit RxLength in the callback?
  • If not, why does the library pass this as a pointer? Passing it as a value would be clearer.

For context, here's where USBD_CDC_DataOut calls the user-provided Receive callback.

I didn't find any clarification about this in UM1734 Rev 4. Search for CDC_Itf_Receive.

I added some additional details in this gist. It's pretty taxing wrestling with the limited formatting tools in this forum. Has ST considered migrating to something with a better UX, such as discourse?

3 REPLIES 3
Miles1
Associate III

Same question applies to the TransmitCplt callback too. Why is Len a pointer? Are we supposed to modify the value of Len within our callback?

typedef struct _USBD_CDC_Itf
{
  // ...
  int8_t (* TransmitCplt)(uint8_t *Buf, uint32_t *Len, uint8_t epnum);
} USBD_CDC_ItfTypeDef;

Uwe Bonnes
Principal III

len has perhaps 2 meanings: As input the length of the provides buffer, as output the length of the received trunk

Miles1
Associate III

Yes, that's one possibility for the Receive callback. The other possibility is the inverse, where the callback sets length to the number of bytes remaining (rather than number of bytes received). The latter seems to be the case for the ECM lib.

/* Process data by application (ie. copy to app buffer or notify user)
      hcdc->RxLength must be reset to zero at the end of the call of this function */
      ((USBD_CDC_ECM_ItfTypeDef *)pdev->pUserData)->Receive(hcdc->RxBuffer, &hcdc->RxLength);

Either of those two behaviors are plausible, or maybe it's the third case where the value is simply ignored. My main gripe here is that this isn't clearly documented (or at least I haven't found these docs yet).

For the TransmitCplt callback, I still don't see how Len as output could be used.