diff --git a/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c b/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c index 0eccc65d..ac2595cc 100644 --- a/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c +++ b/firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c @@ -1077,6 +1077,14 @@ static inline uint8_t UDP_Read(uint8_t bEndpoint, * Exported functions *---------------------------------------------------------------------------*/ + +uint16_t USBD_GetEndpointSize(uint8_t bEndpoint) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + + return pEndpoint->size; +} + /** * USBD (UDP) interrupt handler * Manages device resume, suspend, end of bus reset. diff --git a/firmware/atmel_softpack_libraries/usb/include/USBD.h b/firmware/atmel_softpack_libraries/usb/include/USBD.h index 15a68595..6fc931f1 100644 --- a/firmware/atmel_softpack_libraries/usb/include/USBD.h +++ b/firmware/atmel_softpack_libraries/usb/include/USBD.h @@ -214,6 +214,8 @@ typedef void (*MblTransferCallback)(void *pArg, * Exported functions *------------------------------------------------------------------------------*/ +extern uint16_t USBD_GetEndpointSize(uint8_t bEndpoint); + //extern void USBD_IrqHandler(void); extern void USBD_Init(void); diff --git a/firmware/libcommon/source/host_communication.c b/firmware/libcommon/source/host_communication.c index 0e496c54..9a6e5b32 100644 --- a/firmware/libcommon/source/host_communication.c +++ b/firmware/libcommon/source/host_communication.c @@ -33,10 +33,18 @@ static void usb_write_cb(uint8_t *arg, uint8_t status, uint32_t transferred, { struct msgb *msg = (struct msgb *) arg; struct usb_buffered_ep *bep = msg->dst; + uint16_t ep_size = USBD_GetEndpointSize(bep->ep); unsigned long x; TRACE_DEBUG("%s (EP=0x%02x)\r\n", __func__, bep->ep); + if (((msgb_length(msg) % ep_size) == 0) && (transferred == ep_size)) { + /* terminate with ZLP; pass in 'msg' again as 'arg' so we get + * called the second time and proceed with usb_buf_free below */ + USBD_Write(bep->ep, 0, 0, (TransferCallback) &usb_write_cb, msg); + return; + } + local_irq_save(x); bep->in_progress--; local_irq_restore(x);