Added incomplete MIDIToneGenerator project.
[pub/USBasp.git] / Demos / Device / LowLevel / MassStorage / MassStorage.c
index 72a2302..fc9a97d 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
 #define  INCLUDE_FROM_MASSSTORAGE_C\r
 #include "MassStorage.h"\r
 \r
 #define  INCLUDE_FROM_MASSSTORAGE_C\r
 #include "MassStorage.h"\r
 \r
-/* Scheduler Task List */\r
-TASK_LIST\r
-{\r
-       { .Task = USB_MassStorage      , .TaskStatus = TASK_STOP },\r
-};\r
-\r
-/* Global Variables */\r
 /** Structure to hold the latest Command Block Wrapper issued by the host, containing a SCSI command to execute. */\r
 CommandBlockWrapper_t  CommandBlock;\r
 \r
 /** Structure to hold the latest Command Block Wrapper issued by the host, containing a SCSI command to execute. */\r
 CommandBlockWrapper_t  CommandBlock;\r
 \r
@@ -53,11 +46,26 @@ CommandStatusWrapper_t CommandStatus = { .Signature = CSW_SIGNATURE };
 /** Flag to asynchronously abort any in-progress data transfers upon the reception of a mass storage reset command. */\r
 volatile bool          IsMassStoreReset = false;\r
 \r
 /** Flag to asynchronously abort any in-progress data transfers upon the reception of a mass storage reset command. */\r
 volatile bool          IsMassStoreReset = false;\r
 \r
+\r
 /** Main program entry point. This routine configures the hardware required by the application, then\r
 /** Main program entry point. This routine configures the hardware required by the application, then\r
- *  starts the scheduler to run the application tasks.\r
+ *  enters a loop to run the application tasks in sequence.\r
  */\r
 int main(void)\r
 {\r
  */\r
 int main(void)\r
 {\r
+       SetupHardware();\r
+       \r
+       LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
+\r
+       for (;;)\r
+       {\r
+               MassStorage_Task();\r
+               USB_USBTask();\r
+       }\r
+}\r
+\r
+/** Configures the board hardware and chip peripherals for the demo's functionality. */\r
+void SetupHardware(void)\r
+{\r
        /* Disable watchdog if enabled by bootloader/fuses */\r
        MCUSR &= ~(1 << WDRF);\r
        wdt_disable();\r
        /* Disable watchdog if enabled by bootloader/fuses */\r
        MCUSR &= ~(1 << WDRF);\r
        wdt_disable();\r
@@ -67,29 +75,19 @@ int main(void)
 \r
        /* Hardware Initialization */\r
        LEDs_Init();\r
 \r
        /* Hardware Initialization */\r
        LEDs_Init();\r
-       Dataflash_Init(SPI_SPEED_FCPU_DIV_2);\r
+       SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_SCK_LEAD_FALLING | SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);\r
+       Dataflash_Init();\r
+       USB_Init();\r
 \r
        /* Clear Dataflash sector protections, if enabled */\r
        DataflashManager_ResetDataflashProtections();\r
 \r
        /* Clear Dataflash sector protections, if enabled */\r
        DataflashManager_ResetDataflashProtections();\r
-       \r
-       /* Indicate USB not ready */\r
-       UpdateStatus(Status_USBNotReady);\r
-       \r
-       /* Initialize Scheduler so that it can be used */\r
-       Scheduler_Init();\r
-\r
-       /* Initialize USB Subsystem */\r
-       USB_Init();\r
-\r
-       /* Scheduling - routine never returns, so put this last in the main function */\r
-       Scheduler_Start();\r
 }\r
 \r
 /** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */\r
 }\r
 \r
 /** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs. */\r
