Re-add in old Endpoint/Pipe workaround for unordered pipes - add new ORDERED_EP_CONFI...
[pub/USBasp.git] / Bootloaders / CDC / BootloaderCDC.c
index 0c93adf..97a0f1b 100644 (file)
@@ -121,11 +121,11 @@ void EVENT_USB_Device_ConfigurationChanged(void)
                                   ENDPOINT_BANK_SINGLE);
 }
 
-/** Event handler for the USB_UnhandledControlRequest event. This is used to catch standard and class specific
- *  control requests that are not handled internally by the USB library (including the CDC control commands,
- *  which are all issued via the control endpoint), so that they can be handled appropriately for the application.
+/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
+ *  the device from the USB host before passing along unhandled control requests to the library for processing
+ *  internally.
  */
-void EVENT_USB_Device_UnhandledControlRequest(void)
+void EVENT_USB_Device_ControlRequest(void)
 {
        /* Process CDC specific control requests */
        switch (USB_ControlRequest.bRequest)
@@ -155,6 +155,7 @@ void EVENT_USB_Device_UnhandledControlRequest(void)
        }
 }
 
+#if !defined(NO_BLOCK_SUPPORT)
 /** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending
  *  on the AVR910 protocol command issued.
  *
@@ -236,15 +237,13 @@ static void ReadWriteMemoryBlock(const uint8_t Command)
 
                                        /* Increment the address counter after use */
                                        CurrAddress += 2;
-
-                                       HighByte = false;
                                }
                                else
                                {
                                        LowByte = FetchNextCommandByte();
-
-                                       HighByte = true;
                                }
+                               
+                               HighByte = !HighByte;
                        }
                        else
                        {
@@ -270,6 +269,7 @@ static void ReadWriteMemoryBlock(const uint8_t Command)
                WriteNextResponseByte('\r');
        }
 }
+#endif
 
 /** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if needed
  *  to allow reception of the next data packet from the host.
@@ -319,7 +319,7 @@ static void WriteNextResponseByte(const uint8_t Response)
                }
        }
 
-       /* Write the next byte to the OUT endpoint */
+       /* Write the next byte to the IN endpoint */
        Endpoint_Write_Byte(Response);
 }
 
@@ -332,219 +332,230 @@ void CDC_Task(void)
        Endpoint_SelectEndpoint(CDC_RX_EPNUM);
 
        /* Check if endpoint has a command in it sent from the host */
-       if (Endpoint_IsOUTReceived())
-       {
-               /* Read in the bootloader command (first byte sent from host) */
-               uint8_t Command = FetchNextCommandByte();
+       if (!(Endpoint_IsOUTReceived()))
+         return;
 
-               if ((Command == 'L') || (Command == 'P') || (Command == 'T') || (Command == 'E'))
-               {
-                       if (Command == 'E')
-                         RunBootloader = false;
-                       else if (Command == 'T')
-                         FetchNextCommandByte();
+       /* Read in the bootloader command (first byte sent from host) */
+       uint8_t Command = FetchNextCommandByte();
 
-                       /* Send confirmation byte back to the host */
-                       WriteNextResponseByte('\r');
-               }
-               else if (Command == 't')
-               {
-                       /* Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader */
-                       WriteNextResponseByte(0x44);
-                       WriteNextResponseByte(0x00);
-               }
-               else if (Command == 'a')
-               {
-                       /* Indicate auto-address increment is supported */
-                       WriteNextResponseByte('Y');
-               }
-               else if (Command == 'A')
-               {
-                       /* Set the current address to that given by the host */
-                       CurrAddress   = (FetchNextCommandByte() << 9);
-                       CurrAddress  |= (FetchNextCommandByte() << 1);
+       if (Command == 'E')
+       {
+               RunBootloader = false;
+       
+               /* Send confirmation byte back to the host */
+               WriteNextResponseByte('\r');
+       }
+       else if (Command == 'T')
+       {
+               FetchNextCommandByte();
 
-                       /* Send confirmation byte back to the host */
-                       WriteNextResponseByte('\r');
-               }
-               else if (Command == 'p')
-               {
-                       /* Indicate serial programmer back to the host */
-                       WriteNextResponseByte('S');
-               }
-               else if (Command == 'S')
-               {
-                       /* Write the 7-byte software identifier to the endpoint */
-                       for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++)
-                         WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]);
-               }
-               else if (Command == 'V')
-               {
-                       WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
-                       WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
-               }
-               else if (Command == 's')
-               {
-                       WriteNextResponseByte(AVR_SIGNATURE_3);
-                       WriteNextResponseByte(AVR_SIGNATURE_2);
-                       WriteNextResponseByte(AVR_SIGNATURE_1);
-               }
-               else if (Command == 'b')
-               {
-                       WriteNextResponseByte('Y');
+               /* Send confirmation byte back to the host */
+               WriteNextResponseByte('\r');
+       }
+       else if ((Command == 'L') || (Command == 'P'))
+       {
+               /* Send confirmation byte back to the host */
+               WriteNextResponseByte('\r');
+       }
+       else if (Command == 't')
+       {
+               /* Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader */
+               WriteNextResponseByte(0x44);
+               WriteNextResponseByte(0x00);
+       }
+       else if (Command == 'a')
+       {
+               /* Indicate auto-address increment is supported */
+               WriteNextResponseByte('Y');
+       }
+       else if (Command == 'A')
+       {
+               /* Set the current address to that given by the host */
+               CurrAddress   = (FetchNextCommandByte() << 9);
+               CurrAddress  |= (FetchNextCommandByte() << 1);
 
-                       /* Send block size to the host */
-                       WriteNextResponseByte(SPM_PAGESIZE >> 8);
-                       WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
-               }
-               else if (Command == 'e')
+               /* Send confirmation byte back to the host */
+               WriteNextResponseByte('\r');
+       }
+       else if (Command == 'p')
+       {
+               /* Indicate serial programmer back to the host */
+               WriteNextResponseByte('S');
+       }
+       else if (Command == 'S')
+       {
+               /* Write the 7-byte software identifier to the endpoint */
+               for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++)
+                 WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]);
+       }
+       else if (Command == 'V')
+       {
+               WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
+               WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
+       }
+       else if (Command == 's')
+       {
+               WriteNextResponseByte(AVR_SIGNATURE_3);
+               WriteNextResponseByte(AVR_SIGNATURE_2);
+               WriteNextResponseByte(AVR_SIGNATURE_1);
+       }
+       else if (Command == 'e')
+       {
+               /* Clear the application section of flash */
+               for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < BOOT_START_ADDR; CurrFlashAddress += SPM_PAGESIZE)
                {
-                       /* Clear the application section of flash */
-                       for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < BOOT_START_ADDR; CurrFlashAddress++)
-                       {
-                               boot_page_erase(CurrFlashAddress);
-                               boot_spm_busy_wait();
-                               boot_page_write(CurrFlashAddress);
-                               boot_spm_busy_wait();
-
-                               CurrFlashAddress += SPM_PAGESIZE;
-                       }
-
-                       /* Send confirmation byte back to the host */
-                       WriteNextResponseByte('\r');
+                       boot_page_erase(CurrFlashAddress);
+                       boot_spm_busy_wait();
+                       boot_page_write(CurrFlashAddress);
+                       boot_spm_busy_wait();
                }
