Be doubly-certain that the incomming CDC class driver's endpoint/pipe is flushed...
[pub/USBasp.git] / Bootloaders / DFU / BootloaderDFU.c
index 2086a91..157b78f 100644 (file)
@@ -1,21 +1,21 @@
 /*\r
              LUFA Library\r
 /*\r
              LUFA Library\r
-     Copyright (C) Dean Camera, 2009.\r
+     Copyright (C) Dean Camera, 2010.\r
               \r
   dean [at] fourwalledcubicle [dot] com\r
       www.fourwalledcubicle.com\r
 */\r
 \r
 /*\r
               \r
   dean [at] fourwalledcubicle [dot] com\r
       www.fourwalledcubicle.com\r
 */\r
 \r
 /*\r
-  Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
-\r
-  Permission to use, copy, modify, and distribute this software\r
-  and its documentation for any purpose and without fee is hereby\r
-  granted, provided that the above copyright notice appear in all\r
-  copies and that both that the copyright notice and this\r
-  permission notice and warranty disclaimer appear in supporting\r
-  documentation, and that the name of the author not be used in\r
-  advertising or publicity pertaining to distribution of the\r
+  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+\r
+  Permission to use, copy, modify, distribute, and sell this \r
+  software and its documentation for any purpose is hereby granted\r
+  without fee, provided that the above copyright notice appear in \r
+  all copies and that both that the copyright notice and this\r
+  permission notice and warranty disclaimer appear in supporting \r
+  documentation, and that the name of the author not be used in \r
+  advertising or publicity pertaining to distribution of the \r
   software without specific, written prior permission.\r
 \r
   The author disclaim all warranties with regard to this\r
   software without specific, written prior permission.\r
 \r
   The author disclaim all warranties with regard to this\r
@@ -92,6 +92,7 @@ uint16_t StartAddr = 0x0000;
  */\r
 uint16_t EndAddr = 0x0000;\r
 \r
  */\r
 uint16_t EndAddr = 0x0000;\r
 \r
+\r
 /** Main program entry point. This routine configures the hardware required by the bootloader, then continuously \r
  *  runs the bootloader processing routine until instructed to soft-exit, or hard-reset via the watchdog to start\r
  *  the loaded application code.\r
 /** Main program entry point. This routine configures the hardware required by the bootloader, then continuously \r
  *  runs the bootloader processing routine until instructed to soft-exit, or hard-reset via the watchdog to start\r
  *  the loaded application code.\r
@@ -141,20 +142,11 @@ void ResetHardware(void)
        MCUCR = 0;\r
 }\r
 \r
        MCUCR = 0;\r
 }\r
 \r
-/** Event handler for the USB_Disconnect event. This indicates that the bootloader should exit and the user\r
- *  application started.\r
- */\r
-void EVENT_USB_Disconnect(void)\r
-{\r
-       /* Upon disconnection, run user application */\r
-       RunBootloader = false;\r
-}\r
-\r
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
+/** Event handler for the USB_UnhandledControlRequest event. This is used to catch standard and class specific\r
  *  control requests that are not handled internally by the USB library (including the DFU commands, which are\r
  *  all issued via the control endpoint), so that they can be handled appropriately for the application.\r
  */\r
  *  control requests that are not handled internally by the USB library (including the DFU commands, which are\r
  *  all issued via the control endpoint), so that they can be handled appropriately for the application.\r
  */\r
