summaryrefslogtreecommitdiffstatshomepage
path: root/stmhal/usbd_cdc_interface.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2014-04-17 00:12:07 +0100
committerDamien George <damien.p.george@gmail.com>2014-04-17 00:12:07 +0100
commitefc22e376f14e40f4e3cf8b1f72d2e089dbae6dc (patch)
tree325104f4f7d4a2dca3acef6fef708a20dfa47e0b /stmhal/usbd_cdc_interface.c
parent28817725fc42df64b409853e002eb1c9d0476cd5 (diff)
downloadmicropython-efc22e376f14e40f4e3cf8b1f72d2e089dbae6dc.tar.gz
micropython-efc22e376f14e40f4e3cf8b1f72d2e089dbae6dc.zip
stmhal: Fix 64-byte USB packet bug properly.
A 64-byte packet is now followed by a 0-byte packet if there is nothing more to send. This flushes the USB endpoint.
Diffstat (limited to 'stmhal/usbd_cdc_interface.c')
-rw-r--r--stmhal/usbd_cdc_interface.c21
1 files changed, 11 insertions, 10 deletions
diff --git a/stmhal/usbd_cdc_interface.c b/stmhal/usbd_cdc_interface.c
index b81ab11b24..b2c85fa4f3 100644
--- a/stmhal/usbd_cdc_interface.c
+++ b/stmhal/usbd_cdc_interface.c
@@ -63,6 +63,7 @@ static uint16_t UserTxBufPtrIn = 0; // increment this pointer modulo APP_TX_DATA
static __IO uint16_t UserTxBufPtrOut = 0; // increment this pointer modulo APP_TX_DATA_SIZE when data is drained
static uint16_t UserTxBufPtrOutShadow = 0; // shadow of above
static uint8_t UserTxBufPtrWaitCount = 0; // used to implement a timeout waiting for low-level USB driver
+static uint8_t UserTxNeedEmptyPacket = 0; // used to flush the USB IN endpoint if the last packet was exactly the endpoint packet size
static int user_interrupt_char = VCP_CHAR_NONE;
static void *user_interrupt_data = NULL;
@@ -257,7 +258,7 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
return;
}
- if (UserTxBufPtrOut == UserTxBufPtrIn) {
+ if (UserTxBufPtrOut == UserTxBufPtrIn && !UserTxNeedEmptyPacket) {
// No outstanding data to send
return;
}
@@ -278,7 +279,7 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
UserTxBufPtrOut = UserTxBufPtrOutShadow;
}
- if (UserTxBufPtrOutShadow != UserTxBufPtrIn) {
+ if (UserTxBufPtrOutShadow != UserTxBufPtrIn || UserTxNeedEmptyPacket) {
uint32_t buffptr;
uint32_t buffsize;
@@ -290,14 +291,6 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
buffptr = UserTxBufPtrOutShadow;
- // dpgeorge: For some reason that I don't understand, a packet size of 64 bytes
- // (CDC_DATA_FS_MAX_PACKET_SIZE) does not get through to the USB host until the
- // next packet is sent. To work around this, we just make sure that we never
- // send a packet 64 bytes in length.
- if (buffsize == CDC_DATA_FS_MAX_PACKET_SIZE) {
- buffsize -= 1;
- }
-
USBD_CDC_SetTxBuffer(&hUSBDDevice, (uint8_t*)&UserTxBuffer[buffptr], buffsize);
if (USBD_CDC_TransmitPacket(&hUSBDDevice) == USBD_OK) {
@@ -306,6 +299,14 @@ void USBD_CDC_HAL_TIM_PeriodElapsedCallback(void) {
UserTxBufPtrOutShadow = 0;
}
UserTxBufPtrWaitCount = 0;
+
+ // According to the USB specification, a packet size of 64 bytes (CDC_DATA_FS_MAX_PACKET_SIZE)
+ // gets held at the USB host until the next packet is sent. This is because a
+ // packet of maximum size is considered to be part of a longer chunk of data, and
+ // the host waits for all data to arrive (ie, waits for a packet < max packet size).
+ // To flush a packet of exactly max packet size, we need to send a zero-size packet.
+ // See eg http://www.cypress.com/?id=4&rID=92719
+ UserTxNeedEmptyPacket = (buffsize == CDC_DATA_FS_MAX_PACKET_SIZE && UserTxBufPtrOutShadow == UserTxBufPtrIn);
}
}
}