Re-add in old Endpoint/Pipe workaround for unordered pipes - add new ORDERED_EP_CONFI...
[pub/USBasp.git] / Projects / XPLAINBridge / XPLAINBridge.c
index 7272fd8..912e683 100644 (file)
@@ -1,21 +1,21 @@
 /*
              LUFA Library
      Copyright (C) Dean Camera, 2010.
 /*
              LUFA Library
      Copyright (C) Dean Camera, 2010.
-              
+
   dean [at] fourwalledcubicle [dot] com
   dean [at] fourwalledcubicle [dot] com
-      www.fourwalledcubicle.com
+           www.lufa-lib.org
 */
 
 /*
   Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)
 
 */
 
 /*
   Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)
 
-  Permission to use, copy, modify, distribute, and sell this 
+  Permission to use, copy, modify, distribute, and sell this
   software and its documentation for any purpose is hereby granted
   software and its documentation for any purpose is hereby granted
-  without fee, provided that the above copyright notice appear in 
+  without fee, provided that the above copyright notice appear in
   all copies and that both that the copyright notice and this
   all copies and that both that the copyright notice and this
-  permission notice and warranty disclaimer appear in supporting 
-  documentation, and that the name of the author not be used in 
-  advertising or publicity pertaining to distribution of the 
+  permission notice and warranty disclaimer appear in supporting
+  documentation, and that the name of the author not be used in
+  advertising or publicity pertaining to distribution of the
   software without specific, written prior permission.
 
   The author disclaim all warranties with regard to this
   software without specific, written prior permission.
 
   The author disclaim all warranties with regard to this
 /** \file
  *
  *  Main source file for the XPLAINBridge project. This file contains the main tasks of
 /** \file
  *
  *  Main source file for the XPLAINBridge project. This file contains the main tasks of
- *  the demo and is responsible for the initial application hardware configuration.
+ *  the project and is responsible for the initial application hardware configuration.
  */
 
 #include "XPLAINBridge.h"
 
  */
 
 #include "XPLAINBridge.h"
 