-void EVENT_USB_UnhandledControlPacket(void)\r
+void EVENT_USB_Device_UnhandledControlRequest(void)\r
 {\r
        /* Get the size of the command and data from the wLength value */\r
        SentCommand.DataSize = USB_ControlRequest.wLength;\r
 {\r
        /* Get the size of the command and data from the wLength value */\r
        SentCommand.DataSize = USB_ControlRequest.wLength;\r
@@ -177,7 +169,11 @@ void EVENT_USB_UnhandledControlPacket(void)
                        /* If the request has a data stage, load it into the command struct */\r
                        if (SentCommand.DataSize)\r
                        {\r
                        /* If the request has a data stage, load it into the command struct */\r
                        if (SentCommand.DataSize)\r
                        {\r
-                               while (!(Endpoint_IsOUTReceived()));\r
+                               while (!(Endpoint_IsOUTReceived()))\r
+                               {                               \r
+                                       if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+                                         return;\r
+                               }\r
 \r
                                /* First byte of the data stage is the DNLOAD request's command */\r
                                SentCommand.Command = Endpoint_Read_Byte();\r
 \r
                                /* First byte of the data stage is the DNLOAD request's command */\r
                                SentCommand.Command = Endpoint_Read_Byte();\r
@@ -209,8 +205,8 @@ void EVENT_USB_UnhandledControlPacket(void)
                                        /* Throw away the filler bytes before the start of the firmware */\r
                                        DiscardFillerBytes(DFU_FILLER_BYTES_SIZE);\r
 \r
                                        /* Throw away the filler bytes before the start of the firmware */\r
                                        DiscardFillerBytes(DFU_FILLER_BYTES_SIZE);\r
 \r
-                                       /* Throw away the page alignment filler bytes before the start of the firmware */\r
-                                       DiscardFillerBytes(StartAddr % SPM_PAGESIZE);\r
+                                       /* Throw away the packet alignment filler bytes before the start of the firmware */\r
+                                       DiscardFillerBytes(StartAddr % FIXED_CONTROL_ENDPOINT_SIZE);\r
                                        \r
                                        /* Calculate the number of bytes remaining to be written */\r
                                        uint16_t BytesRemaining = ((EndAddr - StartAddr) + 1);\r
                                        \r
                                        /* Calculate the number of bytes remaining to be written */\r
                                        uint16_t BytesRemaining = ((EndAddr - StartAddr) + 1);\r
@@ -235,7 +231,12 @@ void EVENT_USB_UnhandledControlPacket(void)
                                                        if (!(Endpoint_BytesInEndpoint()))\r
                                                        {\r
                                                                Endpoint_ClearOUT();\r
                                                        if (!(Endpoint_BytesInEndpoint()))\r
                                                        {\r
                                                                Endpoint_ClearOUT();\r
-                                                               while (!(Endpoint_IsOUTReceived()));\r
+\r
+                                                               while (!(Endpoint_IsOUTReceived()))\r
+                                                               {                               \r
+                                                                       if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+                                                                         return;\r
+                                                               }\r
                                                        }\r
 \r
                                                        /* Write the next word into the current flash page */\r
                                                        }\r
 \r
                                                        /* Write the next word into the current flash page */\r
@@ -279,7 +280,12 @@ void EVENT_USB_UnhandledControlPacket(void)
                                                        if (!(Endpoint_BytesInEndpoint()))\r
                                                        {\r
                                                                Endpoint_ClearOUT();\r
                                                        if (!(Endpoint_BytesInEndpoint()))\r
                                                        {\r
                                                                Endpoint_ClearOUT();\r
-                                                               while (!(Endpoint_IsOUTReceived()));\r
+\r
+                                                               while (!(Endpoint_IsOUTReceived()))\r
+                                                               {                               \r
+                                                                       if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+                                                                         return;\r
+                                                               }\r
                                                        }\r
 \r
                                                        /* Read the byte from the USB interface and write to to the EEPROM */\r
                                                        }\r
 \r
                                                        /* Read the byte from the USB interface and write to to the EEPROM */\r
@@ -297,16 +303,18 @@ void EVENT_USB_UnhandledControlPacket(void)
 \r
                        Endpoint_ClearOUT();\r
 \r
 \r
                        Endpoint_ClearOUT();\r
 \r
-                       /* Acknowledge status stage */\r
-                       while (!(Endpoint_IsINReady()));\r
-                       Endpoint_ClearIN();\r
-                               \r
+                       Endpoint_ClearStatusStage();\r
+\r
                        break;\r
                case DFU_UPLOAD:\r
                        Endpoint_ClearSETUP();\r
 \r
                        break;\r
                case DFU_UPLOAD:\r
                        Endpoint_ClearSETUP();\r
 \r
-                       while (!(Endpoint_IsINReady()));\r
-\r
+                       while (!(Endpoint_IsINReady()))\r
+                       {                               \r
+                               if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+                                 return;\r
+                       }\r
+                                                       \r
                        if (DFU_State != dfuUPLOAD_IDLE)\r
                        {\r
                                if ((DFU_State == dfuERROR) && IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01))       // Blank Check\r
                        if (DFU_State != dfuUPLOAD_IDLE)\r
                        {\r
                                if ((DFU_State == dfuERROR) && IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01))       // Blank Check\r
@@ -343,7 +351,12 @@ void EVENT_USB_UnhandledControlPacket(void)
                                                if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)\r
                                                {\r
                                                        Endpoint_ClearIN();\r
                                                if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)\r
                                                {\r
                                                        Endpoint_ClearIN();\r
-                                                       while (!(Endpoint_IsINReady()));\r
+\r
+                                                       while (!(Endpoint_IsINReady()))\r
+                                                       {                               \r
+                                                               if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+                                                                 return;\r
+                                                       }\r
                                                }\r
 \r
                                                /* Read the flash word and send it via USB to the host */\r
                                                }\r
 \r
                                                /* Read the flash word and send it via USB to the host */\r
@@ -368,7 +381,12 @@ void EVENT_USB_UnhandledControlPacket(void)
                                                if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)\r
                                                {\r
                                                        Endpoint_ClearIN();\r
                                                if (Endpoint_BytesInEndpoint() == FIXED_CONTROL_ENDPOINT_SIZE)\r
                                                {\r
                                                        Endpoint_ClearIN();\r
-                                                       while (!(Endpoint_IsINReady()));\r
+                                                       \r
+                                                       while (!(Endpoint_IsINReady()))\r
+                                                       {                               \r
+                                                               if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+                                                                 return;\r
+                                                       }\r
                                                }\r
 \r
                                                /* Read the EEPROM byte and send it via USB to the host */\r
                                                }\r
 \r
                                                /* Read the EEPROM byte and send it via USB to the host */\r
@@ -385,10 +403,7 @@ void EVENT_USB_UnhandledControlPacket(void)
 \r
                        Endpoint_ClearIN();\r
 \r
 \r
                        Endpoint_ClearIN();\r
 \r
-                       /* Acknowledge status stage */\r
-                       while (!(Endpoint_IsOUTReceived()));\r
-                       Endpoint_ClearOUT();\r
-\r
+                       Endpoint_ClearStatusStage();\r
                        break;\r
                case DFU_GETSTATUS:\r
                        Endpoint_ClearSETUP();\r
                        break;\r
                case DFU_GETSTATUS:\r
                        Endpoint_ClearSETUP();\r
@@ -408,10 +423,7 @@ void EVENT_USB_UnhandledControlPacket(void)
 \r
                        Endpoint_ClearIN();\r
                        \r
 \r
                        Endpoint_ClearIN();\r
                        \r
-                       /* Acknowledge status stage */\r
-                       while (!(Endpoint_IsOUTReceived()));\r
-                       Endpoint_ClearOUT();\r
-       \r
+                       Endpoint_ClearStatusStage();\r
                        break;          \r
                case DFU_CLRSTATUS:\r
                        Endpoint_ClearSETUP();\r
                        break;          \r
                case DFU_CLRSTATUS:\r
                        Endpoint_ClearSETUP();\r
@@ -419,10 +431,7 @@ void EVENT_USB_UnhandledControlPacket(void)
                        /* Reset the status value variable to the default OK status */\r
                        DFU_Status = OK;\r
 \r
                        /* Reset the status value variable to the default OK status */\r
                        DFU_Status = OK;\r
 \r
-                       /* Acknowledge status stage */\r
-                       while (!(Endpoint_IsINReady()));\r
-                       Endpoint_ClearIN();\r
-                       \r
+                       Endpoint_ClearStatusStage();\r
                        break;\r
                case DFU_GETSTATE:\r
                        Endpoint_ClearSETUP();\r
                        break;\r
                case DFU_GETSTATE:\r
                        Endpoint_ClearSETUP();\r
@@ -432,21 +441,15 @@ void EVENT_USB_UnhandledControlPacket(void)
                \r
                        Endpoint_ClearIN();\r
                        \r
                \r
                        Endpoint_ClearIN();\r
                        \r
-                       /* Acknowledge status stage */\r
-                       while (!(Endpoint_IsOUTReceived()));\r
-                       Endpoint_ClearOUT();\r
-\r
+                       Endpoint_ClearStatusStage();\r
                        break;\r
                case DFU_ABORT:\r
                        Endpoint_ClearSETUP();\r
                        \r
                        /* Reset the current state variable to the default idle state */\r
                        DFU_State = dfuIDLE;\r
                        break;\r
                case DFU_ABORT:\r
                        Endpoint_ClearSETUP();\r
                        \r
                        /* Reset the current state variable to the default idle state */\r
                        DFU_State = dfuIDLE;\r
-                       \r
-                       /* Acknowledge status stage */\r
-                       while (!(Endpoint_IsINReady()));\r
-                       Endpoint_ClearIN();\r
 \r
 \r
+                       Endpoint_ClearStatusStage();\r
                        break;\r
        }\r
 }\r
                        break;\r
        }\r
 }\r
