]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - msp430-bsl/msp430-bsl.git/blobdiff - source/USB_API/USB_MSC_API/UsbMscStateMachine.c
MSP-BSL v3.0
[msp430-bsl/msp430-bsl.git] / source / USB_API / USB_MSC_API / UsbMscStateMachine.c
diff --git a/source/USB_API/USB_MSC_API/UsbMscStateMachine.c b/source/USB_API/USB_MSC_API/UsbMscStateMachine.c
new file mode 100644 (file)
index 0000000..a4ef22c
--- /dev/null
@@ -0,0 +1,213 @@
+/* --COPYRIGHT--,BSD\r
+ * Copyright (c) 2014, Texas Instruments Incorporated\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ * *  Redistributions of source code must retain the above copyright\r
+ *    notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * *  Redistributions in binary form must reproduce the above copyright\r
+ *    notice, this list of conditions and the following disclaimer in the\r
+ *    documentation and/or other materials provided with the distribution.\r
+ *\r
+ * *  Neither the name of Texas Instruments Incorporated nor the names of\r
+ *    its contributors may be used to endorse or promote products derived\r
+ *    from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ * --/COPYRIGHT--*/\r
+/** @file UsbMscStateMachine.c\r
+ *  @brief Contains APIs related to MSC task Management.\r
+ */\r
+//\r
+//! \cond\r
+//\r
+\r
+/* \r
+ * ======== UsbMscStateMachine.c ========\r
+ */\r
+/*File includes */\r
+#include "../USB_Common/device.h"\r
+#include "../USB_Common/defMSP430USB.h"\r
+#include "../USB_MSC_API/UsbMscScsi.h"\r
+#include "../USB_MSC_API/UsbMsc.h"\r
+#include "../USB_Common/usb.h"\r
+#include <descriptors.h>\r
+#include <string.h>\r
+\r
+#ifdef _MSC_\r
+\r
+/*Macros to indicate data direction */\r
+#define DIRECTION_IN    0x80\r
+#define DIRECTION_OUT   0x00\r
+\r
+/*Buffer pointers passed by application */\r
+extern __no_init tEDB __data16 tInputEndPointDescriptorBlock[];\r
+extern struct _MscState MscState;\r
+\r
+uint8_t Scsi_Verify_CBW ();\r
+\r
+/*----------------------------------------------------------------------------+\r
+ | Functions                                                                  |\r
+ +----------------------------------------------------------------------------*/\r
+void Msc_ResetStateMachine (void)\r
+{\r
+    MscState.bMscSendCsw = FALSE;\r
+    MscState.Scsi_Residue = 0;\r
+    MscState.Scsi_Status = SCSI_PASSED;             /*Variable to track command status */\r
+    MscState.bMcsCommandSupported = TRUE;           /*Flag to indicate read/write command is recieved from host */\r
+    MscState.bMscCbwReceived = 0;                   /*Flag to inidicate whether any CBW recieved from host*/\r
+    MscState.bMscSendCsw = FALSE;\r
+    MscState.isMSCConfigured = FALSE;\r
+    MscState.bUnitAttention = FALSE;\r
+    MscState.bMscCbwFailed = FALSE;\r
+    MscState.bMscResetRequired = FALSE;\r
+       MscState.stallEndpoint = FALSE;\r
+       MscState.stallAtEndofTx = FALSE;\r
+}\r
+\r
+//----------------------------------------------------------------------------\r
+/*This is the core function called by application to handle the MSC SCSI state\r
+* machine */\r
+\r
+//\r
+//! \endcond\r
+//\r
+\r
+//*****************************************************************************\r
+//\r
+//! Checks to See if a SCSI Command has Been Received.\r
+//!\r
+//! Checks to see if a SCSI command has been received. If so, it handles it. If not, it returns\r
+//! having taken no action.\r
+//! The return values of this function are intended to be used with entry of low-power modes. If the\r
+//! function returns \b kUSBMSC_okToSleep, then no further application action is required; that is,\r
+//! either no SCSI command was received; one was received but immediately handled; or one was\r
+//! received but the handling will be completed in the background by the API as it automatically\r
+//! services USB interrupts.\r
+//! If instead the function returns \b kUSBMSC_processBuffer, then the API is currently servicing a\r
+//! SCSI READ or WRITE command, and the API requires the application to process a buffer. (See\r
+//! Sec. 8.3.6 of \e "Programmer's Guide: MSP430 USB API Stack for CDC/PHDC/HID/MSC" for a discussion of buffer\r
+//! processing.)\r
+//! Note that even if the function returns these values, the values could potentially be outdated by\r
+//! the time the application evaluates them. For this reason, it's important to disable interrupts prior\r
+//! to calling this function. See Sec. 8.3.5 of \e "Programmer's Guide: MSP430 USB API Stack for CDC/PHDC/HID/MSC"\r
+//! for more information.\r
+//!\r
+//! \return \b kUSBMSC_okToSleep or \b kUSBMSC_processBuffer\r
+//\r
+//*****************************************************************************\r
+\r
+uint8_t USBMSC_poll ()\r
+{\r
+       uint16_t state;\r
+    uint8_t edbIndex;\r
+    uint8_t * pCT1;\r
+    uint8_t * pCT2;\r
+\r
+    edbIndex = stUsbHandle[MSC0_INTFNUM].edb_Index;\r
+    pCT1 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTX;\r
+    pCT2 = &tInputEndPointDescriptorBlock[edbIndex].bEPBCTY;\r
+\r
+    //check if currently transmitting data..\r
+    if (MscReadControl.bReadProcessing == TRUE){\r
+       state = usbDisableOutEndpointInterrupt(edbIndex);\r
+        //atomic operation - disable interrupts\r
+        if ((MscReadControl.dwBytesToSendLeft == 0) &&\r
+            (MscReadControl.lbaCount == 0)){\r
+            //data is no more processing - clear flags..\r
+            MscReadControl.bReadProcessing = FALSE;\r
+            usbRestoreOutEndpointInterrupt(state);\r
+        } else {\r
+            if (!(tInputEndPointDescriptorBlock[edbIndex].bEPCNF &\r
+                  EPCNF_STALL)){                    //if it is not stalled - contiune communication\r
+                USBIEPIFG |= 1 << (edbIndex + 1);   //trigger IN interrupt to finish data tranmition\r
+            }\r
+            usbRestoreOutEndpointInterrupt(state);\r
+            return (kUSBMSC_processBuffer);\r
+        }\r
+    }\r
+\r
+    if (MscState.isMSCConfigured == FALSE){\r
+        return (kUSBMSC_okToSleep);\r
+    }\r
+\r
+    if (!MscState.bMscSendCsw){\r
+        if (MscState.bMscCbwReceived){\r
+            if (Scsi_Verify_CBW() == SUCCESS){\r
+                //Successful reception of CBW\r
+                //Parse the CBW opcode and invoke the right command handler function\r
+                Scsi_Cmd_Parser(MSC0_INTFNUM);\r
+                MscState.bMscSendCsw = TRUE;\r
+            }\r
+            MscState.bMscCbwReceived = FALSE;       //CBW is performed!\r
+        } else {\r
+            return (kUSBMSC_okToSleep);\r
+        }\r
+        //check if any of out pipes has pending data and trigger interrupt\r
+\r
+        if ((MscWriteControl.pCT1 != NULL)   &&\r
+            ((*MscWriteControl.pCT1 & EPBCNT_NAK ) ||\r
+             (*MscWriteControl.pCT2 & EPBCNT_NAK ))){\r
+            USBOEPIFG |= 1 << (edbIndex + 1);       //trigger OUT interrupt again\r
+            return (kUSBMSC_processBuffer);            //do not asleep, as data is coming in\r
+            //and follow up data perform will be required.\r
+        }\r
+    }\r
+\r
+    if (MscState.bMscSendCsw){\r
+        if (MscState.bMcsCommandSupported == TRUE){\r
+            //watiting till transport is finished!\r
+            if ((MscWriteControl.bWriteProcessing == FALSE) &&\r
+                (MscReadControl.bReadProcessing == FALSE) &&\r
+                (MscReadControl.lbaCount == 0)){\r
+                //Send CSW\r
+                if (MscState.stallAtEndofTx == TRUE) {\r
+                       if ((*pCT1 & EPBCNT_NAK) && (*pCT2 & EPBCNT_NAK)) {\r
+                               MscState.stallAtEndofTx = FALSE;\r
+                               usbStallInEndpoint(MSC0_INTFNUM);\r
+                       }\r
+                }\r
+                else if (SUCCESS == Scsi_Send_CSW(MSC0_INTFNUM)){\r
+                    MscState.bMscSendCsw = FALSE;\r
+                    return (kUSBMSC_okToSleep);\r
+                }\r
+            }          \r
+            else {\r
+               MSCFromHostToBuffer();\r
+            }\r
+        }\r
+    }\r
+\r
+    return (kUSBMSC_processBuffer);                 //When MscState.bMcsCommandSupported = FALSE, bReadProcessing became true, and\r
+                                                    //bWriteProcessing = true.\r
+}\r
+\r
+//\r
+//! \cond\r
+//\r
+\r
+#endif //_MSC_\r
+\r
+//\r
+//! \endcond\r
+//\r
+\r
+/*----------------------------------------------------------------------------+\r
+ | End of source file                                                          |\r
+ +----------------------------------------------------------------------------*/\r
+/*------------------------ Nothing Below This Line --------------------------*/\r
+//Released_Version_4_10_02\r