summaryrefslogtreecommitdiffstats
path: root/Src/Network/IndustrialStack.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Network/IndustrialStack.cpp')
-rw-r--r--Src/Network/IndustrialStack.cpp275
1 files changed, 275 insertions, 0 deletions
diff --git a/Src/Network/IndustrialStack.cpp b/Src/Network/IndustrialStack.cpp
new file mode 100644
index 0000000..e84ab22
--- /dev/null
+++ b/Src/Network/IndustrialStack.cpp
@@ -0,0 +1,275 @@
+/*
+ * 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.
+ */
+/*----------------------------------------------------------*/
+
+//#define CON_TRACE
+
+#define DISABLE_PARALLEL_MODE
+
+#include <assert.h>
+#include "IndustrialStack.h"
+
+CIndustrialStack::CIndustrialStack(uint8_t deviceApi, int controlRxHandle, int controlTxHandle)
+{
+ msnw = new CISNetServiceWrapper(deviceApi, controlRxHandle, controlTxHandle);
+ msnw->AddListener(this);
+ GetQueue(0x3C8); //Make sure that Broadcast queue is the first one
+}
+
+CIndustrialStack::~CIndustrialStack()
+{
+ delete msnw;
+ deviceQueues.RemoveAll(true);
+ intEventListeners.RemoveAll(false);
+}
+
+void CIndustrialStack::EnqueueElement(uint16_t nodeAddress, IISElement *element)
+{
+ CISDeviceQueue *dev = GetQueue(nodeAddress);
+ assert(NULL != dev);
+ element->AddReference();
+ dev->elements.PushBack(element);
+}
+
+void CIndustrialStack::ServiceStack(uint32_t time)
+{
+ for (uint32_t i = 0; i < deviceQueues.Size(); i++)
+ {
+ assert(NULL != deviceQueues[i]);
+ if (deviceQueues[i]->elements.Size() == 0)
+ continue;
+ IISElement *element = deviceQueues[i]->elements[0];
+ assert(NULL != element);
+ ISReturn_t state = element->Service(this, time);
+ if (state == ISReturn_NoChange)
+ continue;
+ deviceQueues[i]->elements.PopFront();
+ HandleStateChange(state, element);
+ element->RemoveReference();
+ msnw->ServiceMns();
+ }
+ msnw->ServiceMns();
+}
+
+bool CIndustrialStack::ElementsPending()
+{
+ for (uint32_t i = 0; i < deviceQueues.Size(); i++)
+ {
+ assert(NULL != deviceQueues[i]);
+ if (deviceQueues[i]->elements.Size() != 0)
+ return true;
+ }
+ return false;
+}
+
+bool CIndustrialStack::ElementsPending(uint16_t ingoreNodeAddress)
+{
+ for (uint32_t i = 0; i < deviceQueues.Size(); i++)
+ {
+ CISDeviceQueue *q = deviceQueues[i];
+ assert(NULL != q);
+ if (q->GetNodeAddress() == ingoreNodeAddress)
+ continue;
+ if (q->elements.Size() != 0)
+ return true;
+ }
+ return false;
+}
+
+void CIndustrialStack::ClearAllElements()
+{
+ for (uint32_t i = 0; i < deviceQueues.Size(); i++)
+ {
+ assert(NULL != deviceQueues[i]);
+ deviceQueues[i]->elements.RemoveAll(true);
+ }
+}
+
+bool CIndustrialStack::SendMostMessage(CISMostMsg *message)
+{
+ assert(NULL != msnw);
+ assert(NULL != message);
+ if (NULL == message)
+ return false;
+#ifdef CON_TRACE
+ ConsolePrintfStart(PRIO_HIGH, "IS TX, node:0x%X," \
+ " fblock:0x%X, func:0x%X, op:0x%X pl:0x[", message->TargetAddress,
+ message->FBlock, message->Func, message->OpType);
+ for (uint32_t i = 0; i < message->PayloadLen; i++)
+ ConsolePrintfContinue(" %02X", message->Payload[i]);
+ ConsolePrintfExit(" ]\n");
+#endif
+ bool success = msnw->SendMostMessage(message);
+ for (uint32_t i = 0; success && i < intEventListeners.Size(); i++)
+ {
+ intEventListeners[i]->OnMostMessage(this, message);
+ }
+ return success;
+}
+
+void CIndustrialStack::Unsynchronize()
+{
+ assert(NULL != msnw);
+ return msnw->Unsynchronize();
+}
+
+void CIndustrialStack::AddInternalEventListener(CSInternalEvent* callback)
+{
+ intEventListeners.PushBack(callback);
+}
+
+/*--------------------------
+ * Callback from MSN Wrapper
+ *--------------------------
+ */
+
+void CIndustrialStack::OnReceivedMostMessage(CISMostMsg *rcvMessage)
+{
+ assert(NULL != rcvMessage);
+ assert(rcvMessage->IsValid);
+#ifdef CON_TRACE
+ ConsolePrintfStart(PRIO_HIGH, "IS RX, node:0x%X," \
+ " fblock:0x%X, func:0x%X, op:0x%X pl:0x[", rcvMessage->SourceAddress,
+ rcvMessage->FBlock, rcvMessage->Func, rcvMessage->OpType);
+ for (uint32_t i = 0; i < rcvMessage->PayloadLen; i++)
+ ConsolePrintfContinue(" %02X", rcvMessage->Payload[i]);
+ ConsolePrintfExit(" ]\n");
+#endif
+ if (CISOpType_ERROR == rcvMessage->OpType
+ || CISOpType_ERRORACK == rcvMessage->OpType)
+ {
+ //Ignore Destroy Resource Errors
+ if (rcvMessage->Func != 0x800)
+ {
+ ConsolePrintfStart(PRIO_ERROR, RED"Received error message, node:0x%X," \
+ " fblock:0x%X, func:0x%X, op:0x%X pl:0x[", rcvMessage->SourceAddress,
+ rcvMessage->FBlock, rcvMessage->Func, rcvMessage->OpType);
+ for (uint32_t i = 0; i < rcvMessage->PayloadLen; i++)
+ ConsolePrintfContinue(" %02X", rcvMessage->Payload[i]);
+ ConsolePrintfExit(" ]"RESETCOLOR"\n");
+ }
+ }
+ for (uint32_t i = 0; i < deviceQueues.Size(); i++)
+ {
+ assert(NULL != deviceQueues[i]);
+ IISElement *element = deviceQueues[i]->elements[0];
+ if (NULL == element)
+ continue;
+ ISReturn_t state = element->OnMostMessage(this, rcvMessage);
+ if (state == ISReturn_NoChange)
+ continue;
+ deviceQueues[i]->elements.PopFront();
+ HandleStateChange(state, element);
+ element->RemoveReference();
+ }
+ for (uint32_t i = 0; i < intEventListeners.Size(); i++)
+ {
+ intEventListeners[i]->OnMostMessage(this, rcvMessage);
+ }
+}
+
+void CIndustrialStack::OnSyncStateChanged(bool isSynced)
+{
+ for (uint32_t i = 0; i < intEventListeners.Size(); i++)
+ {
+ assert(NULL != intEventListeners[i]);
+ intEventListeners[i]->OnSyncStateChanged(this, isSynced);
+ }
+}
+
+void CIndustrialStack::OnControlReadEnd()
+{
+ for (uint32_t i = 0; i < intEventListeners.Size(); i++)
+ {
+ assert(NULL != intEventListeners[i]);
+ intEventListeners[i]->OnControlReadEnd(this);
+ }
+}
+
+/*--------------------------
+ * Private helper functions:
+ *--------------------------
+ */
+
+#ifdef DISABLE_PARALLEL_MODE
+CISDeviceQueue *CIndustrialStack::GetQueue(uint16_t nodeAddress)
+{
+ CISDeviceQueue *dev = deviceQueues[0];
+ if (NULL == dev)
+ {
+ ConsolePrintf(PRIO_HIGH, GREEN"Creating new Device Queue"RESETCOLOR"\n");
+ dev = new CISDeviceQueue(0);
+ deviceQueues.PushBack(dev);
+ }
+ return dev;
+}
+#else
+CISDeviceQueue *CIndustrialStack::GetQueue(uint16_t nodeAddress)
+{
+ CISDeviceQueue *dev = NULL;
+ if (nodeAddress >= 0x400 && nodeAddress <= 0x4FF)
+ nodeAddress -= 0x300;
+ for (uint32_t i = 0; i < deviceQueues.Size(); i++)
+ {
+ if (deviceQueues[i]->GetNodeAddress() == nodeAddress)
+ {
+ dev = deviceQueues[i];
+ break;
+ }
+ }
+ if (NULL == dev)
+ {
+ ConsolePrintf(PRIO_HIGH, GREEN"Creating new Device Queue for"\
+ " node address:0x%02X"RESETCOLOR"\n", nodeAddress);
+ dev = new CISDeviceQueue(nodeAddress);
+ deviceQueues.PushBack(dev);
+ }
+ return dev;
+}
+#endif
+
+void CIndustrialStack::HandleStateChange(ISReturn_t state, IISElement * element)
+{
+ assert(NULL != element);
+ switch (state)
+ {
+ case ISReturn_Failure:
+ case ISReturn_Timeout:
+ ConsolePrintf(PRIO_ERROR, RED"Job '%s' %s"RESETCOLOR"\n",
+ element->ElementName, state == ISReturn_Failure ? "failed" : "timed out");
+ case ISReturn_Success:
+ if (NULL != element->Callback)
+ element->Callback->ElementProcessed(this, state, element);
+ break;
+ case ISReturn_NoChange:
+ //Nothing to do
+ break;
+ default:
+ assert(false);
+ }
+}