Fixed lengthy timeouts in the USBtoSerial project if no application on the host is...
authorDean Camera <dean@fourwalledcubicle.com>
Sun, 16 Sep 2012 18:18:07 +0000 (18:18 +0000)
committerDean Camera <dean@fourwalledcubicle.com>
Sun, 16 Sep 2012 18:18:07 +0000 (18:18 +0000)
Fixed lengthy automatic data flushing in the CDC and MIDI device class drivers.

LUFA/DoxygenPages/ChangeLog.txt
LUFA/Drivers/USB/Class/Device/CDCClassDevice.c
LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c
Projects/USBtoSerial/USBtoSerial.c

index 271c23d..e92f026 100644 (file)
@@ -34,6 +34,8 @@
   *  - Library Applications:
   *   - Fixed broken RESET_TOGGLES_LIBUSB_COMPAT compile time option in the AVRISP-MKII project
   *   - Fixed incompatibility in the CDC class bootloader on some systems (thanks to Sylvain Munaut)
   *  - Library Applications:
   *   - Fixed broken RESET_TOGGLES_LIBUSB_COMPAT compile time option in the AVRISP-MKII project
   *   - Fixed incompatibility in the CDC class bootloader on some systems (thanks to Sylvain Munaut)
+  *   - Fixed lengthy timeouts in the USBtoSerial project if no application on the host is consuming data (thanks to Nicolas Saugnier)
+  *   - Fixed lengthy automatic data flushing in the CDC and MIDI device class drivers
   *
   *  \section Sec_ChangeLog120730 Version 120730
   *  <b>New:</b>
   *
   *  \section Sec_ChangeLog120730 Version 120730
   *  <b>New:</b>
index ff0f9bb..61f4be9 100644 (file)
@@ -138,7 +138,10 @@ void CDC_Device_USBTask(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
          return;
 
        #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
          return;
 
        #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
-       CDC_Device_Flush(CDCInterfaceInfo);
+       Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);
+       
+       if (Endpoint_IsINReady())
+         CDC_Device_Flush(CDCInterfaceInfo);
        #endif
 }
 
        #endif
 }
 
index c9553a4..5defa14 100644 (file)
@@ -59,7 +59,10 @@ void MIDI_Device_USBTask(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
          return;
 
        #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
          return;
 
        #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
-       MIDI_Device_Flush(MIDIInterfaceInfo);
+       Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address);
+       
+       if (Endpoint_IsINReady())
+         MIDI_Device_Flush(MIDIInterfaceInfo);
        #endif
 }
 
        #endif
 }
 
index 7fe67da..a0b8de4 100644 (file)
@@ -108,21 +108,32 @@ int main(void)
                uint16_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer);
                if ((TIFR0 & (1 << TOV0)) || (BufferCount > (uint8_t)(sizeof(USARTtoUSB_Buffer_Data) * .75)))
                {
                uint16_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer);
                if ((TIFR0 & (1 << TOV0)) || (BufferCount > (uint8_t)(sizeof(USARTtoUSB_Buffer_Data) * .75)))
                {
-                       /* Clear flush timer expiry flag */
-                       TIFR0 |= (1 << TOV0);
-
-                       /* Read bytes from the USART receive buffer into the USB IN endpoint */
-                       while (BufferCount--)
+                       Endpoint_SelectEndpoint(VirtualSerial_CDC_Interface.Config.DataINEndpoint.Address);
+                       
+                       /* Check if a packet is already enqueued to the host - if so, we shouldn't try to send more data
+                        * until it completes as there is a chance nothing is listening and a lengthy timeout could occur */
+                       if (Endpoint_IsINReady())
                        {
                        {
-                               /* Try to send the next byte of data to the host, abort if there is an error without dequeuing */
-                               if (CDC_Device_SendByte(&VirtualSerial_CDC_Interface,
-                                                       RingBuffer_Peek(&USARTtoUSB_Buffer)) != ENDPOINT_READYWAIT_NoError)
+                               /* Clear flush timer expiry flag */
+                               TIFR0 |= (1 << TOV0);
+                       
+                               /* Never send more than one bank size less one byte to the host at a time, so that we don't block
+                                * while a Zero Length Packet (ZLP) to terminate the transfer is sent if the host isn't listening */
+                               uint8_t BytesToSend = MIN(BufferCount, (CDC_TXRX_EPSIZE - 1));
+
+                               /* Read bytes from the USART receive buffer into the USB IN endpoint */
+                               while (BytesToSend--)
                                {
                                {
-                                       break;
-                               }
+                                       /* Try to send the next byte of data to the host, abort if there is an error without dequeuing */
+                                       if (CDC_Device_SendByte(&VirtualSerial_CDC_Interface,
+                                                                                       RingBuffer_Peek(&USARTtoUSB_Buffer)) != ENDPOINT_READYWAIT_NoError)
+                                       {
+                                               break;
+                                       }
 
 
-                               /* Dequeue the already sent byte from the buffer now we have confirmed that no transmission error occurred */
-                               RingBuffer_Remove(&USARTtoUSB_Buffer);
+                                       /* Dequeue the already sent byte from the buffer now we have confirmed that no transmission error occurred */
+                                       RingBuffer_Remove(&USARTtoUSB_Buffer);
+                               }
                        }
                }
 
                        }
                }