diff options
author | Harald Welte <laforge@osmocom.org> | 2019-12-15 23:55:15 +0100 |
---|---|---|
committer | Harald Welte <laforge@osmocom.org> | 2019-12-16 00:08:46 +0100 |
commit | 5b136021d8c9fe7af4fe5f6be0b1c7edfc55dce2 (patch) | |
tree | 94fdc967fc9a5545ccb95430cafa061a77bb3467 | |
parent | 81f4ef77500cdbe862f5808373d375ae9ec8a853 (diff) |
host_communication: Send zero-length-packet on wMaxPacketSize
We need to send zero-length packets on bulk endpoints whenever the
transfer size is exactly a multiple of the wMaxPacketSize.
See USB 2.0 Specification Section 5.8.3 titled "Bulk Transfer Packet
Size constraints."
Change-Id: Ice3842399d5a5c4a18383860f81074497c6e7c9b
Closes: OS#4331
-rw-r--r-- | firmware/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c | 8 | ||||
-rw-r--r-- | firmware/atmel_softpack_libraries/usb/include/USBD.h | 2 | ||||
-rw-r--r-- | firmware/libcommon/source/host_communication.c | 8 |
3 files changed, 18 insertions, 0 deletions
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 0eccc65..ac2595c 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 15a6859..6fc931f 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 0e496c5..9a6e5b3 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); |