-               else if (Command == 'l')
-               {
-                       /* Set the lock bits to those given by the host */
-                       boot_lock_bits_set(FetchNextCommandByte());
 
-                       /* Send confirmation byte back to the host */
-                       WriteNextResponseByte('\r');
-               }
-               else if (Command == 'r')
-               {
-                       WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
-               }
-               else if (Command == 'F')
-               {
-                       WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
-               }
-               else if (Command == 'N')
-               {
-                       WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
-               }
-               else if (Command == 'Q')
-               {
-                       WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
-               }
-               else if (Command == 'C')
-               {
-                       /* Write the high byte to the current flash page */
-                       boot_page_fill(CurrAddress, FetchNextCommandByte());
+               /* Send confirmation byte back to the host */
+               WriteNextResponseByte('\r');
+       }
+       #if !defined(NO_LOCK_BYTE_WRITE_SUPPORT)
+       else if (Command == 'l')
+       {
+               /* Set the lock bits to those given by the host */
+               boot_lock_bits_set(FetchNextCommandByte());
 
-                       /* Send confirmation byte back to the host */
-                       WriteNextResponseByte('\r');
-               }
-               else if (Command == 'c')
-               {
-                       /* Write the low byte to the current flash page */
-                       boot_page_fill(CurrAddress | 1, FetchNextCommandByte());
+               /* Send confirmation byte back to the host */
+               WriteNextResponseByte('\r');
+       }
+       #endif
+       else if (Command == 'r')
+       {
+               WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
+       }
+       else if (Command == 'F')
+       {
+               WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
+       }
+       else if (Command == 'N')
+       {
+               WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
+       }
+       else if (Command == 'Q')
+       {
+               WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
+       }
+       #if !defined(NO_BLOCK_SUPPORT)
+       else if (Command == 'b')
+       {
+               WriteNextResponseByte('Y');
 
-                       /* Increment the address */
-                       CurrAddress += 2;
+               /* Send block size to the host */
+               WriteNextResponseByte(SPM_PAGESIZE >> 8);
+               WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
+       }
+       else if ((Command == 'B') || (Command == 'g'))
+       {
+               /* Delegate the block write/read to a separate function for clarity */
+               ReadWriteMemoryBlock(Command);
+       }
+       #endif
+       #if !defined(NO_FLASH_BYTE_SUPPORT)
+       else if (Command == 'C')
+       {
+               /* Write the high byte to the current flash page */
+               boot_page_fill(CurrAddress, FetchNextCommandByte());
 
-                       /* Send confirmation byte back to the host */
-                       WriteNextResponseByte('\r');
-               }
-               else if (Command == 'm')
-               {
-                       /* Commit the flash page to memory */
-                       boot_page_write(CurrAddress);
+               /* Send confirmation byte back to the host */
+               WriteNextResponseByte('\r');
+       }
+       else if (Command == 'c')
+       {
+               /* Write the low byte to the current flash page */
+               boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());
 
