aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2019-12-15 23:55:15 +0100
committerHarald Welte <laforge@osmocom.org>2019-12-16 00:08:46 +0100
commit5b136021d8c9fe7af4fe5f6be0b1c7edfc55dce2 (patch)
tree94fdc967fc9a5545ccb95430cafa061a77bb3467
parent81f4ef77500cdbe862f5808373d375ae9ec8a853 (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.c8
-rw-r--r--firmware/atmel_softpack_libraries/usb/include/USBD.h2
-rw-r--r--firmware/libcommon/source/host_communication.c8
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);