@@ -465,7 +468,11 @@ static void DiscardFillerBytes(uint8_t NumberOfBytes)
                        Endpoint_ClearOUT();\r
 \r
                        /* Wait until next data packet received */\r
                        Endpoint_ClearOUT();\r
 \r
                        /* Wait until next data packet received */\r
-                       while (!(Endpoint_IsOUTReceived()));\r
+                       while (!(Endpoint_IsOUTReceived()))\r
+                       {                               \r
+                               if (USB_DeviceState == DEVICE_STATE_Unattached)\r
+                                 return;\r
+                       }\r
                }\r
                else\r
                {\r
                }\r
                else\r
                {\r
@@ -683,11 +690,7 @@ static void ProcessReadCommand(void)
        uint8_t DataIndexToRead = SentCommand.Data[1];\r
 \r
        if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00))                         // Read bootloader info\r
        uint8_t DataIndexToRead = SentCommand.Data[1];\r
 \r
        if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x00))                         // Read bootloader info\r
-       {\r
-               ResponseByte = BootloaderInfo[DataIndexToRead];\r
-       }\r
+         ResponseByte = BootloaderInfo[DataIndexToRead];\r
        else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01))                    // Read signature byte\r
        else if (IS_ONEBYTE_COMMAND(SentCommand.Data, 0x01))                    // Read signature byte\r
-       {\r
-               ResponseByte = SignatureInfo[DataIndexToRead - 0x30];\r
-       }\r
+         ResponseByte = SignatureInfo[DataIndexToRead - 0x30];\r
 }\r
 }\r