How Does This USB Transfer Code Work for Packets > 64?
I have a USB HID device based on the STM32L432 that I inherited maintenance on. My particular device has a HID Report Descriptor that is greater than 64 bytes. I'm debugging using an ST-Link and single-stepping, trying to figure out how the code handles transmitting this large packet to the host via EP0, since EP0 has a max packet size of 64.
This code is directly from the STCube libraries (stm32l4xx_ll_usb.c):
HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx , USB_EPTypeDef *ep, uint8_t dma)
{
uint16_t pmabuffer = 0;
uint32_t len = ep->xfer_len;
/* IN endpoint */
if (ep->is_in == 1)
{
/*Multi packet transfer*/
if (ep->xfer_len > ep->maxpacket)
{
len=ep->maxpacket;
ep->xfer_len-=len;
}
else
{
len=ep->xfer_len;
ep->xfer_len =0;
}
/* configure and validate Tx endpoint */
if (ep->doublebuffer == 0)
{
USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, len);
PCD_SET_EP_TX_CNT(USBx, ep->num, len);
}
else
{
/* Write the data to the USB endpoint */
if (PCD_GET_ENDPOINT(USBx, ep->num)& USB_EP_DTOG_TX)
{
/* Set the Double buffer counter for pmabuffer1 */
PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
pmabuffer = ep->pmaaddr1;
}
else
{
/* Set the Double buffer counter for pmabuffer0 */
PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
pmabuffer = ep->pmaaddr0;
}
USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, len);
PCD_FreeUserBuffer(USBx, ep->num, ep->is_in);
}
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID);
}
else /* OUT endpoint */
{
/* Multi packet transfer*/
if (ep->xfer_len > ep->maxpacket)
{
len=ep->maxpacket;
ep->xfer_len-=len;
}
else
{
len=ep->xfer_len;
ep->xfer_len =0;
}
/* configure and validate Rx endpoint */
if (ep->doublebuffer == 0)
{
/*Set RX buffer count*/
PCD_SET_EP_RX_CNT(USBx, ep->num, len);
}
else
{
/*Set the Double buffer counter*/
PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
}
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
}
return HAL_OK;
}I can see where it checks if the buffer size is greater than 64 here, and then subtracts 64 from the buffer length to leave the remaining buffer size to be transferred:
/*Multi packet transfer*/
if (ep->xfer_len > ep->maxpacket)
{
len=ep->maxpacket;
ep->xfer_len-=len;
}
else
{
len=ep->xfer_len;
ep->xfer_len =0;
}But I must be missing something, because it never actually seems to go back and do ANYTHING with that remaining data in the buffer. But the code works: my full 170-byte report descriptor is transferred fine. What am I missing?