-void EVENT_USB_Connect(void)\r
+void EVENT_USB_Device_Connect(void)\r
 {\r
        /* Indicate USB enumerating */\r
 {\r
        /* Indicate USB enumerating */\r
-       UpdateStatus(Status_USBEnumerating);\r
+       LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
        \r
        /* Reset the MSReset flag upon connection */\r
        IsMassStoreReset = false;\r
        \r
        /* Reset the MSReset flag upon connection */\r
        IsMassStoreReset = false;\r
@@ -98,41 +96,41 @@ void EVENT_USB_Connect(void)
 /** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
  *  the status LEDs and stops the Mass Storage management task.\r
  */\r
 /** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via\r
  *  the status LEDs and stops the Mass Storage management task.\r
  */\r
-void EVENT_USB_Disconnect(void)\r
+void EVENT_USB_Device_Disconnect(void)\r
 {\r
 {\r
-       /* Stop running mass storage task */\r
-       Scheduler_SetTaskMode(USB_MassStorage, TASK_STOP);\r
-\r
        /* Indicate USB not ready */\r
        /* Indicate USB not ready */\r
-       UpdateStatus(Status_USBNotReady);\r
+       LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
 }\r
 \r
 /** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration\r
  *  of the USB device after enumeration - the device endpoints are configured and the Mass Storage management task started.\r
  */\r
 }\r
 \r
 /** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration\r
  *  of the USB device after enumeration - the device endpoints are configured and the Mass Storage management task started.\r
  */\r
-void EVENT_USB_ConfigurationChanged(void)\r
+void EVENT_USB_Device_ConfigurationChanged(void)\r
 {\r
 {\r
-       /* Setup Mass Storage In and Out Endpoints */\r
-       Endpoint_ConfigureEndpoint(MASS_STORAGE_IN_EPNUM, EP_TYPE_BULK,\r
-                                      ENDPOINT_DIR_IN, MASS_STORAGE_IO_EPSIZE,\r
-                                  ENDPOINT_BANK_DOUBLE);\r
-\r
-       Endpoint_ConfigureEndpoint(MASS_STORAGE_OUT_EPNUM, EP_TYPE_BULK,\r
-                                      ENDPOINT_DIR_OUT, MASS_STORAGE_IO_EPSIZE,\r
-                                  ENDPOINT_BANK_DOUBLE);\r
-\r
        /* Indicate USB connected and ready */\r
        /* Indicate USB connected and ready */\r
-       UpdateStatus(Status_USBReady);\r
+       LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
+\r
+       /* Setup Mass Storage In and Out Endpoints */\r
+       if (!(Endpoint_ConfigureEndpoint(MASS_STORAGE_IN_EPNUM, EP_TYPE_BULK,\r
+                                            ENDPOINT_DIR_IN, MASS_STORAGE_IO_EPSIZE,\r
+                                        ENDPOINT_BANK_SINGLE)))\r
+       {\r
+               LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
+       }\r
        \r
        \r
-       /* Start mass storage task */\r
-       Scheduler_SetTaskMode(USB_MassStorage, TASK_RUN);\r
+       if (!(Endpoint_ConfigureEndpoint(MASS_STORAGE_OUT_EPNUM, EP_TYPE_BULK,\r
+                                            ENDPOINT_DIR_OUT, MASS_STORAGE_IO_EPSIZE,\r
+                                        ENDPOINT_BANK_SINGLE)))\r
+       {\r
+               LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
+       }                                                          \r
 }\r
 \r
 /** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
  *  control requests that are not handled internally by the USB library (including the Mass Storage class-specific\r
  *  requests) so that they can be handled appropriately for the application.\r
  */\r
 }\r
 \r
 /** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific\r
  *  control requests that are not handled internally by the USB library (including the Mass Storage class-specific\r
  *  requests) 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
        /* Process UFI specific control requests */\r
        switch (USB_ControlRequest.bRequest)\r
 {\r
        /* Process UFI specific control requests */\r
        switch (USB_ControlRequest.bRequest)\r
@@ -143,11 +141,9 @@ void EVENT_USB_UnhandledControlPacket(void)
                                Endpoint_ClearSETUP();\r
 \r
                                /* Indicate that the current transfer should be aborted */\r
                                Endpoint_ClearSETUP();\r
 \r
                                /* Indicate that the current transfer should be aborted */\r
-                               IsMassStoreReset = true;                        \r
+                               IsMassStoreReset = true;\r
 \r
 \r
-                               /* Acknowledge status stage */\r
-                               while (!(Endpoint_IsINReady()));\r
-                               Endpoint_ClearIN();\r
+                               Endpoint_ClearStatusStage();\r
                        }\r
 \r
                        break;\r
                        }\r
 \r
                        break;\r
@@ -161,113 +157,80 @@ 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
+                               Endpoint_ClearStatusStage();\r
                        }\r
                        \r
                        break;\r
        }\r
 }\r
 \r
                        }\r
                        \r
                        break;\r
        }\r
 }\r
 \r
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- *  log to a serial port, or anything else that is suitable for status updates.\r
- *\r
- *  \param CurrentStatus  Current status of the system, from the MassStorage_StatusCodes_t enum\r
- */\r
-void UpdateStatus(uint8_t CurrentStatus)\r
-{\r
-       uint8_t LEDMask = LEDS_NO_LEDS;\r
-       \r
-       /* Set the LED mask to the appropriate LED mask based on the given status code */\r
-       switch (CurrentStatus)\r
-       {\r
-               case Status_USBNotReady:\r
-                       LEDMask = (LEDS_LED1);\r
-                       break;\r
-               case Status_USBEnumerating:\r
-                       LEDMask = (LEDS_LED1 | LEDS_LED2);\r
-                       break;\r
-               case Status_USBReady:\r
-                       LEDMask = (LEDS_LED2 | LEDS_LED4);\r
-                       break;\r
-               case Status_CommandBlockError:\r
-                       LEDMask = (LEDS_LED1);\r
-                       break;\r
-               case Status_ProcessingCommandBlock:\r
-                       LEDMask = (LEDS_LED1 | LEDS_LED2);\r
-                       break;\r
-       }\r
-       \r
-       /* Set the board LEDs to the new LED mask */\r
-       LEDs_SetAllLEDs(LEDMask);\r
-}\r
-\r
 /** Task to manage the Mass Storage interface, reading in Command Block Wrappers from the host, processing the SCSI commands they\r
  *  contain, and returning Command Status Wrappers back to the host to indicate the success or failure of the last issued command.\r
  */\r
 /** Task to manage the Mass Storage interface, reading in Command Block Wrappers from the host, processing the SCSI commands they\r
  *  contain, and returning Command Status Wrappers back to the host to indicate the success or failure of the last issued command.\r
  */\r