-/* Current firmware mode, making the device behave as either a programmer or a USART bridge */
-bool CurrentFirmwareMode = MODE_PDI_PROGRAMMER;
+/** Current firmware mode, making the device behave as either a programmer or a USART bridge */
+bool CurrentFirmwareMode = MODE_USART_BRIDGE;
 
 /** LUFA CDC Class driver interface configuration and state information. This structure is
  *  passed to all CDC Class driver functions, so that multiple instances of the same class
 
 /** LUFA CDC Class driver interface configuration and state information. This structure is
  *  passed to all CDC Class driver functions, so that multiple instances of the same class
@@ -45,7 +45,7 @@ bool CurrentFirmwareMode = MODE_PDI_PROGRAMMER;
  */
 USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
        {
  */
 USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface =
        {
-               .Config = 
+               .Config =
                        {
                                .ControlInterfaceNumber         = 0,
 
                        {
                                .ControlInterfaceNumber         = 0,
 
@@ -100,7 +100,7 @@ void AVRISP_Task(void)
        V2Params_UpdateParamValues();
 
        Endpoint_SelectEndpoint(AVRISP_DATA_OUT_EPNUM);
        V2Params_UpdateParamValues();
 
        Endpoint_SelectEndpoint(AVRISP_DATA_OUT_EPNUM);
-       
+
        /* Check to see if a V2 Protocol command has been received */
        if (Endpoint_IsOUTReceived())
        {
        /* Check to see if a V2 Protocol command has been received */
        if (Endpoint_IsOUTReceived())
        {
@@ -119,19 +119,36 @@ void UARTBridge_Task(void)
        if (USB_DeviceState != DEVICE_STATE_Configured)
          return;
 
        if (USB_DeviceState != DEVICE_STATE_Configured)
          return;
 
-       /* Read bytes from the USB OUT endpoint into the UART transmit buffer */
-       int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
-       if (!(ReceivedByte < 0) && !(RingBuffer_IsFull(&USBtoUART_Buffer)))
-         RingBuffer_AtomicInsert(&USBtoUART_Buffer, CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface));
+       /* Only try to read in bytes from the CDC interface if the transmit buffer is not full */
+       if (!(RingBuffer_IsFull(&USBtoUART_Buffer)))
+       {
+               int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
+
+               /* Read bytes from the USB OUT endpoint into the UART transmit buffer */
+               if (!(ReceivedByte < 0))
+                 RingBuffer_Insert(&USBtoUART_Buffer, ReceivedByte);
+       }
        
        
-       /* Check if the UART receive buffer flush timer has expired */
-       if (TIFR0 & (1 << TOV0))
+       /* Check if the UART receive buffer flush timer has expired or buffer is nearly full */
+       RingBuff_Count_t BufferCount = RingBuffer_GetCount(&UARTtoUSB_Buffer);
+       if ((TIFR0 & (1 << TOV0)) || (BufferCount > 200))
        {
        {
+               /* Clear flush timer expiry flag */
                TIFR0 |= (1 << TOV0);
 
                TIFR0 |= (1 << TOV0);
 
-               /* Read bytes from the UART receive buffer into the USB IN endpoint */
-               while (UARTtoUSB_Buffer.Count)
-                 CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_AtomicRemove(&UARTtoUSB_Buffer));
+               /* Read bytes from the USART receive buffer into the USB IN endpoint */
+               while (BufferCount--)
+               {
+                       /* 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(&UARTtoUSB_Buffer)) != ENDPOINT_READYWAIT_NoError)
+                       {
+                               break;
+                       }
+
+                       /* Dequeue the already sent byte from the buffer now we have confirmed that no transmission error occurred */
+                       RingBuffer_Remove(&UARTtoUSB_Buffer);
+               }
        }
 
        CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
        }
 
        CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
@@ -171,12 +188,12 @@ void SetupHardware(void)
 /** Event handler for the library USB Configuration Changed event. */
 void EVENT_USB_Device_ConfigurationChanged(void)
 {
 /** Event handler for the library USB Configuration Changed event. */
 void EVENT_USB_Device_ConfigurationChanged(void)
 {
-       bool EndpointConfigSuccess = true;
+       bool ConfigSuccess = true;
 
        /* Configure the device endpoints according to the selected mode */
        if (CurrentFirmwareMode == MODE_USART_BRIDGE)
        {
 
        /* Configure the device endpoints according to the selected mode */
        if (CurrentFirmwareMode == MODE_USART_BRIDGE)
        {
-               EndpointConfigSuccess &= CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);
+               ConfigSuccess &= CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface);
 
                /* Configure the UART flush timer - run at Fcpu/1024 for maximum interval before overflow */
                TCCR0B = ((1 << CS02) | (1 << CS00));
 
                /* Configure the UART flush timer - run at Fcpu/1024 for maximum interval before overflow */
                TCCR0B = ((1 << CS02) | (1 << CS00));
@@ -184,31 +201,29 @@ void EVENT_USB_Device_ConfigurationChanged(void)
                /* Initialize ring buffers used to hold serial data between USB and software UART interfaces */
                RingBuffer_InitBuffer(&USBtoUART_Buffer);
                RingBuffer_InitBuffer(&UARTtoUSB_Buffer);
                /* Initialize ring buffers used to hold serial data between USB and software UART interfaces */
                RingBuffer_InitBuffer(&USBtoUART_Buffer);
                RingBuffer_InitBuffer(&UARTtoUSB_Buffer);
+
+               /* Start the software USART */
+               SoftUART_Init();
        }
        else
        {
        }
        else
        {
-               EndpointConfigSuccess &= Endpoint_ConfigureEndpoint(AVRISP_DATA_OUT_EPNUM, EP_TYPE_BULK,
-                                                                                                   ENDPOINT_DIR_OUT, AVRISP_DATA_EPSIZE,
-                                                                                                   ENDPOINT_BANK_SINGLE);
+               ConfigSuccess &= Endpoint_ConfigureEndpoint(AVRISP_DATA_OUT_EPNUM, EP_TYPE_BULK, ENDPOINT_DIR_OUT,
+                                                           AVRISP_DATA_EPSIZE, ENDPOINT_BANK_SINGLE);
 
                #if defined(LIBUSB_DRIVER_COMPAT)
 
                #if defined(LIBUSB_DRIVER_COMPAT)
-               EndpointConfigSuccess &= Endpoint_ConfigureEndpoint(AVRISP_DATA_IN_EPNUM, EP_TYPE_BULK,
-                                                                   ENDPOINT_DIR_IN, AVRISP_DATA_EPSIZE,
-                                                                   ENDPOINT_BANK_SINGLE);
+               ConfigSuccess &= Endpoint_ConfigureEndpoint(AVRISP_DATA_IN_EPNUM, EP_TYPE_BULK, ENDPOINT_DIR_IN,
+                                                           AVRISP_DATA_EPSIZE, ENDPOINT_BANK_SINGLE);
                #endif
                #endif
-       
+
                /* Configure the V2 protocol packet handler */
                V2Protocol_Init();
        }
 
                /* Configure the V2 protocol packet handler */
                V2Protocol_Init();
        }
 
-       if (EndpointConfigSuccess)
-         LEDs_SetAllLEDs(LEDMASK_USB_READY);
-       else
-         LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
+       LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
 }
 
 }
 
-/** Event handler for the library USB Unhandled Control Request event. */
-void EVENT_USB_Device_UnhandledControlRequest(void)
+/** Event handler for the library USB Control Request reception event. */
+void EVENT_USB_Device_ControlRequest(void)
 {
        if (CurrentFirmwareMode == MODE_USART_BRIDGE)
          CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface);
 {
        if (CurrentFirmwareMode == MODE_USART_BRIDGE)
          CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface);
@@ -250,7 +265,7 @@ void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCI
  */
 uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
                                     const uint8_t wIndex,
  */
 uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
                                     const uint8_t wIndex,
-                                    void** const DescriptorAddress)
+                                    const void** const DescriptorAddress)
 {
        /* Return the correct descriptors based on the selected mode */
        if (CurrentFirmwareMode == MODE_USART_BRIDGE)
 {
        /* Return the correct descriptors based on the selected mode */
        if (CurrentFirmwareMode == MODE_USART_BRIDGE)
@@ -258,3 +273,4 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
        else
          return AVRISP_GetDescriptor(wValue, wIndex, DescriptorAddress);
 }
        else
          return AVRISP_GetDescriptor(wValue, wIndex, DescriptorAddress);
 }
+