-                       /* Wait until write operation has completed */
-                       boot_spm_busy_wait();
+               /* Increment the address */
+               CurrAddress += 2;
 
-                       /* Send confirmation byte back to the host */
-                       WriteNextResponseByte('\r');
-               }
-               else if ((Command == 'B') || (Command == 'g'))
-               {
-                       /* Delegate the block write/read to a separate function for clarity */
-                       ReadWriteMemoryBlock(Command);
-               }
-               else if (Command == 'R')
-               {
-                       #if (FLASHEND > 0xFFFF)
-                       uint16_t ProgramWord = pgm_read_word_far(CurrAddress);
-                       #else
-                       uint16_t ProgramWord = pgm_read_word(CurrAddress);
-                       #endif
-
-                       WriteNextResponseByte(ProgramWord >> 8);
-                       WriteNextResponseByte(ProgramWord & 0xFF);
-               }
-               else if (Command == 'D')
-               {
-                       /* Read the byte from the endpoint and write it to the EEPROM */
-                       eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
+               /* Send confirmation byte back to the host */
+               WriteNextResponseByte('\r');
+       }
+       else if (Command == 'm')
+       {
+               /* Commit the flash page to memory */
+               boot_page_write(CurrAddress);
 
-                       /* Increment the address after use */
-                       CurrAddress += 2;
+               /* Wait until write operation has completed */
+               boot_spm_busy_wait();
 
-                       /* Send confirmation byte back to the host */
-                       WriteNextResponseByte('\r');
-               }
-               else if (Command == 'd')
-               {
-                       /* Read the EEPROM byte and write it to the endpoint */
-                       WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
+               /* Send confirmation byte back to the host */
+               WriteNextResponseByte('\r');
+       }
+       else if (Command == 'R')
+       {
+               #if (FLASHEND > 0xFFFF)
+               uint16_t ProgramWord = pgm_read_word_far(CurrAddress);
+               #else
+               uint16_t ProgramWord = pgm_read_word(CurrAddress);
+               #endif
+
+               WriteNextResponseByte(ProgramWord >> 8);
+               WriteNextResponseByte(ProgramWord & 0xFF);
+       }
+       #endif
+       #if !defined(NO_EEPROM_BYTE_SUPPORT)
+       else if (Command == 'D')
+       {
+               /* Read the byte from the endpoint and write it to the EEPROM */
+               eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
 
-                       /* Increment the address after use */
-                       CurrAddress += 2;
-               }
-               else if (Command == 27)
-               {
-                       /* Escape is sync, ignore */
-               }
-               else
-               {
-                       /* Unknown command, return fail code */
-                       WriteNextResponseByte('?');
-               }
+               /* Increment the address after use */
+               CurrAddress += 2;
 
-               /* Select the IN endpoint */
-               Endpoint_SelectEndpoint(CDC_TX_EPNUM);
+               /* Send confirmation byte back to the host */
+               WriteNextResponseByte('\r');
+       }
+       else if (Command == 'd')
+       {
+               /* Read the EEPROM byte and write it to the endpoint */
+               WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
 
-               /* Remember if the endpoint is completely full before clearing it */
-               bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
+               /* Increment the address after use */
+               CurrAddress += 2;
+       }
+       #endif
+       else if (Command != 27)
+       {
+               /* Unknown (non-sync) command, return fail code */
+               WriteNextResponseByte('?');
+       }
 
-               /* Send the endpoint data to the host */
-               Endpoint_ClearIN();
+       /* Select the IN endpoint */
+       Endpoint_SelectEndpoint(CDC_TX_EPNUM);
 
-               /* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal end of transfer */
-               if (IsEndpointFull)
-               {
-                       while (!(Endpoint_IsINReady()))
-                       {
-                               if (USB_DeviceState == DEVICE_STATE_Unattached)
-                                 return;
-                       }
+       /* Remember if the endpoint is completely full before clearing it */
+       bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
 
-                       Endpoint_ClearIN();
-               }
+       /* Send the endpoint data to the host */
+       Endpoint_ClearIN();
 
-               /* Wait until the data has been sent to the host */
+       /* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal end of transfer */
+       if (IsEndpointFull)
+       {
                while (!(Endpoint_IsINReady()))
                {
                        if (USB_DeviceState == DEVICE_STATE_Unattached)
                          return;
                }
 
-               /* Select the OUT endpoint */
-               Endpoint_SelectEndpoint(CDC_RX_EPNUM);
+               Endpoint_ClearIN();
+       }
 
-               /* Acknowledge the command from the host */
-               Endpoint_ClearOUT();
+       /* Wait until the data has been sent to the host */
+       while (!(Endpoint_IsINReady()))
+       {
+               if (USB_DeviceState == DEVICE_STATE_Unattached)
+                 return;
        }
+
+       /* Select the OUT endpoint */
+       Endpoint_SelectEndpoint(CDC_RX_EPNUM);
+
+       /* Acknowledge the command from the host */
+       Endpoint_ClearOUT();
 }