-TASK(USB_MassStorage)\r
+void MassStorage_Task(void)\r
 {\r
 {\r
-       /* Check if the USB System is connected to a Host */\r
-       if (USB_IsConnected)\r
+       /* Device must be connected and configured for the task to run */\r
+       if (USB_DeviceState != DEVICE_STATE_Configured)\r
+         return;\r
+         \r
+       /* Select the Data Out Endpoint */\r
+       Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);\r
+       \r
+       /* Check to see if a command from the host has been issued */\r
+       if (Endpoint_IsReadWriteAllowed())\r
        {\r
        {\r
-               /* Select the Data Out Endpoint */\r
-               Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);\r
-               \r
-               /* Check to see if a command from the host has been issued */\r
-               if (Endpoint_IsReadWriteAllowed())\r
-               {       \r
-                       /* Indicate busy */\r
-                       UpdateStatus(Status_ProcessingCommandBlock);\r
-\r
-                       /* Process sent command block from the host */\r
-                       if (ReadInCommandBlock())\r
-                       {\r
-                               /* Check direction of command, select Data IN endpoint if data is from the device */\r
-                               if (CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN)\r
-                                 Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);\r
+               /* Indicate busy */\r
+               LEDs_SetAllLEDs(LEDMASK_USB_BUSY);\r
 \r
 \r
-                               /* Decode the received SCSI command */\r
-                               SCSI_DecodeSCSICommand();\r
+               /* Process sent command block from the host */\r
+               if (ReadInCommandBlock())\r
+               {\r
+                       /* Check direction of command, select Data IN endpoint if data is from the device */\r
+                       if (CommandBlock.Flags & COMMAND_DIRECTION_DATA_IN)\r
+                         Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);\r
 \r
 \r
-                               /* Load in the CBW tag into the CSW to link them together */\r
-                               CommandStatus.Tag = CommandBlock.Tag;\r
+                       /* Decode the received SCSI command, set returned status code */\r
+                       CommandStatus.Status = SCSI_DecodeSCSICommand() ? Command_Pass : Command_Fail;          \r
 \r
 \r
-                               /* Load in the data residue counter into the CSW */\r
-                               CommandStatus.DataTransferResidue = CommandBlock.DataTransferLength;\r
+                       /* Load in the CBW tag into the CSW to link them together */\r
+                       CommandStatus.Tag = CommandBlock.Tag;\r
 \r
 \r
-                               /* Stall the selected data pipe if command failed (if data is still to be transferred) */\r
-                               if ((CommandStatus.Status == Command_Fail) && (CommandStatus.DataTransferResidue))\r
-                                 Endpoint_StallTransaction();\r
+                       /* Load in the data residue counter into the CSW */\r
+                       CommandStatus.DataTransferResidue = CommandBlock.DataTransferLength;\r
+                       \r
+                       /* Stall the selected data pipe if command failed (if data is still to be transferred) */\r
+                       if ((CommandStatus.Status == Command_Fail) && (CommandStatus.DataTransferResidue))\r
+                         Endpoint_StallTransaction();\r
 \r
 \r
-                               /* Return command status block to the host */\r
-                               ReturnCommandStatus();\r
-                               \r
-                               /* Check if a Mass Storage Reset occurred */\r
-                               if (IsMassStoreReset)\r
-                               {\r
-                                       /* Reset the data endpoint banks */\r
-                                       Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM);\r
-                                       Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM);\r
-                                       \r
-                                       Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);\r
-                                       Endpoint_ClearStall();\r
-                                       Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);\r
-                                       Endpoint_ClearStall();\r
-\r
-                                       /* Clear the abort transfer flag */\r
-                                       IsMassStoreReset = false;\r
-                               }\r
-\r
-                               /* Indicate ready */\r
-                               UpdateStatus(Status_USBReady);\r
-                       }\r
-                       else\r
-                       {\r
-                               /* Indicate error reading in the command block from the host */\r
-                               UpdateStatus(Status_CommandBlockError);\r
-                       }\r
+                       /* Return command status block to the host */\r
+                       ReturnCommandStatus();\r
+\r
+                       /* Indicate ready */\r
+                       LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
                }\r
                }\r
