summaryrefslogtreecommitdiffstats
path: root/Src/Network/IndustrialStack.h
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Network/IndustrialStack.h')
-rw-r--r--Src/Network/IndustrialStack.h238
1 files changed, 238 insertions, 0 deletions
diff --git a/Src/Network/IndustrialStack.h b/Src/Network/IndustrialStack.h
new file mode 100644
index 0000000..fc42f66
--- /dev/null
+++ b/Src/Network/IndustrialStack.h
@@ -0,0 +1,238 @@
+/*
+ * Video On Demand Samples
+ *
+ * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+
+/*----------------------------------------------------------*/
+/*! \file
+ * \brief This file contains the CIndustrialStack class (common part).
+ */
+/*----------------------------------------------------------*/
+
+#ifndef INDUSTRIAL_STACK_H
+#define INDUSTRIAL_STACK_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+#include "SafeVector.h"
+#include "IndustrialStack_Types.h"
+#include "IndustrialStack_MNS.h"
+#include "Console.h"
+
+class CIndustrialStack : IISNetServiceWrapperCB
+{
+private:
+ CISNetServiceWrapper *msnw;
+ CSafeVector<CISDeviceQueue *> deviceQueues;
+ CSafeVector<CSInternalEvent *> intEventListeners;
+ CISDeviceQueue *GetQueue(uint16_t deviceType);
+ void HandleStateChange(ISReturn_t state, IISElement * element);
+public:
+ CIndustrialStack(uint8_t deviceApi, int controlRxHandle, int controlTxHandle);
+ virtual ~CIndustrialStack();
+ void ServiceStack(uint32_t time);
+ void EnqueueElement(uint16_t nodeAddress, IISElement *element);
+ bool ElementsPending();
+ bool ElementsPending(uint16_t ingoreNodeAddress);
+ void ClearAllElements();
+ bool SendMostMessage(CISMostMsg *message);
+ void Unsynchronize();
+ void AddInternalEventListener(CSInternalEvent* callback);
+
+ /* Callback from IISNetServiceWrapperCB interface */
+ virtual void OnReceivedMostMessage(CISMostMsg *rcvMessage);
+ virtual void OnSyncStateChanged(bool isSynced);
+ virtual void OnControlReadEnd();
+};
+
+class CISWaitElement : public IISElement
+{
+protected:
+ uint32_t startTime;
+ uint32_t timeout;
+public:
+ CISWaitElement() : IISElement(), startTime(0), timeout(2000)
+ {
+ ElementName = "Wait Element";
+ }
+
+ void SetTimeout(uint32_t timeInMillis)
+ {
+ timeout = timeInMillis;
+ }
+
+ virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time)
+ {
+ assert(NULL != iStack);
+ if (0 == startTime)
+ startTime = time;
+ else if ( ( time - startTime >= timeout ) )
+ return ISReturn_Success;
+ return ISReturn_NoChange;
+ }
+
+ virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *rcvMessage)
+ {
+ assert(NULL != iStack);
+ return ISReturn_NoChange;
+ }
+};
+
+class CISWaitForPendingElements : public CISWaitElement
+{
+private:
+ uint16_t ignoreNode;
+public:
+ CISWaitForPendingElements(uint16_t ingoreNodeAddress)
+ : CISWaitElement(), ignoreNode(ingoreNodeAddress)
+ {
+ }
+
+ virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time)
+ {
+ assert(NULL != iStack);
+ if (!iStack->ElementsPending(ignoreNode))
+ return ISReturn_Success;
+ return (CISWaitElement::Service(iStack, time) == ISReturn_NoChange)
+ ? ISReturn_NoChange : ISReturn_Timeout;
+ }
+};
+
+class CISSendMostMsgElement : public CISWaitElement
+{
+private:
+ uint8_t retryCount;
+public:
+ CISMostMsg Request;
+ CISMostMsg Response;
+ bool WaitForResponse;
+ CISOpType_t WaitForResponseOpType;
+
+ CISSendMostMsgElement() : CISWaitElement(), retryCount(4),
+ WaitForResponse(false),
+ WaitForResponseOpType(CISOpType_INVALID)
+ {
+ timeout = 500;
+ }
+
+ virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time)
+ {
+ assert(NULL != iStack);
+ if (0 == startTime)
+ {
+ CISWaitElement::Service(iStack, time);
+ if (Request.IsValid == false || Request.FBlock == 0xFFFFFFFF
+ || Request.Func == 0xFFFFFFFF || Request.Inst == 0xFFFFFFFF
+ || Request.OpType == CISOpType_INVALID)
+ {
+ ConsolePrintf(PRIO_ERROR,
+ RED"CISSendMostMsgElement %s invalid MOST message to be"\
+ " sent"RESETCOLOR"\n", ElementName);
+ return ISReturn_Failure;
+ }
+ bool success = iStack->SendMostMessage(&Request);
+ if (success && !WaitForResponse)
+ return ISReturn_Success;
+ return success ? ISReturn_NoChange : ISReturn_Failure;
+ }
+ ISReturn_t waitState = CISWaitElement::Service(iStack, time);
+ if (ISReturn_Success == waitState)
+ {
+ if (0 == --retryCount)
+ {
+ ConsolePrintf(PRIO_ERROR, RED"All High level retries failed for Request '%s',"\
+ " node 0x%X!"RESETCOLOR"\n",
+ ElementName, Request.TargetAddress);
+ return ISReturn_Timeout;
+ }
+ //Retry sending
+ ConsolePrintf(PRIO_HIGH, YELLOW"High level retry after timeout for Request '%s',"\
+ " node 0x%X"RESETCOLOR"\n",
+ ElementName, Request.TargetAddress);
+ startTime = time;
+ return (iStack->SendMostMessage(&Request)) ? ISReturn_NoChange : ISReturn_Failure;
+ }
+ return ISReturn_NoChange;
+ }
+
+ virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *rcvMessage)
+ {
+ if (!WaitForResponse)
+ return ISReturn_NoChange;
+ assert(NULL != iStack);
+ assert(NULL != rcvMessage);
+ assert(Request.IsValid);
+ assert(rcvMessage->IsValid);
+
+ uint32_t requestAddr = Request.TargetAddress;
+ uint32_t responseAddr = rcvMessage->SourceAddress;
+ if (requestAddr >= 0x400 && requestAddr <= 0x4FF )
+ requestAddr -= 0x300;
+ if (responseAddr >= 0x400 && responseAddr <= 0x4FF )
+ responseAddr -= 0x300;
+
+ if ( ( requestAddr < 0x300 || requestAddr > 0x3FF )
+ && ( responseAddr != requestAddr))
+ return ISReturn_NoChange;
+
+ if ( rcvMessage->FBlock == Request.FBlock
+ && rcvMessage->Func == Request.Func)
+ {
+ if (rcvMessage->OpType == WaitForResponseOpType)
+ {
+ Response.DeepCopy(rcvMessage);
+ return ISReturn_Success;
+ }
+ else if(0 == --retryCount)
+ {
+ Response.DeepCopy(rcvMessage);
+ return ISReturn_Failure;
+ }
+ //Retry sending
+ ConsolePrintf(PRIO_HIGH, YELLOW"High level retry after wrong result for Request '%s',"\
+ " node 0x%X"RESETCOLOR"\n",
+ ElementName, Request.TargetAddress);
+ return (iStack->SendMostMessage(&Request)) ? ISReturn_NoChange : ISReturn_Failure;
+ }
+ return ISReturn_NoChange;
+ }
+};
+
+class CSInternalEvent : public IISElement
+{
+public:
+ virtual ISReturn_t Service(CIndustrialStack *iStack, uint32_t time)
+ {
+ //Must not be called
+ return ISReturn_Failure;
+ }
+ virtual ISReturn_t OnMostMessage(CIndustrialStack *iStack, CISMostMsg *r)
+ {
+ //Must not be called
+ return ISReturn_Failure;
+ }
+ virtual void OnSyncStateChanged(CIndustrialStack *iStack, bool isSynced) {}
+ virtual void OnControlReadEnd(CIndustrialStack *iStack) {}
+};
+
+#endif //INDUSTRIAL_STACK_H