aboutsummaryrefslogtreecommitdiffstats
path: root/ucs2-interface/ucs-xml/UcsXml.c
diff options
context:
space:
mode:
authorFulup Ar Foll <fulup@iot.bzh>2017-05-26 18:45:56 +0200
committerFulup Ar Foll <fulup@iot.bzh>2017-05-26 18:45:56 +0200
commitd2e42029ec04c3f224580f8007cdfbbfe0fc47a6 (patch)
treead2ccf167cf7997c84191d41e6ba55cb2efd6bed /ucs2-interface/ucs-xml/UcsXml.c
parent18e393e1443fd4c38b34979888fb55d30448cf31 (diff)
Initial Commit
Diffstat (limited to 'ucs2-interface/ucs-xml/UcsXml.c')
-rw-r--r--ucs2-interface/ucs-xml/UcsXml.c1174
1 files changed, 1174 insertions, 0 deletions
diff --git a/ucs2-interface/ucs-xml/UcsXml.c b/ucs2-interface/ucs-xml/UcsXml.c
new file mode 100644
index 0000000..cd7c477
--- /dev/null
+++ b/ucs2-interface/ucs-xml/UcsXml.c
@@ -0,0 +1,1174 @@
+/*
+ * Unicens XML Parser
+ *
+ * Copyright (C) 2017 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 2 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.
+ *
+ */
+#include <assert.h>
+#include <string.h>
+#include "mxml.h"
+#include "UcsXml.h"
+
+/************************************************************************/
+/* USER ADJUSTABLE CONSTANTS */
+/************************************************************************/
+
+#define MAX_JOB_LIST_LEN 6
+
+/************************************************************************/
+/* PRIVATE DECLARATIONS */
+/************************************************************************/
+
+#define COMPILETIME_CHECK(cond) (void)sizeof(int[!!(cond) - 1])
+
+struct UcsXmlObjectList
+{
+ void *obj;
+ struct UcsXmlObjectList *next;
+};
+
+struct UcsXmlRouteInfo
+{
+ bool isSource;
+ char routeName[32];
+ Ucs_Rm_EndPoint_t *ep;
+ struct UcsXmlRouteInfo *next;
+};
+
+struct UcsXmlScriptInfo
+{
+ char scriptName[32];
+ Ucs_Rm_Node_t *node;
+ struct UcsXmlScriptInfo *next;
+};
+
+typedef enum
+{
+ SYNC_DATA = 0, /*!< \brief Specifies the synchronous streaming data type */
+ CONTROL_DATA = 2, /*!< \brief Specifies the control data type */
+ AV_PACKETIZED = 3, /*!< \brief Specifies the A/V Packetized Isochronous
+ streaming data type */
+ QOS_IP = 4, /*!< \brief Specifies the Quality of Service IP
+ streaming data type*/
+ DISC_FRAME_PHASE = 5, /*!< \brief Specifies the DiscreteFrame Isochronous
+ streaming phase data type */
+ IPC_PACKET = 7, /*!< \brief Specifies the IPC packet data type */
+ INVALID = 0xFF /*!< \brief Defined invalid value */
+} MData_t;
+
+typedef enum
+{
+ MPORT_MOST,
+ MPORT_USB,
+ MPORT_MLB,
+ MPORT_I2S,
+ MPORT_INVALID = 0xFF
+} MPort_t;
+
+typedef enum
+{
+ Parse_Success = 10,
+ Parse_MemoryError,
+ Parse_XmlError
+} ParseResult_t;
+
+typedef struct {
+ struct UcsXmlObjectList objList;
+ struct UcsXmlRouteInfo *pRtLst;
+ struct UcsXmlScriptInfo *pScrLst;
+ Ucs_Rm_Node_t *nod;
+ Ucs_Xrm_ResObject_t *inSocket;
+ Ucs_Xrm_ResObject_t *outSocket;
+ Ucs_Xrm_ResObject_t **jobList;
+ MData_t dataType;
+ uint16_t blockWidth;
+ const char* chName;
+ uint16_t pause;
+} PrivateData_t;
+
+/************************************************************************/
+/* Constants */
+/************************************************************************/
+
+//Key section
+static const char* UNICENS = "unicens";
+static const char* ASYNC_BANDWIDTH = "async_bandwidth";
+static const char* CHANNEL = "channel";
+static const char* CHANNEL_NAME = "channel_name";
+static const char* ADDRESS = "channel_addr";
+static const char* BANDWIDTH = "bandwidth";
+static const char* OFFSET = "offset";
+static const char* DATA_TYPE = "data_type";
+static const char* DEVICE = "device";
+static const char* DEVICE_MLB_SPEED = "mlb_port_speed";
+static const char* NODE_ADDR = "node_address";
+static const char* DIR = "dir";
+static const char* I2S_PIN = "i2s_pin";
+static const char* PACKETS_XACT = "packets_per_xact";
+static const char* PORT = "port";
+static const char* SOCKET = "socket";
+
+static const char* I2S_FS_SPEED = "i2s_fs_speed";
+static const char* I2S_ALIGN = "i2s_align";
+
+//value section
+static const char* PORT_MOST = "MOST";
+static const char* PORT_USB = "USB";
+static const char* PORT_MLB = "MLB";
+static const char* PORT_I2S = "I2S";
+
+static const char* DATATYPE_SYNC = "SYNC";
+static const char* DATATYPE_AVP = "AVP";
+static const char* DATATYPE_CTRL = "CTRL";
+static const char* DATATYPE_QOS = "QOS";
+static const char* DATATYPE_DFP = "DFP";
+static const char* DATATYPE_IPC = "IPC";
+
+static const char* DIR_IN = "IN";
+static const char* DIR_OUT = "OUT";
+
+static const char* I2S_PIN_SRXA0 = "SRXA0";
+static const char* I2S_PIN_SRXA1 = "SRXA1";
+static const char* I2S_PIN_SRXB0 = "SRXB0";
+static const char* I2S_PIN_SRXB1 = "SRXB1";
+
+static const char* I2S_ALIGN_L16 = "Left16";
+static const char* I2S_ALIGN_L24 = "Left24";
+static const char* I2S_ALIGN_R16 = "Right16";
+static const char* I2S_ALIGN_R24 = "Right24";
+static const char* I2S_ALIGN_SEQUENTIAL = "Seq";
+
+static const char* SCRIPT = "script";
+static const char* ACTION = "action";
+static const char* NAME = "name";
+static const char* TYPE = "type";
+static const char* FBLOCK_ID = "fblock_id";
+static const char* FUNCTION_ID = "function_id";
+static const char* OP_TYPE_REQUEST = "op_request";
+static const char* OP_TYPE_RESPONSE = "op_response";
+static const char* PAYLOAD_REQ_HEX = "load_req_hex";
+static const char* PAYLOAD_RES_HEX = "load_res_hex";
+static const char* PAUSE_MS = "pause_ms";
+
+static const char* SEND_MSG = "SEND_MSG";
+static const char* PAUSE = "PAUSE";
+
+/************************************************************************/
+/* Private Function Prototypes */
+/************************************************************************/
+
+static void *MCalloc(struct UcsXmlObjectList *list, uint32_t nElem, uint32_t elemSize);
+static void FreeObjList(struct UcsXmlObjectList *cur);
+static void FreeVal(UcsXmlVal_t *v);
+static bool GetElement(mxml_node_t *element, const char *name, bool goDeep, mxml_node_t **out, bool mandatory);
+static bool GetCount(mxml_node_t *element, const char *name, uint32_t *out, bool mandatory);
+static bool GetString(mxml_node_t *element, const char *key, const char **out, bool mandatory);
+static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory);
+static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory);
+static bool GetMlbSpeed(mxml_node_t *element, const char *key, Ucs_Mlb_ClockConfig_t *clock, bool mandatory);
+static bool GetI2SSpeed(mxml_node_t *element, const char *key, Ucs_Stream_PortClockConfig_t *clock, bool mandatory);
+static bool GetI2SPin(mxml_node_t *element, Ucs_Stream_PortPinId_t *pin, uint8_t *portIndex, bool mandatory);
+static bool GetI2SAlignment(mxml_node_t *element, Ucs_Stream_PortDataAlign_t *align, bool mandatory);
+static bool GetDirection(mxml_node_t *element, Ucs_SocketDirection_t *out);
+static bool GetDataType(mxml_node_t *element, MData_t *out);
+static bool GetPort(mxml_node_t *element, MPort_t *out);
+static bool GetPayload(mxml_node_t *element, const char *name, uint8_t **pPayload, uint8_t *len,
+ struct UcsXmlObjectList *obj, bool mandatory);
+static bool AddJob(Ucs_Xrm_ResObject_t **joblist, Ucs_Xrm_ResObject_t *job);
+static void AddRoute(struct UcsXmlRouteInfo **pRtLst, struct UcsXmlRouteInfo *route);
+static void AddScript(struct UcsXmlScriptInfo **pScrLst, struct UcsXmlScriptInfo *script);
+static ParseResult_t ParseAll(mxml_node_t *tree, UcsXmlVal_t *v, PrivateData_t *vp);
+static ParseResult_t ParseDevice(mxml_node_t * dev, PrivateData_t *vp);
+static ParseResult_t ParseChannel(mxml_node_t * ch, PrivateData_t *vp);
+static ParseResult_t ParseSocket(mxml_node_t *soc, PrivateData_t *vp);
+static ParseResult_t ParseMostSoc(Ucs_Xrm_MostSocket_t *mostSoc, mxml_node_t *soc, PrivateData_t *vp);
+static ParseResult_t ParseUsbSoc(Ucs_Xrm_UsbSocket_t *usbSoc, mxml_node_t *soc, PrivateData_t *vp);
+static ParseResult_t ParseMlbSoc(Ucs_Xrm_MlbSocket_t *mlbSoc, mxml_node_t *soc, PrivateData_t *vp);
+static ParseResult_t ParseStreamSoc(Ucs_Xrm_StrmSocket_t *strmSoc, mxml_node_t *soc, PrivateData_t *vp);
+static ParseResult_t ParseScript(mxml_node_t *scr, PrivateData_t *vp);
+static ParseResult_t ParseScriptAction(mxml_node_t *act, Ucs_Rm_Node_t *n, uint32_t index, PrivateData_t *vp);
+static ParseResult_t ParseRoutes(UcsXmlVal_t *v, PrivateData_t *vp);
+
+/************************************************************************/
+/* Public Functions */
+/************************************************************************/
+
+UcsXmlVal_t *UcsXml_Parse(const char *xmlString)
+{
+ UcsXmlVal_t *v;
+ ParseResult_t result = Parse_Success;
+ mxml_node_t *tree = mxmlLoadString(NULL, xmlString, MXML_NO_CALLBACK);
+ if (!tree)
+ {
+ result = Parse_XmlError;
+ }
+ if (Parse_Success == result)
+ {
+ if (!GetElement(tree, UNICENS, true, &tree, true))
+ result = Parse_XmlError;
+ }
+ if (Parse_Success == result)
+ {
+ //Do not use MCalloc for the root element
+ v = calloc(1, sizeof(UcsXmlVal_t));
+ if (NULL == v) result = Parse_MemoryError;
+ }
+ if (Parse_Success == result)
+ {
+ //Do not use MCalloc for the private data
+ v->pInternal = calloc(1, sizeof(PrivateData_t));
+ if (NULL == v->pInternal) result = Parse_MemoryError;
+ }
+ if (Parse_Success == result)
+ {
+ result = ParseAll(tree, v, v->pInternal);
+ }
+ if (!tree)
+ {
+ mxmlDelete(tree);
+ }
+ if (Parse_Success == result)
+ {
+ return v;
+ }
+ if (Parse_MemoryError == result)
+ {
+ UcsXml_CB_OnError("XML error, aborting..", 0);
+ }
+ else
+ {
+ UcsXml_CB_OnError("Alloc error, aborting..", 0);
+ }
+ assert(false);
+ FreeVal(v);
+ return NULL;
+}
+
+void UcsXml_FreeVal(UcsXmlVal_t *val)
+{
+ FreeVal(val);
+}
+
+/************************************************************************/
+/* Private Function Implementations */
+/************************************************************************/
+
+static void *MCalloc(struct UcsXmlObjectList *list, uint32_t nElem, uint32_t elemSize)
+{
+ void *obj;
+ struct UcsXmlObjectList *tail = list;
+ if (NULL == list || 0 == nElem || 0 == elemSize) return NULL;
+
+ obj = calloc(nElem, elemSize);
+ if (NULL == obj)
+ {
+ assert(false);
+ return NULL;
+ }
+ if (NULL == list->obj)
+ {
+ list->obj = obj;
+ return obj;
+ }
+ while(tail->next) tail = tail->next;
+ tail->next = calloc(1, sizeof(struct UcsXmlObjectList));
+ if (NULL == tail->next)
+ {
+ assert(false);
+ free(obj);
+ return NULL;
+ }
+ tail->next->obj = obj;
+ return obj;
+}
+
+static void FreeObjList(struct UcsXmlObjectList *cur)
+{
+ struct UcsXmlObjectList *root = cur;
+ while(cur)
+ {
+ struct UcsXmlObjectList *next = cur->next;
+ assert(NULL != cur->obj);
+ if (cur->obj)
+ free(cur->obj);
+ if (cur != root)
+ free(cur);
+ cur = next;
+ }
+}
+
+static void FreeVal(UcsXmlVal_t *v)
+{
+ PrivateData_t *vp;
+ if (NULL == v || NULL == v->pInternal)
+ return;
+ vp = v->pInternal;
+ FreeObjList(&vp->objList);
+ free(v->pInternal);
+ free(v);
+}
+
+static bool GetElement(mxml_node_t *element, const char *name, bool goDeep, mxml_node_t **out, bool mandatory)
+{
+ mxml_node_t *n = element;
+ if (NULL == n || NULL == name || NULL == out) return false;
+ if (goDeep)
+ {
+ *out = mxmlFindElement(n, n, name, NULL, NULL, MXML_DESCEND);
+ return (NULL != *out);
+ }
+ while ((n = n->next))
+ {
+ if (MXML_ELEMENT != n->type)
+ continue;
+ if (0 == strcmp(name, n->value.opaque))
+ {
+ *out = n;
+ return true;
+ }
+ }
+ if (mandatory)
+ UcsXml_CB_OnError("Can not find tag <%s>", 1, name);
+ return false;
+}
+
+static bool GetCount(mxml_node_t *element, const char *name, uint32_t *out, bool mandatory)
+{
+ uint32_t cnt = 0;
+ mxml_node_t *n;
+ if (NULL == element || NULL == name) return false;
+ if(!GetElement(element, name, true, &n, false))
+ return false;
+ while(NULL != n)
+ {
+ ++cnt;
+ if(!GetElement(n, name, false, &n, false))
+ break;
+ }
+ if (mandatory && 0 == cnt)
+ {
+ UcsXml_CB_OnError("element count of <%s> is zero", 1, name);
+ return false;
+ }
+ *out = cnt;
+ return true;
+}
+
+static bool GetString(mxml_node_t *element, const char *key, const char **out, bool mandatory)
+{
+ uint32_t i;
+ if (NULL == element || NULL == key) return false;
+ for (i = 0; i < element->value.element.num_attrs; i++)
+ {
+ mxml_attr_t *attr = &element->value.element.attrs[i];
+ if (0 == strcmp(key, attr->name))
+ {
+ *out = attr->value;
+ return true;
+ }
+ }
+ if (mandatory)
+ UcsXml_CB_OnError("Can not find attribute='%s' from element <%s>",
+ 2, key, element->value.element.name);
+ return false;
+}
+
+static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory)
+{
+ const char* txt;
+ if (!GetString(element, key, &txt, mandatory)) return false;
+ *out = strtol( txt, NULL, 0 );
+ return true;
+}
+
+static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory)
+{
+ const char* txt;
+ if (!GetString(element, key, &txt, mandatory)) return false;
+ *out = strtol( txt, NULL, 0 );
+ return true;
+}
+
+static bool GetMlbSpeed(mxml_node_t *element, const char *key, Ucs_Mlb_ClockConfig_t *clock, bool mandatory)
+{
+ uint16_t speed;
+ if (!GetUInt16(element, DEVICE_MLB_SPEED, &speed, false))
+ return false;
+ switch(speed)
+ {
+ case 256: *clock = UCS_MLB_CLK_CFG_256_FS; break;
+ case 512: *clock = UCS_MLB_CLK_CFG_512_FS; break;
+ case 1024: *clock = UCS_MLB_CLK_CFG_1024_FS; break;
+ case 2048: *clock = UCS_MLB_CLK_CFG_2048_FS; break;
+ case 3072: *clock = UCS_MLB_CLK_CFG_3072_FS; break;
+ case 4096: *clock = UCS_MLB_CLK_CFG_4096_FS; break;
+ case 6144: *clock = UCS_MLB_CLK_CFG_6144_FS; break;
+ case 8192: *clock = UCS_MLB_CLK_CFG_8192_FS; break;
+ case 0: *clock = UCS_MLB_CLK_CFG_WILDCARD; break;
+ default:
+ UcsXml_CB_OnError("Invalid MLB clock val:'%d'", 1, clock);
+ return false;
+ }
+ return true;
+}
+
+static bool GetI2SSpeed(mxml_node_t *element, const char *key, Ucs_Stream_PortClockConfig_t *clock, bool mandatory)
+{
+ uint16_t speed;
+ if (!GetUInt16(element, I2S_FS_SPEED, &speed, false))
+ return false;
+ switch(speed)
+ {
+ case 8: *clock = UCS_STREAM_PORT_CLK_CFG_8FS; break;
+ case 16: *clock = UCS_STREAM_PORT_CLK_CFG_16FS; break;
+ case 32: *clock = UCS_STREAM_PORT_CLK_CFG_32FS; break;
+ case 64: *clock = UCS_STREAM_PORT_CLK_CFG_64FS; break;
+ case 128: *clock = UCS_STREAM_PORT_CLK_CFG_128FS; break;
+ case 256: *clock = UCS_STREAM_PORT_CLK_CFG_256FS; break;
+ case 512: *clock = UCS_STREAM_PORT_CLK_CFG_512FS; break;
+ case 0: *clock = UCS_MLB_CLK_CFG_WILDCARD; break;
+ default:
+ UcsXml_CB_OnError("Invalid I2S clock val:'%d'", 1, clock);
+ return false;
+ }
+ return true;
+}
+
+static bool GetI2SPin(mxml_node_t *element, Ucs_Stream_PortPinId_t *pin, uint8_t *portIndex, bool mandatory)
+{
+ const char *txt;
+ if (!GetString(element, I2S_PIN, &txt, true))
+ return false;
+ if (0 == strcmp(I2S_PIN_SRXA0, txt))
+ {
+ *pin = UCS_STREAM_PORT_PIN_ID_SRXA0;
+ *portIndex = 0;
+ return true;
+ }
+ else if (0 == strcmp(I2S_PIN_SRXA1, txt))
+ {
+ *pin = UCS_STREAM_PORT_PIN_ID_SRXA1;
+ *portIndex = 0;
+ return true;
+ }
+ else if (0 == strcmp(I2S_PIN_SRXB0, txt))
+ {
+ *pin = UCS_STREAM_PORT_PIN_ID_SRXB0;
+ *portIndex = 1;
+ return true;
+ }
+ else if (0 == strcmp(I2S_PIN_SRXB1, txt))
+ {
+ *pin = UCS_STREAM_PORT_PIN_ID_SRXB1;
+ *portIndex = 1;
+ return true;
+ }
+ UcsXml_CB_OnError("Invalid I2S pin val:'%s'", 1, txt);
+ return false;
+}
+
+static bool GetI2SAlignment(mxml_node_t *element, Ucs_Stream_PortDataAlign_t *align, bool mandatory)
+{
+ const char *txt;
+ if (!GetString(element, I2S_ALIGN, &txt, true))
+ return false;
+ if (0 == strcmp(I2S_ALIGN_L16, txt))
+ *align = UCS_STREAM_PORT_ALGN_LEFT16BIT;
+ else if (0 == strcmp(I2S_ALIGN_L24, txt))
+ *align = UCS_STREAM_PORT_ALGN_LEFT24BIT;
+ else if (0 == strcmp(I2S_ALIGN_R16, txt))
+ *align = UCS_STREAM_PORT_ALGN_RIGHT16BIT;
+ else if (0 == strcmp(I2S_ALIGN_R24, txt))
+ *align = UCS_STREAM_PORT_ALGN_RIGHT24BIT;
+ else if (0 == strcmp(I2S_ALIGN_SEQUENTIAL, txt))
+ *align = UCS_STREAM_PORT_ALGN_SEQ;
+ else
+ {
+ UcsXml_CB_OnError("Invalid I2S alignment:'%s'", 1, txt);
+ return false;
+ }
+ return true;
+}
+
+static bool GetDirection(mxml_node_t *element, Ucs_SocketDirection_t *out)
+{
+ const char *txt;
+ if (!GetString(element, DIR, &txt, true)) return false;
+ if (0 == strcmp(DIR_IN, txt))
+ *out = UCS_SOCKET_DIR_INPUT;
+ else if (0 == strcmp(DIR_OUT, txt))
+ *out = UCS_SOCKET_DIR_OUTPUT;
+ else
+ return false;
+ return true;
+}
+
+static bool GetDataType(mxml_node_t *element, MData_t *out)
+{
+ const char *txt;
+ if (!GetString(element, DATA_TYPE, &txt, true)) return false;
+ if (0 == strcmp(DATATYPE_SYNC, txt)) {
+ *out = SYNC_DATA;
+ } else if (0 == strcmp(DATATYPE_CTRL, txt)) {
+ *out = CONTROL_DATA;
+ } else if (0 == strcmp(DATATYPE_AVP, txt)) {
+ *out = AV_PACKETIZED;
+ } else if (0 == strcmp(DATATYPE_QOS, txt)) {
+ *out = QOS_IP;
+ } else if (0 == strcmp(DATATYPE_DFP, txt)) {
+ *out = DISC_FRAME_PHASE;
+ } else if (0 == strcmp(DATATYPE_IPC, txt)) {
+ *out = IPC_PACKET;
+ } else {
+ UcsXml_CB_OnError("Unknown data type : '%s'", 1, txt);
+ return false;
+ }
+ return true;
+}
+
+static bool GetPort(mxml_node_t *element, MPort_t *out)
+{
+ const char *txt;
+ if (!GetString(element, PORT, &txt, true)) return false;
+ if (0 == strcmp(txt, PORT_MOST)) {
+ *out = MPORT_MOST;
+ } else if (0 == strcmp(txt, PORT_USB)) {
+ *out = MPORT_USB;
+ } else if (0 == strcmp(txt, PORT_MLB)) {
+ *out = MPORT_MLB;
+ } else if (0 == strcmp(txt, PORT_I2S)) {
+ *out = MPORT_I2S;
+ } else {
+ UcsXml_CB_OnError("Unknown port : '%s'", 1, txt);
+ return false;
+ }
+ return true;
+}
+
+static bool GetPayload(mxml_node_t *element, const char *name, uint8_t **pPayload, uint8_t *outLen, struct UcsXmlObjectList *obj, bool mandatory)
+{
+ uint32_t tempLen, len = 0;
+ uint8_t *p;
+ const char *txt;
+ char *txtCopy;
+ char *tkPtr;
+ char *token;
+ if (!GetString(element, name, &txt, mandatory))
+ return false;
+ tempLen = strlen(txt) + 1;
+ txtCopy = malloc(tempLen);
+ if (NULL == txtCopy)
+ return false;
+ strncpy(txtCopy, txt, tempLen);
+ tempLen = tempLen / 3; /* 2 chars hex value plus space (AA ) */
+ p = MCalloc(obj, tempLen, 1);
+ if (NULL == p)
+ {
+ free(txtCopy);
+ return false;
+ }
+ *pPayload = p;
+ token = strtok_r( txtCopy, " ,.-", &tkPtr );
+ while( NULL != token )
+ {
+ if( len >= tempLen )
+ {
+ UcsXml_CB_OnError("Script payload values must be stuffed to two characters", 0);
+ free(txtCopy);
+ assert(false);
+ return 0;
+ }
+ p[len++] = strtol( token, NULL, 16 );
+ token = strtok_r( NULL, " ,.-", &tkPtr );
+ }
+ *outLen = len;
+ return true;
+}
+
+static bool AddJob(Ucs_Xrm_ResObject_t **joblist, Ucs_Xrm_ResObject_t *job)
+{
+ uint32_t i;
+ if (NULL == joblist || NULL == job)
+ {
+ assert(false);
+ return false;
+ }
+ for (i = 0; i < MAX_JOB_LIST_LEN; i++)
+ {
+ if (NULL == joblist[i])
+ {
+ joblist[i] = job;
+ return true;
+ }
+ }
+ assert(false);
+ return false;
+}
+
+static void AddRoute(struct UcsXmlRouteInfo **pRtLst, struct UcsXmlRouteInfo *route)
+{
+ struct UcsXmlRouteInfo *tail;
+ if (NULL == pRtLst || NULL == route) return;
+ if (NULL == pRtLst[0])
+ {
+ pRtLst[0] = route;
+ return;
+ }
+ tail = pRtLst[0];
+ while(tail->next) tail = tail->next;
+ tail->next = route;
+}
+
+static void AddScript(struct UcsXmlScriptInfo **pScrLst, struct UcsXmlScriptInfo *script)
+{
+ struct UcsXmlScriptInfo *tail;
+ if (NULL == pScrLst || NULL == script) return;
+ if (NULL == pScrLst[0])
+ {
+ pScrLst[0] = script;
+ return;
+ }
+ tail = pScrLst[0];
+ while(tail->next) tail = tail->next;
+ tail->next = script;
+}
+
+static ParseResult_t ParseAll(mxml_node_t *tree, UcsXmlVal_t *v, PrivateData_t *vp)
+{
+ uint32_t devCount;
+ mxml_node_t *sub;
+ ParseResult_t result;
+ if (!GetCount(tree, DEVICE, &devCount, true))
+ return Parse_XmlError;
+
+ v->pNod = MCalloc(&vp->objList, devCount, sizeof(Ucs_Rm_Node_t));
+ if (NULL == v->pNod) return Parse_MemoryError;
+
+ if (!GetUInt16(tree, ASYNC_BANDWIDTH, &v->packetBw, true))
+ return Parse_XmlError;
+
+ ///Iterate all devices
+ if (!GetElement(tree, DEVICE, true, &sub, true))
+ return Parse_XmlError;
+ while(sub)
+ {
+ mxml_node_t *ch;
+ vp->nod = &v->pNod[v->nodSize];
+ if (Parse_Success != (result = ParseDevice(sub, vp)))
+ return result;
+ ///Iterate all channels. Device without any channel is also valid.
+ if (GetElement(sub->child, CHANNEL, false, &ch, false))
+ {
+ while(ch)
+ {
+ mxml_node_t *soc;
+ uint8_t sockCnt = 0;
+ if (Parse_Success != (result = ParseChannel(ch, vp)))
+ return result;
+ ///Iterate all sockets
+ if(!GetElement(ch->child, SOCKET, false, &soc, true))
+ return Parse_XmlError;
+ while(soc)
+ {
+ ParseResult_t result;
+ if (Parse_Success != (result = ParseSocket(soc, vp)))
+ return result;
+ ++sockCnt;
+ if (!GetElement(soc, SOCKET, false, &soc, false))
+ break;
+ }
+ if (2 != sockCnt)
+ {
+ UcsXml_CB_OnError("%d sockets per channel found, must be 2", 1, sockCnt);
+ return Parse_XmlError;
+ }
+ if (!GetElement(ch, CHANNEL, false, &ch, false))
+ break;
+ }
+ }
+ ++v->nodSize;
+ if (!GetElement(sub, DEVICE, false, &sub, false))
+ break;
+ }
+
+ ///Fill route structures
+ result = ParseRoutes(v, vp);
+ if (Parse_MemoryError == result) return Parse_MemoryError;
+ else if (Parse_XmlError == result) return Parse_XmlError;
+
+ ///Iterate all scripts. No scripts at all is allowed
+ if(GetElement(tree, SCRIPT, true, &sub, false))
+ {
+ while(sub)
+ {
+ ParseResult_t result = ParseScript(sub, vp);
+ if (Parse_MemoryError == result) return Parse_MemoryError;
+ else if (Parse_XmlError == result) return Parse_XmlError;
+ if(!GetElement(sub, SCRIPT, false, &sub, false))
+ break;
+ }
+ }
+ return result;
+}
+
+static ParseResult_t ParseDevice(mxml_node_t * dev, PrivateData_t *vp)
+{
+ const char *txt;
+ assert(NULL != dev && NULL != vp);
+ vp->nod->signature_ptr = MCalloc(&vp->objList, 1, sizeof(Ucs_Signature_t));
+ if(NULL == vp->nod->signature_ptr) return Parse_MemoryError;
+ if (!GetUInt16(dev, NODE_ADDR, &vp->nod->signature_ptr->node_address, true))
+ return Parse_XmlError;
+ if (GetString(dev, SCRIPT, &txt, false))
+ {
+ struct UcsXmlScriptInfo *scr = MCalloc(&vp->objList, 1, sizeof(struct UcsXmlScriptInfo));
+ if (NULL == scr) return Parse_MemoryError;
+ scr->node = vp->nod;
+ strncpy(scr->scriptName, txt, sizeof(scr->scriptName));
+ AddScript(&vp->pScrLst, scr);
+ }
+ return Parse_Success;;
+}
+
+static ParseResult_t ParseChannel(mxml_node_t *ch, PrivateData_t *vp)
+{
+ vp->inSocket = NULL;
+ vp->outSocket = NULL;
+ vp->jobList = NULL;
+ vp->dataType = 0xFF;
+ vp->blockWidth = 0;
+ vp->chName = NULL;
+ assert(NULL != ch && NULL != vp);
+ if (!GetString(ch, CHANNEL_NAME, &vp->chName, true))
+ return Parse_XmlError;
+ if (!GetDataType(ch, &vp->dataType))
+ return Parse_XmlError;
+ if (!GetUInt16(ch, BANDWIDTH, &vp->blockWidth, true))
+ return Parse_XmlError;
+ vp->jobList = MCalloc(&vp->objList, MAX_JOB_LIST_LEN, sizeof(Ucs_Xrm_ResObject_t *));
+ if (NULL == vp->jobList) return Parse_MemoryError;
+ return Parse_Success;
+}
+
+static ParseResult_t ParseSocket(mxml_node_t *soc, PrivateData_t *vp)
+{
+ MPort_t port;
+ bool isIn = false;
+ bool isSource = false;
+ uint16_t offset = 0;
+ assert(NULL != soc && NULL != vp);
+ Ucs_SocketDirection_t direction;
+ if (!GetDirection(soc, &direction))
+ return Parse_XmlError;
+ isIn = (UCS_SOCKET_DIR_INPUT == direction);
+ if (!GetPort(soc, &port))
+ return Parse_XmlError;
+ switch(port)
+ {
+ case MPORT_MOST:
+ {
+ Ucs_Xrm_MostSocket_t *sock = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_MostSocket_t));
+ if (NULL == sock) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, sock)) return Parse_XmlError;
+ sock->data_type = vp->dataType;
+ sock->bandwidth = vp->blockWidth;
+ if (Parse_Success != ParseMostSoc(sock, soc, vp))
+ return Parse_XmlError;
+ isSource = (UCS_SOCKET_DIR_OUTPUT == direction);
+ if (isIn) vp->inSocket = sock; else vp->outSocket = sock;
+ break;
+ }
+ case MPORT_USB:
+ {
+ Ucs_Xrm_UsbSocket_t *sock = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_UsbSocket_t));
+ if (NULL == sock) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, sock)) return Parse_XmlError;
+ sock->data_type = vp->dataType;
+ if (Parse_Success != ParseUsbSoc(sock, soc, vp))
+ return Parse_XmlError;
+ if (isIn) vp->inSocket = sock; else vp->outSocket = sock;
+ break;
+ }
+ case MPORT_MLB:
+ {
+ Ucs_Xrm_MlbSocket_t *sock = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_MlbSocket_t));
+ if (NULL == sock) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, sock)) return Parse_XmlError;
+ sock->data_type = vp->dataType;
+ sock->bandwidth = vp->blockWidth;
+ if (Parse_Success != ParseMlbSoc(sock, soc, vp))
+ return Parse_XmlError;
+ if (isIn) vp->inSocket = sock; else vp->outSocket = sock;
+ break;
+ }
+ case MPORT_I2S:
+ {
+ Ucs_Xrm_StrmSocket_t *sock = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_StrmSocket_t));
+ if (NULL == sock) return Parse_MemoryError;
+ sock->data_type = vp->dataType;
+ sock->bandwidth = vp->blockWidth;
+ if (Parse_Success != ParseStreamSoc(sock, soc, vp))
+ return Parse_XmlError;
+ if (isIn) vp->inSocket = sock; else vp->outSocket = sock;
+ break;
+ }
+ default:
+ assert(false);
+ return Parse_XmlError;
+ }
+ if (GetUInt16(soc, OFFSET, &offset, false))
+ {
+ //TODO: If offset is non zero allocate Splitter / Combiner
+ }
+ //Connect in and out socket once they are created
+ if (vp->inSocket && vp->outSocket)
+ {
+ switch(vp->dataType)
+ {
+ case AV_PACKETIZED:
+ {
+ Ucs_Xrm_AvpCon_t *con = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_AvpCon_t));
+ if (NULL == con) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, con))
+ return Parse_XmlError;
+ con->resource_type = UCS_XRM_RC_TYPE_AVP_CON;
+ con->socket_in_obj_ptr = vp->inSocket;
+ con->socket_out_obj_ptr = vp->outSocket;
+ con->isoc_packet_size = UCS_ISOC_PCKT_SIZE_188; //TODO:Read from XML
+ break;
+ }
+ case SYNC_DATA:
+ {
+ Ucs_Xrm_SyncCon_t *con = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_SyncCon_t));
+ if (NULL == con) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, con))
+ return Parse_XmlError;
+ con->resource_type = UCS_XRM_RC_TYPE_SYNC_CON;
+ con->socket_in_obj_ptr = vp->inSocket;
+ con->socket_out_obj_ptr = vp->outSocket;
+ con->mute_mode = UCS_SYNC_MUTE_MODE_NO_MUTING; //TODO:Read from XML
+ con->offset = offset;
+ break;
+ }
+ default:
+ UcsXml_CB_OnError("Could not connect sockets, data type not implemented: %d", 1, vp->dataType);
+ return Parse_XmlError;
+ break;
+ }
+ Ucs_Rm_EndPoint_t *ep = MCalloc(&vp->objList, 1, sizeof(Ucs_Rm_EndPoint_t));
+ if (NULL == ep) return Parse_MemoryError;
+ ep->endpoint_type = isSource ? UCS_RM_EP_SOURCE : UCS_RM_EP_SINK;
+ ep->jobs_list_ptr = vp->jobList;
+ ep->node_obj_ptr = vp->nod;
+
+ struct UcsXmlRouteInfo *route = MCalloc(&vp->objList, 1, sizeof(struct UcsXmlRouteInfo));
+ if (NULL == route) return Parse_MemoryError;
+ route->isSource = isSource;
+ route->ep = ep;
+ strncpy(route->routeName, vp->chName, sizeof(route->routeName));
+ AddRoute(&vp->pRtLst, route);
+ }
+ return Parse_Success;
+}
+
+static ParseResult_t ParseMostSoc(Ucs_Xrm_MostSocket_t *mostSoc, mxml_node_t *soc, PrivateData_t *vp)
+{
+ assert(NULL != mostSoc && NULL != soc && NULL != vp);
+ COMPILETIME_CHECK(SYNC_DATA == (MData_t)UCS_MOST_SCKT_SYNC_DATA);
+ COMPILETIME_CHECK(AV_PACKETIZED == (MData_t)UCS_MOST_SCKT_AV_PACKETIZED);
+ COMPILETIME_CHECK(QOS_IP == (MData_t)UCS_MOST_SCKT_QOS_IP);
+ COMPILETIME_CHECK(DISC_FRAME_PHASE == (MData_t)UCS_MOST_SCKT_DISC_FRAME_PHASE);
+ switch((MData_t)mostSoc->data_type)
+ {
+ case SYNC_DATA:
+ case AV_PACKETIZED:
+ case QOS_IP:
+ case DISC_FRAME_PHASE:
+ break; //Nothing to do, valid values.
+ default:
+ UcsXml_CB_OnError("Invalid DataType=%d for MOST socket", 1, mostSoc->data_type);
+ return Parse_XmlError;
+ }
+ mostSoc->resource_type = UCS_XRM_RC_TYPE_MOST_SOCKET;
+ mostSoc->most_port_handle = 0x0D00;
+ if (!GetDirection(soc, &mostSoc->direction))
+ return Parse_XmlError;
+ return Parse_Success;
+}
+
+static ParseResult_t ParseUsbSoc(Ucs_Xrm_UsbSocket_t *usbSoc, mxml_node_t *soc, PrivateData_t *vp)
+{
+ Ucs_Xrm_DefaultCreatedPort_t *p;
+ assert(NULL != usbSoc && NULL != soc && NULL != vp);
+ COMPILETIME_CHECK(SYNC_DATA == (MData_t)UCS_USB_SCKT_SYNC_DATA);
+ COMPILETIME_CHECK(CONTROL_DATA == (MData_t)UCS_USB_SCKT_CONTROL_DATA);
+ COMPILETIME_CHECK(AV_PACKETIZED == (MData_t)UCS_USB_SCKT_AV_PACKETIZED);
+ switch((MData_t)usbSoc->data_type)
+ {
+ case SYNC_DATA:
+ case CONTROL_DATA:
+ case AV_PACKETIZED:
+ break; //Nothing to do, valid values.
+ default:
+ UcsXml_CB_OnError("Invalid DataType=%d for USB socket", 1, usbSoc->data_type);
+ return Parse_XmlError;
+ }
+ usbSoc->resource_type = UCS_XRM_RC_TYPE_USB_SOCKET;
+ if (!GetDirection(soc, &usbSoc->direction))
+ return Parse_XmlError;
+ if (!GetUInt8(soc, ADDRESS, &usbSoc->end_point_addr, true))
+ return Parse_XmlError;
+
+ if (!GetUInt16(soc, PACKETS_XACT, &usbSoc->frames_per_transfer, true))
+ return Parse_XmlError;
+
+ //XML provides currently no way to open USB port, so use ConfigString default
+ p = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_DefaultCreatedPort_t));
+ if (NULL == p) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, p)) return Parse_MemoryError;
+ p->resource_type = UCS_XRM_RC_TYPE_DC_PORT;
+ p->port_type = UCS_XRM_PORT_TYPE_USB;
+ p->index = 0;
+ usbSoc->usb_port_obj_ptr = p;
+ return Parse_Success;
+}
+
+static ParseResult_t ParseMlbSoc(Ucs_Xrm_MlbSocket_t *mlbSoc, mxml_node_t *soc, PrivateData_t *vp)
+{
+ Ucs_Mlb_ClockConfig_t clock;
+ assert(NULL != mlbSoc && NULL != soc && NULL != vp);
+ COMPILETIME_CHECK(SYNC_DATA == (MData_t)UCS_MLB_SCKT_SYNC_DATA);
+ COMPILETIME_CHECK(CONTROL_DATA == (MData_t)UCS_MLB_SCKT_CONTROL_DATA);
+ COMPILETIME_CHECK(AV_PACKETIZED == (MData_t)UCS_USB_SCKT_AV_PACKETIZED);
+ COMPILETIME_CHECK(QOS_IP == (MData_t)UCS_MLB_SCKT_QOS_IP);
+ COMPILETIME_CHECK(DISC_FRAME_PHASE == (MData_t)UCS_MLB_SCKT_DISC_FRAME_PHASE);
+ COMPILETIME_CHECK(IPC_PACKET == (MData_t)UCS_MLB_SCKT_IPC_PACKET);
+ switch((MData_t)mlbSoc->data_type)
+ {
+ case SYNC_DATA:
+ case CONTROL_DATA:
+ case AV_PACKETIZED:
+ case QOS_IP:
+ case DISC_FRAME_PHASE:
+ case IPC_PACKET:
+ break; //Nothing to do, valid values.
+ default:
+ UcsXml_CB_OnError("Invalid DataType=%d for MLB socket", 1, mlbSoc->data_type);
+ return Parse_XmlError;
+ }
+ mlbSoc->resource_type = UCS_XRM_RC_TYPE_MLB_SOCKET;
+ if (!GetDirection(soc, &mlbSoc->direction))
+ return Parse_XmlError;
+ if (!GetUInt16(soc, ADDRESS, &mlbSoc->channel_address, true))
+ return Parse_XmlError;
+
+ //Create MLB port when DEVICE_MLB_SPEED is defined, otherwise use ConfigString default
+ if (GetMlbSpeed(soc, DEVICE_MLB_SPEED, &clock, false))
+ {
+ Ucs_Xrm_MlbPort_t *p = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_MlbPort_t));
+ if (NULL == p) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, p)) return Parse_MemoryError;
+ p->resource_type = UCS_XRM_RC_TYPE_MLB_PORT;
+ p->index = 0;
+ p->clock_config = clock;
+ mlbSoc->mlb_port_obj_ptr = p;
+ } else {
+ Ucs_Xrm_DefaultCreatedPort_t *p = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_DefaultCreatedPort_t));
+ if (NULL == p) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, p)) return Parse_MemoryError;
+ p->resource_type = UCS_XRM_RC_TYPE_DC_PORT;
+ p->port_type = UCS_XRM_PORT_TYPE_MLB;
+ p->index = 0;
+ mlbSoc->mlb_port_obj_ptr = p;
+ }
+ return Parse_Success;
+}
+
+static ParseResult_t ParseStreamSoc(Ucs_Xrm_StrmSocket_t *strmSoc, mxml_node_t *soc, PrivateData_t *vp)
+{
+ const char *txt;
+ Ucs_Xrm_StrmPort_t *strPort;
+ assert(NULL != strmSoc && NULL != soc && NULL != vp);
+ COMPILETIME_CHECK(SYNC_DATA == (MData_t)UCS_STREAM_PORT_SCKT_SYNC_DATA);
+ if (SYNC_DATA != (MData_t)strmSoc->data_type)
+ {
+ UcsXml_CB_OnError("Invalid DataType=%d for I2S socket", 1, strmSoc->data_type);
+ return Parse_XmlError;
+ }
+ strPort = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_StrmPort_t));
+ if (NULL == strPort) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, strPort)) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, strmSoc)) return Parse_MemoryError;
+ strmSoc->resource_type = UCS_XRM_RC_TYPE_STRM_SOCKET;
+ strmSoc->stream_port_obj_ptr = strPort;
+
+ strPort->resource_type = UCS_XRM_RC_TYPE_STRM_PORT;
+ if (!GetDirection(soc, &strmSoc->direction))
+ return Parse_XmlError;
+ if (!GetI2SPin(soc, &strmSoc->stream_pin_id, &strPort->index, true))
+ return Parse_XmlError;
+ if (!GetI2SSpeed(soc, I2S_FS_SPEED, &strPort->clock_config, true))
+ return Parse_XmlError;
+ if (!GetString(soc, I2S_ALIGN, &txt, true))
+ return Parse_XmlError;
+ if (!GetI2SAlignment(soc, &strPort->data_alignment, true))
+ return Parse_XmlError;
+ return Parse_Success;
+}
+
+static ParseResult_t ParseScript(mxml_node_t *scr, PrivateData_t *vp)
+{
+ mxml_node_t *act;
+ uint32_t actCnt;
+ uint32_t i = 0;
+ const char *txt;
+ assert(NULL != scr && NULL != vp);
+ vp->pause = 0;
+ if (!GetString(scr, NAME, &txt, true))
+ return Parse_XmlError;
+ Ucs_Rm_Node_t *n = NULL;
+ struct UcsXmlScriptInfo *scrlist = vp->pScrLst;
+ while(NULL != scrlist)
+ {
+ if (0 == strcmp(txt, scrlist->scriptName))
+ {
+ n = scrlist->node;
+ break;
+ }
+ scrlist = scrlist->next;
+ }
+ if (NULL == n)
+ {
+ UcsXml_CB_OnError("Script defined:'%s', which was never referenced", 1, txt);
+ return Parse_XmlError;
+ }
+ if (!GetCount(scr, ACTION, &actCnt, true)) return Parse_XmlError;
+ if (NULL == (n->script_list_ptr = MCalloc(&vp->objList, actCnt, sizeof(Ucs_Ns_Script_t))))
+ return Parse_MemoryError;
+ n->script_list_size = actCnt;
+ ///Iterate all actions
+ if (!GetElement(scr, ACTION, true, &act, true)) return false;
+ while(act)
+ {
+ ParseResult_t result = ParseScriptAction(act, n, i, vp);
+ if (Parse_Success != result) return result;
+ if (!GetElement(act, ACTION, false, &act, false))
+ break;
+ ++i;
+ }
+ return Parse_Success;
+}
+
+static ParseResult_t ParseScriptAction(mxml_node_t *act, Ucs_Rm_Node_t *n, uint32_t index, PrivateData_t *vp)
+{
+ const char *txt;
+ uint8_t opResult;
+ assert(NULL != act && NULL != vp);
+ Ucs_Ns_Script_t *scr = &n->script_list_ptr[index];
+ if (!GetString(act, TYPE, &txt, true))
+ return Parse_XmlError;
+ if (0 == strcmp(txt, SEND_MSG))
+ {
+ Ucs_Ns_ConfigMsg_t *req;
+ scr->send_cmd = MCalloc(&vp->objList, 1, sizeof(Ucs_Ns_ConfigMsg_t));
+ req = scr->send_cmd;
+ if (NULL == req) return Parse_MemoryError;
+ scr->pause = vp->pause;
+ if (vp->pause) vp->pause = 0;
+ req->InstId = 1;
+ if (!GetUInt8(act, FBLOCK_ID, &req->FBlockId, true))
+ return Parse_XmlError;
+
+ if (!GetUInt16(act, FUNCTION_ID, &req->FunktId, true))
+ return Parse_XmlError;
+
+ if (!GetUInt8(act, OP_TYPE_REQUEST, &req->OpCode, true))
+ return Parse_XmlError;
+
+ if (GetUInt8(act, OP_TYPE_RESPONSE, &opResult, false))
+ {
+ //Waiting for response is optional
+ Ucs_Ns_ConfigMsg_t *res;
+ scr->exp_result = MCalloc(&vp->objList, 1, sizeof(Ucs_Ns_ConfigMsg_t));
+ res = scr->exp_result;
+ res->FBlockId = req->FBlockId;
+ res->InstId = req->InstId;
+ res->FunktId = req->FunktId;
+ res->OpCode = opResult;
+ //Not interested in result:
+ GetPayload(act, PAYLOAD_RES_HEX, &res->DataPtr, &res->DataLen, &vp->objList, false);
+ }
+ if (!GetPayload(act, PAYLOAD_REQ_HEX, &req->DataPtr, &req->DataLen, &vp->objList, true))
+ return Parse_XmlError;
+ if (0 == req->DataLen || NULL == req->DataPtr)
+ return Parse_XmlError;
+ }
+ else if (0 == strcmp(txt, PAUSE))
+ {
+ if (!GetUInt16(act, PAUSE_MS, &vp->pause, true))
+ return Parse_XmlError;
+ }
+ return Parse_Success;
+}
+
+static ParseResult_t ParseRoutes(UcsXmlVal_t *v, PrivateData_t *vp)
+{
+ uint16_t routeAmount = 0;
+ struct UcsXmlRouteInfo *sourceRoute;
+ assert(NULL != v && NULL != vp);
+ //First: Count the amount of routes and allocate the correct amount
+ sourceRoute = vp->pRtLst;
+ while (NULL != sourceRoute)
+ {
+ if (!sourceRoute->isSource) //There can be more sinks than sources, so count them
+ {
+ ++routeAmount;
+ }
+ sourceRoute = sourceRoute->next;
+ }
+ if (0 == routeAmount)
+ return Parse_Success; //Its okay to have no routes at all (e.g. MEP traffic only)
+ v->pRoutes = MCalloc(&vp->objList, routeAmount, sizeof(Ucs_Rm_Route_t));
+ if (NULL == v->pRoutes) return Parse_MemoryError;
+
+ //Second: Fill allocated structure now
+ sourceRoute = vp->pRtLst;
+ while (NULL != sourceRoute)
+ {
+ if (sourceRoute->isSource)
+ {
+ struct UcsXmlRouteInfo *sinkRoute = vp->pRtLst;
+ while (NULL != sinkRoute)
+ {
+ if (sourceRoute != sinkRoute
+ && !sinkRoute->isSource
+ && (0 == strncmp(sourceRoute->routeName, sinkRoute->routeName, sizeof(sourceRoute->routeName))))
+ {
+ Ucs_Rm_Route_t *route = &v->pRoutes[v->routesSize++];
+ route->source_endpoint_ptr = sourceRoute->ep;
+ route->sink_endpoint_ptr = sinkRoute->ep;
+ route->active = 1;
+ }
+ sinkRoute = sinkRoute->next;
+ }
+ }
+ sourceRoute = sourceRoute->next;
+ }
+ return Parse_Success;
+}