+               else\r
+               {\r
+                       /* Indicate error reading in the command block from the host */\r
+                       LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
+               }\r
+       }\r
+\r
+       /* Check if a Mass Storage Reset occurred */\r
+       if (IsMassStoreReset)\r
+       {\r
+               /* Reset the data endpoint banks */\r
+               Endpoint_ResetFIFO(MASS_STORAGE_OUT_EPNUM);\r
+               Endpoint_ResetFIFO(MASS_STORAGE_IN_EPNUM);\r
+               \r
+               Endpoint_SelectEndpoint(MASS_STORAGE_OUT_EPNUM);\r
+               Endpoint_ClearStall();\r
+               Endpoint_ResetDataToggle();\r
+               Endpoint_SelectEndpoint(MASS_STORAGE_IN_EPNUM);\r
+               Endpoint_ClearStall();\r
+               Endpoint_ResetDataToggle();\r
+\r
+               /* Clear the abort transfer flag */\r
+               IsMassStoreReset = false;\r
        }\r
 }\r
 \r
        }\r
 }\r
 \r
@@ -290,9 +253,11 @@ static bool ReadInCommandBlock(void)
          return false;\r
 \r
        /* Verify the command block - abort if invalid */\r
          return false;\r
 \r
        /* Verify the command block - abort if invalid */\r
-       if ((CommandBlock.Signature != CBW_SIGNATURE) ||\r
-           (CommandBlock.LUN >= TOTAL_LUNS) ||\r
-               (CommandBlock.SCSICommandLength > MAX_SCSI_COMMAND_LENGTH))\r
+       if ((CommandBlock.Signature         != CBW_SIGNATURE) ||\r
+           (CommandBlock.LUN               >= TOTAL_LUNS)    ||\r
+               (CommandBlock.Flags              & 0x1F)          ||\r
+               (CommandBlock.SCSICommandLength == 0)             ||\r
+               (CommandBlock.SCSICommandLength >  MAX_SCSI_COMMAND_LENGTH))\r
        {\r
                /* Stall both data pipes until reset by host */\r
                Endpoint_StallTransaction();\r
        {\r
                /* Stall both data pipes until reset by host */\r
                Endpoint_StallTransaction();\r