Merge pull request #2 from ronan22/master
[apps/agl-service-unicens.git] / ucs2-interface / ucs-xml / UcsXml.c
1 /*
2  * Unicens XML Parser
3  *
4  * Copyright (C) 2017 Microchip Technology Germany II GmbH & Co. KG
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * You may also obtain this software under a propriety license from Microchip.
20  * Please contact Microchip for further information.
21  *
22  */
23 #include <assert.h>
24 #include <string.h>
25 #include "mxml.h"
26 #include "UcsXml.h"
27
28 /************************************************************************/
29 /* USER ADJUSTABLE CONSTANTS                                            */
30 /************************************************************************/
31
32 #define MAX_JOB_LIST_LEN 6
33
34 /************************************************************************/
35 /* PRIVATE DECLARATIONS                                                 */
36 /************************************************************************/
37
38 #define COMPILETIME_CHECK(cond)  (void)sizeof(int[!!(cond) - 1])
39
40 struct UcsXmlObjectList
41 {
42     void *obj;
43     struct UcsXmlObjectList *next;
44 };
45
46 struct UcsXmlRouteInfo
47 {
48     bool isSource;
49     char routeName[32];
50     Ucs_Rm_EndPoint_t *ep;
51     struct UcsXmlRouteInfo *next;
52 };
53
54 struct UcsXmlScriptInfo
55 {
56     char scriptName[32];
57     Ucs_Rm_Node_t *node;
58     struct UcsXmlScriptInfo *next;
59 };
60
61 typedef enum
62 {
63     SYNC_DATA        = 0,      /*!< \brief  Specifies the synchronous streaming data type */
64     CONTROL_DATA     = 2,      /*!< \brief  Specifies the control data type */
65     AV_PACKETIZED    = 3,      /*!< \brief  Specifies the A/V Packetized Isochronous 
66                                             streaming data type */
67     QOS_IP           = 4,      /*!< \brief  Specifies the Quality of Service IP 
68                                             streaming data type*/
69     DISC_FRAME_PHASE = 5,      /*!< \brief  Specifies the DiscreteFrame Isochronous
70                                             streaming phase data type */
71     IPC_PACKET       = 7,       /*!< \brief Specifies the IPC packet data type */
72     INVALID          = 0xFF     /*!< \brief Defined invalid value */
73 } MData_t;
74
75 typedef enum
76 {
77     MPORT_MOST,
78     MPORT_USB,
79     MPORT_MLB,
80     MPORT_I2S,
81     MPORT_INVALID = 0xFF
82 } MPort_t;
83
84 typedef enum
85 {
86     Parse_Success = 10,
87     Parse_MemoryError,
88     Parse_XmlError
89 } ParseResult_t;
90
91 typedef struct {
92     struct UcsXmlObjectList objList;
93     struct UcsXmlRouteInfo *pRtLst;
94     struct UcsXmlScriptInfo *pScrLst;
95     Ucs_Rm_Node_t *nod;
96     Ucs_Xrm_ResObject_t *inSocket;
97     Ucs_Xrm_ResObject_t *outSocket;
98     Ucs_Xrm_ResObject_t **jobList;
99     MData_t dataType;
100     uint16_t blockWidth;
101     const char* chName;
102     uint16_t pause;
103 } PrivateData_t;
104
105 /************************************************************************/
106 /* Constants                                                            */
107 /************************************************************************/
108
109 //Key section
110 static const char* UNICENS =                "unicens";
111 static const char* ASYNC_BANDWIDTH =        "async_bandwidth";
112 static const char* CHANNEL =                "channel";
113 static const char* CHANNEL_NAME =           "channel_name";
114 static const char* ADDRESS =                "channel_addr";
115 static const char* BANDWIDTH =              "bandwidth";
116 static const char* OFFSET =                 "offset";
117 static const char* DATA_TYPE =              "data_type";
118 static const char* DEVICE =                 "device";
119 static const char* DEVICE_MLB_SPEED =       "mlb_port_speed";
120 static const char* NODE_ADDR =              "node_address";
121 static const char* DIR =                    "dir";
122 static const char* I2S_PIN =                "i2s_pin";
123 static const char* PACKETS_XACT =           "packets_per_xact";
124 static const char* PORT =                   "port";
125 static const char* SOCKET =                 "socket";
126
127 static const char* I2S_FS_SPEED =           "i2s_fs_speed";
128 static const char* I2S_ALIGN =              "i2s_align";
129
130 //value section
131 static const char* PORT_MOST =              "MOST";
132 static const char* PORT_USB =               "USB";
133 static const char* PORT_MLB =               "MLB";
134 static const char* PORT_I2S =               "I2S";
135
136 static const char* DATATYPE_SYNC =          "SYNC";
137 static const char* DATATYPE_AVP =           "AVP";
138 static const char* DATATYPE_CTRL =          "CTRL";
139 static const char* DATATYPE_QOS =           "QOS";
140 static const char* DATATYPE_DFP =           "DFP";
141 static const char* DATATYPE_IPC =           "IPC";
142
143 static const char* DIR_IN =                 "IN";
144 static const char* DIR_OUT =                "OUT";
145
146 static const char* I2S_PIN_SRXA0 =          "SRXA0";
147 static const char* I2S_PIN_SRXA1 =          "SRXA1";
148 static const char* I2S_PIN_SRXB0 =          "SRXB0";
149 static const char* I2S_PIN_SRXB1 =          "SRXB1";
150
151 static const char* I2S_ALIGN_L16 =          "Left16";
152 static const char* I2S_ALIGN_L24 =          "Left24";
153 static const char* I2S_ALIGN_R16 =          "Right16";
154 static const char* I2S_ALIGN_R24 =          "Right24";
155 static const char* I2S_ALIGN_SEQUENTIAL =   "Seq";
156
157 static const char* SCRIPT =                 "script";
158 static const char* ACTION =                 "action";
159 static const char* NAME =                   "name";
160 static const char* TYPE =                   "type";
161 static const char* FBLOCK_ID =              "fblock_id";
162 static const char* FUNCTION_ID =            "function_id";
163 static const char* OP_TYPE_REQUEST =        "op_request";
164 static const char* OP_TYPE_RESPONSE =       "op_response";
165 static const char* PAYLOAD_REQ_HEX =        "load_req_hex";
166 static const char* PAYLOAD_RES_HEX =        "load_res_hex";
167 static const char* PAUSE_MS =               "pause_ms";
168
169 static const char* SEND_MSG =               "SEND_MSG";
170 static const char* PAUSE =                  "PAUSE";
171
172 /************************************************************************/
173 /* Private Function Prototypes                                          */
174 /************************************************************************/
175
176 static void *MCalloc(struct UcsXmlObjectList *list, uint32_t nElem, uint32_t elemSize);
177 static void FreeObjList(struct UcsXmlObjectList *cur);
178 static void FreeVal(UcsXmlVal_t *v);
179 static bool GetElement(mxml_node_t *element, const char *name, bool goDeep, mxml_node_t **out, bool mandatory);
180 static bool GetCount(mxml_node_t *element, const char *name, uint32_t *out, bool mandatory);
181 static bool GetString(mxml_node_t *element, const char *key, const char **out, bool mandatory);
182 static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory);
183 static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory);
184 static bool GetMlbSpeed(mxml_node_t *element, const char *key, Ucs_Mlb_ClockConfig_t *clock, bool mandatory);
185 static bool GetI2SSpeed(mxml_node_t *element, const char *key, Ucs_Stream_PortClockConfig_t *clock, bool mandatory);
186 static bool GetI2SPin(mxml_node_t *element, Ucs_Stream_PortPinId_t *pin, uint8_t *portIndex, bool mandatory);
187 static bool GetI2SAlignment(mxml_node_t *element, Ucs_Stream_PortDataAlign_t *align, bool mandatory);
188 static bool GetDirection(mxml_node_t *element, Ucs_SocketDirection_t *out);
189 static bool GetDataType(mxml_node_t *element, MData_t *out);
190 static bool GetPort(mxml_node_t *element, MPort_t *out);
191 static bool GetPayload(mxml_node_t *element, const char *name, uint8_t **pPayload, uint8_t *len, 
192             struct UcsXmlObjectList *obj, bool mandatory);
193 static bool AddJob(Ucs_Xrm_ResObject_t **joblist, Ucs_Xrm_ResObject_t *job);
194 static void AddRoute(struct UcsXmlRouteInfo **pRtLst, struct UcsXmlRouteInfo *route);
195 static void AddScript(struct UcsXmlScriptInfo **pScrLst, struct UcsXmlScriptInfo *script);
196 static ParseResult_t ParseAll(mxml_node_t *tree, UcsXmlVal_t *v, PrivateData_t *vp);
197 static ParseResult_t ParseDevice(mxml_node_t * dev, PrivateData_t *vp);
198 static ParseResult_t ParseChannel(mxml_node_t * ch, PrivateData_t *vp);
199 static ParseResult_t ParseSocket(mxml_node_t *soc, PrivateData_t *vp);
200 static ParseResult_t ParseMostSoc(Ucs_Xrm_MostSocket_t *mostSoc, mxml_node_t *soc, PrivateData_t *vp);
201 static ParseResult_t ParseUsbSoc(Ucs_Xrm_UsbSocket_t *usbSoc, mxml_node_t *soc, PrivateData_t *vp);
202 static ParseResult_t ParseMlbSoc(Ucs_Xrm_MlbSocket_t *mlbSoc, mxml_node_t *soc, PrivateData_t *vp);
203 static ParseResult_t ParseStreamSoc(Ucs_Xrm_StrmSocket_t *strmSoc, mxml_node_t *soc, PrivateData_t *vp);
204 static ParseResult_t ParseScript(mxml_node_t *scr, PrivateData_t *vp);
205 static ParseResult_t ParseScriptAction(mxml_node_t *act, Ucs_Rm_Node_t *n, uint32_t index, PrivateData_t *vp);
206 static ParseResult_t ParseRoutes(UcsXmlVal_t *v, PrivateData_t *vp);
207
208 /************************************************************************/
209 /* Public Functions                                                     */
210 /************************************************************************/
211
212 UcsXmlVal_t *UcsXml_Parse(const char *xmlString)
213 {
214     UcsXmlVal_t *v = NULL;
215     ParseResult_t result = Parse_Success;
216     mxml_node_t *tree = mxmlLoadString(NULL, xmlString, MXML_NO_CALLBACK);
217     if (!tree)
218     {
219         result = Parse_XmlError;
220     }
221     if (Parse_Success == result)
222     {
223         if (!GetElement(tree, UNICENS, true, &tree, true))
224             result = Parse_XmlError;
225     }
226     if (Parse_Success == result)
227     {
228         //Do not use MCalloc for the root element
229         v = calloc(1, sizeof(UcsXmlVal_t));
230         if (NULL == v) result = Parse_MemoryError;
231     }
232     if (Parse_Success == result)
233     {
234         //Do not use MCalloc for the private data
235         v->pInternal = calloc(1, sizeof(PrivateData_t));
236         if (NULL == v->pInternal) result = Parse_MemoryError;
237     }
238     if (Parse_Success == result)
239     {
240         result = ParseAll(tree, v, v->pInternal);
241     }
242     if (!tree)
243     {
244         mxmlDelete(tree);
245     }
246     if (Parse_Success == result)
247     {
248         return v;
249     }
250     if (Parse_MemoryError == result)
251     {
252         UcsXml_CB_OnError("XML error, aborting..", 0);
253     }
254     else
255     {
256         UcsXml_CB_OnError("Alloc error, aborting..", 0);
257     }
258     assert(false);
259     FreeVal(v);
260     return NULL;
261 }
262
263 void UcsXml_FreeVal(UcsXmlVal_t *val)
264 {
265     FreeVal(val);
266 }
267
268 /************************************************************************/
269 /* Private Function Implementations                                     */
270 /************************************************************************/
271
272 static void *MCalloc(struct UcsXmlObjectList *list, uint32_t nElem, uint32_t elemSize)
273 {
274     void *obj;
275     struct UcsXmlObjectList *tail = list;
276     if (NULL == list || 0 == nElem || 0 == elemSize) return NULL;
277     
278     obj = calloc(nElem, elemSize);
279     if (NULL == obj)
280     {
281         assert(false);
282         return NULL;
283     }
284     if (NULL == list->obj)
285     {
286         list->obj = obj;
287         return obj;
288     }
289     while(tail->next) tail = tail->next;
290     tail->next = calloc(1, sizeof(struct UcsXmlObjectList));
291     if (NULL == tail->next)
292     {
293         assert(false);
294         free(obj);
295         return NULL;
296     }
297     tail->next->obj = obj;
298     return obj;
299 }
300
301 static void FreeObjList(struct UcsXmlObjectList *cur)
302 {
303     struct UcsXmlObjectList *root = cur;
304     while(cur)
305     {
306         struct UcsXmlObjectList *next = cur->next;
307         assert(NULL != cur->obj);
308         if (cur->obj)
309             free(cur->obj);
310         if (cur != root)
311             free(cur);
312         cur = next;
313     }
314 }
315
316 static void FreeVal(UcsXmlVal_t *v)
317 {
318     PrivateData_t *vp;
319     if (NULL == v || NULL == v->pInternal)
320         return;
321     vp = v->pInternal;
322     FreeObjList(&vp->objList);
323     free(v->pInternal);
324     free(v);
325 }
326
327 static bool GetElement(mxml_node_t *element, const char *name, bool goDeep, mxml_node_t **out, bool mandatory)
328 {
329     mxml_node_t *n = element;
330     if (NULL == n || NULL == name || NULL == out) return false;
331     if (goDeep)
332     {
333         *out = mxmlFindElement(n, n, name, NULL, NULL, MXML_DESCEND);
334         return (NULL != *out);
335     }
336     while ((n = n->next))
337     {
338         if (MXML_ELEMENT != n->type)
339             continue;
340         if (0 == strcmp(name, n->value.opaque))
341         {
342             *out = n;
343             return true;
344         }
345     }
346     if (mandatory)
347         UcsXml_CB_OnError("Can not find tag <%s>", 1, name);
348     return false;
349 }
350
351 static bool GetCount(mxml_node_t *element, const char *name, uint32_t *out, bool mandatory)
352 {
353     uint32_t cnt = 0;
354     mxml_node_t *n;
355     if (NULL == element || NULL == name) return false;
356     if(!GetElement(element, name, true, &n, false))
357         return false;
358     while(NULL != n)
359     {
360         ++cnt;
361         if(!GetElement(n, name, false, &n, false))
362             break;
363     }
364     if (mandatory && 0 == cnt)
365     {
366         UcsXml_CB_OnError("element count of <%s> is zero", 1, name);
367         return false;
368     }
369     *out = cnt;
370     return true;
371 }
372
373 static bool GetString(mxml_node_t *element, const char *key, const char **out, bool mandatory)
374 {
375     uint32_t i;
376     if (NULL == element || NULL == key) return false;
377     for (i = 0; i < element->value.element.num_attrs; i++)
378     {
379         mxml_attr_t *attr = &element->value.element.attrs[i];
380         if (0 == strcmp(key, attr->name))
381         {
382             *out = attr->value;
383             return true;
384         }
385     }
386     if (mandatory)
387         UcsXml_CB_OnError("Can not find attribute='%s' from element <%s>", 
388             2, key, element->value.element.name);
389     return false;
390 }
391
392 static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory)
393 {
394     const char* txt;
395     if (!GetString(element, key, &txt, mandatory)) return false;
396     *out = strtol( txt, NULL, 0 );
397     return true;
398 }
399
400 static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory)
401 {
402     const char* txt;
403     if (!GetString(element, key, &txt, mandatory)) return false;
404     *out = strtol( txt, NULL, 0 );
405     return true;
406 }
407
408 static bool GetMlbSpeed(mxml_node_t *element, const char *key, Ucs_Mlb_ClockConfig_t *clock, bool mandatory)
409 {
410     uint16_t speed;
411     if (!GetUInt16(element, DEVICE_MLB_SPEED, &speed, false))
412         return false;
413     switch(speed)
414     {
415     case 256: *clock = UCS_MLB_CLK_CFG_256_FS; break;
416     case 512: *clock = UCS_MLB_CLK_CFG_512_FS; break;
417     case 1024: *clock = UCS_MLB_CLK_CFG_1024_FS; break;
418     case 2048: *clock = UCS_MLB_CLK_CFG_2048_FS; break;
419     case 3072: *clock = UCS_MLB_CLK_CFG_3072_FS; break;
420     case 4096: *clock = UCS_MLB_CLK_CFG_4096_FS; break;
421     case 6144: *clock = UCS_MLB_CLK_CFG_6144_FS; break;
422     case 8192: *clock = UCS_MLB_CLK_CFG_8192_FS; break;
423     case 0: *clock = UCS_MLB_CLK_CFG_WILDCARD; break;
424     default: 
425         UcsXml_CB_OnError("Invalid MLB clock val:'%d'", 1, clock);
426         return false;
427     }
428     return true;
429 }
430
431 static bool GetI2SSpeed(mxml_node_t *element, const char *key, Ucs_Stream_PortClockConfig_t *clock, bool mandatory)
432 {
433     uint16_t speed;
434     if (!GetUInt16(element, I2S_FS_SPEED, &speed, false))
435         return false;
436     switch(speed)
437     {
438     case 8: *clock = UCS_STREAM_PORT_CLK_CFG_8FS; break;
439     case 16: *clock = UCS_STREAM_PORT_CLK_CFG_16FS; break;
440     case 32: *clock = UCS_STREAM_PORT_CLK_CFG_32FS; break;
441     case 64: *clock = UCS_STREAM_PORT_CLK_CFG_64FS; break;
442     case 128: *clock = UCS_STREAM_PORT_CLK_CFG_128FS; break;
443     case 256: *clock = UCS_STREAM_PORT_CLK_CFG_256FS; break;
444     case 512: *clock = UCS_STREAM_PORT_CLK_CFG_512FS; break;
445     case 0: *clock = UCS_MLB_CLK_CFG_WILDCARD; break;
446     default: 
447         UcsXml_CB_OnError("Invalid I2S clock val:'%d'", 1, clock);
448         return false;
449     }
450     return true;
451 }
452
453 static bool GetI2SPin(mxml_node_t *element, Ucs_Stream_PortPinId_t *pin, uint8_t *portIndex, bool mandatory)
454 {
455     const char *txt;
456     if (!GetString(element, I2S_PIN, &txt, true))
457         return false;
458     if (0 == strcmp(I2S_PIN_SRXA0, txt))
459     {
460         *pin = UCS_STREAM_PORT_PIN_ID_SRXA0;
461         *portIndex = 0;
462         return true;
463     }
464     else if (0 == strcmp(I2S_PIN_SRXA1, txt))
465     {
466         *pin = UCS_STREAM_PORT_PIN_ID_SRXA1;
467         *portIndex = 0;
468         return true;
469     }
470     else if (0 == strcmp(I2S_PIN_SRXB0, txt))
471     {
472         *pin = UCS_STREAM_PORT_PIN_ID_SRXB0;
473         *portIndex = 1;
474         return true;
475     }
476     else if (0 == strcmp(I2S_PIN_SRXB1, txt))
477     {
478         *pin = UCS_STREAM_PORT_PIN_ID_SRXB1;
479         *portIndex = 1;
480         return true;
481     }
482     UcsXml_CB_OnError("Invalid I2S pin val:'%s'", 1, txt);
483     return false;
484 }
485
486 static bool GetI2SAlignment(mxml_node_t *element, Ucs_Stream_PortDataAlign_t *align, bool mandatory)
487 {
488     const char *txt;
489     if (!GetString(element, I2S_ALIGN, &txt, true))
490         return false;
491     if (0 == strcmp(I2S_ALIGN_L16, txt))
492         *align = UCS_STREAM_PORT_ALGN_LEFT16BIT;
493     else if (0 == strcmp(I2S_ALIGN_L24, txt))
494         *align = UCS_STREAM_PORT_ALGN_LEFT24BIT;
495     else if (0 == strcmp(I2S_ALIGN_R16, txt))
496         *align = UCS_STREAM_PORT_ALGN_RIGHT16BIT;
497     else if (0 == strcmp(I2S_ALIGN_R24, txt))
498         *align = UCS_STREAM_PORT_ALGN_RIGHT24BIT;
499     else if (0 == strcmp(I2S_ALIGN_SEQUENTIAL, txt))
500         *align = UCS_STREAM_PORT_ALGN_SEQ;
501     else 
502     {
503         UcsXml_CB_OnError("Invalid I2S alignment:'%s'", 1, txt);
504         return false;
505     }
506     return true;
507 }
508
509 static bool GetDirection(mxml_node_t *element, Ucs_SocketDirection_t *out)
510 {
511     const char *txt;
512     if (!GetString(element, DIR, &txt, true)) return false;
513     if (0 == strcmp(DIR_IN, txt))
514         *out = UCS_SOCKET_DIR_INPUT;
515     else if (0 == strcmp(DIR_OUT, txt))
516         *out = UCS_SOCKET_DIR_OUTPUT;
517     else 
518         return false;
519     return true;
520 }
521
522 static bool GetDataType(mxml_node_t *element, MData_t *out)
523 {
524     const char *txt;
525     if (!GetString(element, DATA_TYPE, &txt, true)) return false;
526     if (0 == strcmp(DATATYPE_SYNC, txt)) {
527         *out = SYNC_DATA;
528     } else if (0 == strcmp(DATATYPE_CTRL, txt)) {
529         *out = CONTROL_DATA;
530     } else if (0 == strcmp(DATATYPE_AVP, txt)) {
531         *out = AV_PACKETIZED;
532     } else if (0 == strcmp(DATATYPE_QOS, txt)) {
533         *out = QOS_IP;
534     } else if (0 == strcmp(DATATYPE_DFP, txt)) {
535         *out = DISC_FRAME_PHASE;
536     } else if (0 == strcmp(DATATYPE_IPC, txt)) {
537         *out = IPC_PACKET;
538     } else {
539         UcsXml_CB_OnError("Unknown data type : '%s'", 1, txt);
540         return false;
541     }
542     return true;
543 }
544
545 static bool GetPort(mxml_node_t *element, MPort_t *out)
546 {
547     const char *txt;
548     if (!GetString(element, PORT, &txt, true)) return false;
549     if (0 == strcmp(txt, PORT_MOST)) {
550             *out = MPORT_MOST;
551     } else if (0 == strcmp(txt, PORT_USB)) {
552         *out = MPORT_USB;
553     } else if (0 == strcmp(txt, PORT_MLB)) {
554         *out = MPORT_MLB;
555     } else if (0 == strcmp(txt, PORT_I2S)) {
556         *out = MPORT_I2S;
557     } else {
558         UcsXml_CB_OnError("Unknown port : '%s'", 1, txt);
559         return false;
560     }
561     return true;
562 }
563
564 static bool GetPayload(mxml_node_t *element, const char *name, uint8_t **pPayload, uint8_t *outLen, struct UcsXmlObjectList *obj, bool mandatory)
565 {
566     uint32_t tempLen, len = 0;
567     uint8_t *p;
568     const char *txt;
569     char *txtCopy;
570     char *tkPtr;
571     char *token;
572     if (!GetString(element, name, &txt, mandatory))
573         return false;
574     tempLen = strlen(txt) + 1;
575     txtCopy = malloc(tempLen);
576     if (NULL == txtCopy) 
577         return false;
578     strncpy(txtCopy, txt, tempLen);
579     tempLen = tempLen / 3; /* 2 chars hex value plus space (AA )  */
580     p = MCalloc(obj, tempLen, 1);
581     if (NULL == p)
582     {
583         free(txtCopy);
584         return false;
585     }
586     *pPayload = p;
587     token = strtok_r( txtCopy, " ,.-", &tkPtr );
588     while( NULL != token )
589     {
590         if( len >= tempLen )
591         {
592             UcsXml_CB_OnError("Script payload values must be stuffed to two characters", 0);
593             free(txtCopy);
594             assert(false);
595             return 0;
596         }
597         p[len++] = strtol( token, NULL, 16 );
598         token = strtok_r( NULL, " ,.-", &tkPtr );
599     }
600     *outLen = len;
601     return true;
602 }
603
604 static bool AddJob(Ucs_Xrm_ResObject_t **joblist, Ucs_Xrm_ResObject_t *job)
605 {
606     uint32_t i;
607     if (NULL == joblist || NULL == job)
608     {
609         assert(false);
610         return false;
611     }
612     for (i = 0; i < MAX_JOB_LIST_LEN; i++)
613     {
614         if (NULL == joblist[i]) 
615         {
616             joblist[i] = job;
617             return true;
618         }
619     }
620     assert(false);
621     return false;
622 }
623
624 static void AddRoute(struct UcsXmlRouteInfo **pRtLst, struct UcsXmlRouteInfo *route)
625 {
626     struct UcsXmlRouteInfo *tail;
627     if (NULL == pRtLst || NULL == route) return;
628     if (NULL == pRtLst[0])
629     {
630         pRtLst[0] = route;
631         return;
632     }
633     tail = pRtLst[0];
634     while(tail->next) tail = tail->next;
635     tail->next = route;
636 }
637
638 static void AddScript(struct UcsXmlScriptInfo **pScrLst, struct UcsXmlScriptInfo *script)
639 {
640     struct UcsXmlScriptInfo *tail;
641     if (NULL == pScrLst || NULL == script) return;
642     if (NULL == pScrLst[0])
643     {
644         pScrLst[0] = script;
645         return;
646     }
647     tail = pScrLst[0];
648     while(tail->next) tail = tail->next;
649     tail->next = script;
650 }
651
652 static ParseResult_t ParseAll(mxml_node_t *tree, UcsXmlVal_t *v, PrivateData_t *vp)
653 {
654     uint32_t devCount;
655     mxml_node_t *sub;
656     ParseResult_t result;
657     if (!GetCount(tree, DEVICE, &devCount, true))
658         return Parse_XmlError;
659     
660     v->pNod = MCalloc(&vp->objList, devCount, sizeof(Ucs_Rm_Node_t));
661     if (NULL == v->pNod) return Parse_MemoryError;
662
663     if (!GetUInt16(tree, ASYNC_BANDWIDTH, &v->packetBw, true))
664         return Parse_XmlError;
665
666     ///Iterate all devices
667     if (!GetElement(tree, DEVICE, true, &sub, true))
668         return Parse_XmlError;
669     while(sub)
670     {
671         mxml_node_t *ch;
672         vp->nod = &v->pNod[v->nodSize];
673         if (Parse_Success != (result = ParseDevice(sub, vp)))
674             return result;
675         ///Iterate all channels. Device without any channel is also valid.
676         if (GetElement(sub->child, CHANNEL, false, &ch, false))
677         {
678             while(ch)
679             {
680                 mxml_node_t *soc;
681                 uint8_t sockCnt = 0;
682                 if (Parse_Success != (result = ParseChannel(ch, vp)))
683                     return result;
684                 ///Iterate all sockets
685                 if(!GetElement(ch->child, SOCKET, false, &soc, true))
686                     return Parse_XmlError;
687                 while(soc)
688                 {
689                     ParseResult_t result;
690                     if (Parse_Success != (result = ParseSocket(soc, vp)))
691                         return result;
692                     ++sockCnt;
693                     if (!GetElement(soc, SOCKET, false, &soc, false))
694                         break;
695                 }
696                 if (2 != sockCnt)
697                 {
698                     UcsXml_CB_OnError("%d sockets per channel found, must be 2", 1, sockCnt);
699                     return Parse_XmlError;
700                 }
701                 if (!GetElement(ch, CHANNEL, false, &ch, false))
702                     break;
703             }
704         }
705         ++v->nodSize;
706         if (!GetElement(sub, DEVICE, false, &sub, false))
707             break;
708     }
709
710     ///Fill route structures
711     result = ParseRoutes(v, vp);
712     if (Parse_MemoryError == result) return Parse_MemoryError;
713     else if (Parse_XmlError == result) return Parse_XmlError;
714     
715     ///Iterate all scripts. No scripts at all is allowed
716     if(GetElement(tree, SCRIPT, true, &sub, false))
717     {
718         while(sub)
719         {
720             ParseResult_t result = ParseScript(sub, vp);
721             if (Parse_MemoryError == result) return Parse_MemoryError;
722             else if (Parse_XmlError == result) return Parse_XmlError;
723             if(!GetElement(sub, SCRIPT, false, &sub, false))
724                 break;
725         }
726     }
727     return result;
728 }
729
730 static ParseResult_t ParseDevice(mxml_node_t * dev, PrivateData_t *vp)
731 {
732     const char *txt;
733     assert(NULL != dev && NULL != vp);
734     vp->nod->signature_ptr = MCalloc(&vp->objList, 1, sizeof(Ucs_Signature_t));
735     if(NULL == vp->nod->signature_ptr) return Parse_MemoryError;
736     if (!GetUInt16(dev, NODE_ADDR, &vp->nod->signature_ptr->node_address, true))
737         return Parse_XmlError;
738     if (GetString(dev, SCRIPT, &txt, false))
739     {
740         struct UcsXmlScriptInfo *scr = MCalloc(&vp->objList, 1, sizeof(struct UcsXmlScriptInfo));
741         if (NULL == scr) return Parse_MemoryError;
742         scr->node = vp->nod;
743         strncpy(scr->scriptName, txt, sizeof(scr->scriptName));
744         AddScript(&vp->pScrLst, scr);
745     }
746     return Parse_Success;;
747 }
748
749 static ParseResult_t ParseChannel(mxml_node_t *ch, PrivateData_t *vp)
750 {
751     vp->inSocket = NULL;
752     vp->outSocket = NULL;
753     vp->jobList = NULL;
754     vp->dataType = 0xFF;
755     vp->blockWidth = 0;
756     vp->chName = NULL;
757     assert(NULL != ch && NULL != vp);
758     if (!GetString(ch, CHANNEL_NAME, &vp->chName, true))
759         return Parse_XmlError;
760     if (!GetDataType(ch, &vp->dataType))
761         return Parse_XmlError;
762     if (!GetUInt16(ch, BANDWIDTH, &vp->blockWidth, true))
763         return Parse_XmlError;
764     vp->jobList = MCalloc(&vp->objList, MAX_JOB_LIST_LEN, sizeof(Ucs_Xrm_ResObject_t *));
765     if (NULL == vp->jobList) return Parse_MemoryError;
766     return Parse_Success;
767 }
768
769 static ParseResult_t ParseSocket(mxml_node_t *soc, PrivateData_t *vp)
770 {
771     MPort_t port;
772     bool isIn = false;
773     bool isSource = false;
774     uint16_t offset = 0;
775     assert(NULL != soc && NULL != vp);
776     Ucs_SocketDirection_t direction;
777     if (!GetDirection(soc, &direction))
778         return Parse_XmlError;
779     isIn = (UCS_SOCKET_DIR_INPUT == direction);
780     if (!GetPort(soc, &port))
781         return Parse_XmlError;
782     switch(port)
783     {
784         case MPORT_MOST:
785         {
786             Ucs_Xrm_MostSocket_t *sock = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_MostSocket_t));
787             if (NULL == sock) return Parse_MemoryError;
788             if (!AddJob(vp->jobList, sock)) return Parse_XmlError;
789             sock->data_type = vp->dataType;
790             sock->bandwidth = vp->blockWidth;
791             if (Parse_Success != ParseMostSoc(sock, soc, vp))
792                 return Parse_XmlError;
793             isSource = (UCS_SOCKET_DIR_OUTPUT == direction);
794             if (isIn) vp->inSocket = sock; else vp->outSocket = sock;
795             break;
796         }
797         case MPORT_USB:
798         {
799             Ucs_Xrm_UsbSocket_t *sock = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_UsbSocket_t));
800             if (NULL == sock) return Parse_MemoryError;
801             if (!AddJob(vp->jobList, sock)) return Parse_XmlError;
802             sock->data_type = vp->dataType;
803             if (Parse_Success != ParseUsbSoc(sock, soc, vp))
804                 return Parse_XmlError;
805             if (isIn) vp->inSocket = sock; else vp->outSocket = sock;
806             break;
807         }
808         case MPORT_MLB:
809         {
810             Ucs_Xrm_MlbSocket_t *sock = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_MlbSocket_t));
811             if (NULL == sock) return Parse_MemoryError;
812             if (!AddJob(vp->jobList, sock)) return Parse_XmlError;
813             sock->data_type = vp->dataType;
814             sock->bandwidth = vp->blockWidth;
815             if (Parse_Success != ParseMlbSoc(sock, soc, vp))
816                 return Parse_XmlError;
817             if (isIn) vp->inSocket = sock; else vp->outSocket = sock;
818             break;
819         }
820         case MPORT_I2S:
821         {
822             Ucs_Xrm_StrmSocket_t *sock = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_StrmSocket_t));
823             if (NULL == sock) return Parse_MemoryError;
824             sock->data_type = vp->dataType;
825             sock->bandwidth = vp->blockWidth;
826             if (Parse_Success != ParseStreamSoc(sock, soc, vp))
827                 return Parse_XmlError;
828             if (isIn) vp->inSocket = sock; else vp->outSocket = sock;
829             break;
830         }
831         default:
832             assert(false);
833             return Parse_XmlError;
834     }
835     if (GetUInt16(soc, OFFSET, &offset, false))
836     {
837         //TODO: If offset is non zero allocate Splitter / Combiner
838     }
839     //Connect in and out socket once they are created
840     if (vp->inSocket && vp->outSocket)
841     {
842         switch(vp->dataType)
843         {
844         case AV_PACKETIZED:
845             {
846                 Ucs_Xrm_AvpCon_t *con = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_AvpCon_t));
847                 if (NULL == con) return Parse_MemoryError;
848                 if (!AddJob(vp->jobList, con))
849                     return Parse_XmlError;
850                 con->resource_type = UCS_XRM_RC_TYPE_AVP_CON;
851                 con->socket_in_obj_ptr = vp->inSocket;
852                 con->socket_out_obj_ptr = vp->outSocket;
853                 con->isoc_packet_size = UCS_ISOC_PCKT_SIZE_188; //TODO:Read from XML
854                 break;
855             }
856         case SYNC_DATA:
857             {
858                 Ucs_Xrm_SyncCon_t *con = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_SyncCon_t));
859                 if (NULL == con) return Parse_MemoryError;
860                 if (!AddJob(vp->jobList, con))
861                     return Parse_XmlError;
862                 con->resource_type = UCS_XRM_RC_TYPE_SYNC_CON;
863                 con->socket_in_obj_ptr = vp->inSocket;
864                 con->socket_out_obj_ptr = vp->outSocket;
865                 con->mute_mode = UCS_SYNC_MUTE_MODE_NO_MUTING; //TODO:Read from XML
866                 con->offset = offset;
867                 break;
868             }
869         default:
870             UcsXml_CB_OnError("Could not connect sockets, data type not implemented: %d", 1, vp->dataType);
871             return Parse_XmlError;
872             break;
873         }
874         Ucs_Rm_EndPoint_t *ep = MCalloc(&vp->objList, 1, sizeof(Ucs_Rm_EndPoint_t));
875         if (NULL == ep) return Parse_MemoryError;
876         ep->endpoint_type = isSource ? UCS_RM_EP_SOURCE : UCS_RM_EP_SINK;
877         ep->jobs_list_ptr = vp->jobList;
878         ep->node_obj_ptr = vp->nod;
879
880         struct UcsXmlRouteInfo *route = MCalloc(&vp->objList, 1, sizeof(struct UcsXmlRouteInfo));
881         if (NULL == route) return Parse_MemoryError;
882         route->isSource = isSource;
883         route->ep = ep;
884         strncpy(route->routeName, vp->chName, sizeof(route->routeName));
885         AddRoute(&vp->pRtLst, route);
886     }
887     return Parse_Success;
888 }
889
890 static ParseResult_t ParseMostSoc(Ucs_Xrm_MostSocket_t *mostSoc, mxml_node_t *soc, PrivateData_t *vp)
891 {
892     assert(NULL != mostSoc && NULL != soc && NULL != vp);
893     COMPILETIME_CHECK(SYNC_DATA == (MData_t)UCS_MOST_SCKT_SYNC_DATA);
894     COMPILETIME_CHECK(AV_PACKETIZED == (MData_t)UCS_MOST_SCKT_AV_PACKETIZED);
895     COMPILETIME_CHECK(QOS_IP == (MData_t)UCS_MOST_SCKT_QOS_IP);
896     COMPILETIME_CHECK(DISC_FRAME_PHASE == (MData_t)UCS_MOST_SCKT_DISC_FRAME_PHASE);
897     switch((MData_t)mostSoc->data_type)
898     {
899         case SYNC_DATA:
900         case AV_PACKETIZED:
901         case QOS_IP:
902         case DISC_FRAME_PHASE:
903             break; //Nothing to do, valid values.
904         default:
905             UcsXml_CB_OnError("Invalid DataType=%d for MOST socket", 1, mostSoc->data_type);
906             return Parse_XmlError;
907     }
908     mostSoc->resource_type = UCS_XRM_RC_TYPE_MOST_SOCKET;
909     mostSoc->most_port_handle = 0x0D00;
910     if (!GetDirection(soc, &mostSoc->direction))
911         return Parse_XmlError;
912     return Parse_Success;
913 }
914
915 static ParseResult_t ParseUsbSoc(Ucs_Xrm_UsbSocket_t *usbSoc, mxml_node_t *soc, PrivateData_t *vp)
916 {
917     Ucs_Xrm_DefaultCreatedPort_t *p;
918     assert(NULL != usbSoc && NULL != soc && NULL != vp);
919     COMPILETIME_CHECK(SYNC_DATA == (MData_t)UCS_USB_SCKT_SYNC_DATA);
920     COMPILETIME_CHECK(CONTROL_DATA == (MData_t)UCS_USB_SCKT_CONTROL_DATA);
921     COMPILETIME_CHECK(AV_PACKETIZED == (MData_t)UCS_USB_SCKT_AV_PACKETIZED);
922     switch((MData_t)usbSoc->data_type)
923     {
924         case SYNC_DATA:
925         case CONTROL_DATA:
926         case AV_PACKETIZED:
927             break; //Nothing to do, valid values.
928         default:
929             UcsXml_CB_OnError("Invalid DataType=%d for USB socket", 1, usbSoc->data_type);
930             return Parse_XmlError;
931     }
932     usbSoc->resource_type = UCS_XRM_RC_TYPE_USB_SOCKET;
933     if (!GetDirection(soc, &usbSoc->direction))
934         return Parse_XmlError;
935     if (!GetUInt8(soc, ADDRESS, &usbSoc->end_point_addr, true))
936         return Parse_XmlError;
937
938     if (!GetUInt16(soc, PACKETS_XACT, &usbSoc->frames_per_transfer, true))
939         return Parse_XmlError;
940
941     //XML provides currently no way to open USB port, so use ConfigString default
942     p = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_DefaultCreatedPort_t));
943     if (NULL == p) return Parse_MemoryError;
944     if (!AddJob(vp->jobList, p)) return Parse_MemoryError;
945     p->resource_type = UCS_XRM_RC_TYPE_DC_PORT;
946     p->port_type = UCS_XRM_PORT_TYPE_USB;
947     p->index = 0;
948     usbSoc->usb_port_obj_ptr = p;
949     return Parse_Success;
950 }
951
952 static ParseResult_t ParseMlbSoc(Ucs_Xrm_MlbSocket_t *mlbSoc, mxml_node_t *soc, PrivateData_t *vp)
953 {
954     Ucs_Mlb_ClockConfig_t clock;
955     assert(NULL != mlbSoc && NULL != soc && NULL != vp);
956     COMPILETIME_CHECK(SYNC_DATA == (MData_t)UCS_MLB_SCKT_SYNC_DATA);
957     COMPILETIME_CHECK(CONTROL_DATA == (MData_t)UCS_MLB_SCKT_CONTROL_DATA);
958     COMPILETIME_CHECK(AV_PACKETIZED == (MData_t)UCS_USB_SCKT_AV_PACKETIZED);
959     COMPILETIME_CHECK(QOS_IP == (MData_t)UCS_MLB_SCKT_QOS_IP);
960     COMPILETIME_CHECK(DISC_FRAME_PHASE == (MData_t)UCS_MLB_SCKT_DISC_FRAME_PHASE);
961     COMPILETIME_CHECK(IPC_PACKET == (MData_t)UCS_MLB_SCKT_IPC_PACKET);
962     switch((MData_t)mlbSoc->data_type)
963     {
964         case SYNC_DATA:
965         case CONTROL_DATA:
966         case AV_PACKETIZED:
967         case QOS_IP:
968         case DISC_FRAME_PHASE:
969         case IPC_PACKET:
970             break; //Nothing to do, valid values.
971         default:
972             UcsXml_CB_OnError("Invalid DataType=%d for MLB socket", 1, mlbSoc->data_type);
973             return Parse_XmlError;
974     }
975     mlbSoc->resource_type = UCS_XRM_RC_TYPE_MLB_SOCKET;
976     if (!GetDirection(soc, &mlbSoc->direction))
977         return Parse_XmlError;
978     if (!GetUInt16(soc, ADDRESS, &mlbSoc->channel_address, true))
979          return Parse_XmlError;
980
981     //Create MLB port when DEVICE_MLB_SPEED is defined, otherwise use ConfigString default
982     if (GetMlbSpeed(soc, DEVICE_MLB_SPEED, &clock, false))
983     {
984         Ucs_Xrm_MlbPort_t *p = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_MlbPort_t));
985         if (NULL == p) return Parse_MemoryError;
986         if (!AddJob(vp->jobList, p)) return Parse_MemoryError;
987         p->resource_type = UCS_XRM_RC_TYPE_MLB_PORT;
988         p->index = 0;
989         p->clock_config = clock;
990         mlbSoc->mlb_port_obj_ptr = p;
991     } else {
992         Ucs_Xrm_DefaultCreatedPort_t *p = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_DefaultCreatedPort_t));
993         if (NULL == p) return Parse_MemoryError;
994         if (!AddJob(vp->jobList, p)) return Parse_MemoryError;
995         p->resource_type = UCS_XRM_RC_TYPE_DC_PORT;
996         p->port_type = UCS_XRM_PORT_TYPE_MLB;
997         p->index = 0;
998         mlbSoc->mlb_port_obj_ptr = p;
999     }
1000     return Parse_Success;
1001 }
1002
1003 static ParseResult_t ParseStreamSoc(Ucs_Xrm_StrmSocket_t *strmSoc, mxml_node_t *soc, PrivateData_t *vp)
1004 {
1005     const char *txt;
1006     Ucs_Xrm_StrmPort_t *strPort;
1007     assert(NULL != strmSoc && NULL != soc && NULL != vp);
1008     COMPILETIME_CHECK(SYNC_DATA == (MData_t)UCS_STREAM_PORT_SCKT_SYNC_DATA);
1009     if (SYNC_DATA != (MData_t)strmSoc->data_type)
1010     {
1011         UcsXml_CB_OnError("Invalid DataType=%d for I2S socket", 1, strmSoc->data_type);
1012             return Parse_XmlError;
1013     }
1014     strPort = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_StrmPort_t));
1015     if (NULL == strPort) return Parse_MemoryError;
1016     if (!AddJob(vp->jobList, strPort)) return Parse_MemoryError;
1017     if (!AddJob(vp->jobList, strmSoc)) return Parse_MemoryError;
1018     strmSoc->resource_type = UCS_XRM_RC_TYPE_STRM_SOCKET;
1019     strmSoc->stream_port_obj_ptr = strPort;
1020
1021     strPort->resource_type = UCS_XRM_RC_TYPE_STRM_PORT;
1022     if (!GetDirection(soc, &strmSoc->direction))
1023         return Parse_XmlError;
1024     if (!GetI2SPin(soc, &strmSoc->stream_pin_id, &strPort->index, true))
1025         return Parse_XmlError;
1026     if (!GetI2SSpeed(soc, I2S_FS_SPEED, &strPort->clock_config, true))
1027         return Parse_XmlError;
1028     if (!GetString(soc, I2S_ALIGN, &txt, true))
1029         return Parse_XmlError;
1030     if (!GetI2SAlignment(soc, &strPort->data_alignment, true))
1031         return Parse_XmlError;
1032     return Parse_Success;
1033 }
1034
1035 static ParseResult_t ParseScript(mxml_node_t *scr, PrivateData_t *vp)
1036 {
1037     mxml_node_t *act;
1038     uint32_t actCnt;
1039     uint32_t i = 0;
1040     const char *txt;
1041     assert(NULL != scr && NULL != vp);
1042     vp->pause = 0;
1043     if (!GetString(scr, NAME, &txt, true))
1044         return Parse_XmlError;
1045     Ucs_Rm_Node_t *n = NULL;
1046     struct UcsXmlScriptInfo *scrlist = vp->pScrLst;
1047     while(NULL != scrlist)
1048     {
1049         if (0 == strcmp(txt, scrlist->scriptName))
1050         {
1051             n = scrlist->node;
1052             break;
1053         }
1054         scrlist = scrlist->next;
1055     }
1056     if (NULL == n)
1057     {
1058         UcsXml_CB_OnError("Script defined:'%s', which was never referenced", 1, txt);
1059         return Parse_XmlError;
1060     }
1061     if (!GetCount(scr, ACTION, &actCnt, true)) return Parse_XmlError;
1062     if (NULL == (n->script_list_ptr = MCalloc(&vp->objList, actCnt, sizeof(Ucs_Ns_Script_t))))
1063         return Parse_MemoryError;
1064     n->script_list_size = actCnt;
1065     ///Iterate all actions
1066     if (!GetElement(scr, ACTION, true, &act, true)) return false;
1067     while(act)
1068     {
1069         ParseResult_t result = ParseScriptAction(act, n, i, vp);
1070         if (Parse_Success != result) return result;
1071         if (!GetElement(act, ACTION, false, &act, false))
1072             break;
1073         ++i;
1074     }
1075     return Parse_Success;
1076 }
1077
1078 static ParseResult_t ParseScriptAction(mxml_node_t *act, Ucs_Rm_Node_t *n, uint32_t index, PrivateData_t *vp)
1079 {
1080     const char *txt;
1081     uint8_t opResult;
1082     assert(NULL != act && NULL != vp);
1083     Ucs_Ns_Script_t *scr =  &n->script_list_ptr[index];
1084     if (!GetString(act, TYPE, &txt, true))
1085         return Parse_XmlError;
1086     if (0 == strcmp(txt, SEND_MSG))
1087     {
1088         Ucs_Ns_ConfigMsg_t *req;
1089         scr->send_cmd = MCalloc(&vp->objList, 1, sizeof(Ucs_Ns_ConfigMsg_t));
1090         req = scr->send_cmd;
1091         if (NULL == req) return Parse_MemoryError;
1092         scr->pause = vp->pause;
1093         if (vp->pause) vp->pause = 0;
1094         req->InstId = 1;
1095         if (!GetUInt8(act, FBLOCK_ID, &req->FBlockId, true))
1096             return Parse_XmlError;
1097
1098         if (!GetUInt16(act, FUNCTION_ID, &req->FunktId, true))
1099             return Parse_XmlError;
1100
1101         if (!GetUInt8(act, OP_TYPE_REQUEST, &req->OpCode, true))
1102             return Parse_XmlError;
1103
1104         if (GetUInt8(act, OP_TYPE_RESPONSE, &opResult, false))
1105         {
1106             //Waiting for response is optional
1107             Ucs_Ns_ConfigMsg_t *res;
1108             scr->exp_result = MCalloc(&vp->objList, 1, sizeof(Ucs_Ns_ConfigMsg_t));
1109             res = scr->exp_result;
1110             res->FBlockId = req->FBlockId;
1111             res->InstId = req->InstId;
1112             res->FunktId = req->FunktId;
1113             res->OpCode = opResult;
1114             //Not interested in result:
1115             GetPayload(act, PAYLOAD_RES_HEX, &res->DataPtr, &res->DataLen, &vp->objList, false);
1116         }
1117         if (!GetPayload(act, PAYLOAD_REQ_HEX, &req->DataPtr, &req->DataLen, &vp->objList, true))
1118             return Parse_XmlError;
1119         if (0 == req->DataLen || NULL == req->DataPtr)
1120             return Parse_XmlError;
1121     }
1122     else if (0 == strcmp(txt, PAUSE))
1123     {
1124         if (!GetUInt16(act, PAUSE_MS, &vp->pause, true))
1125             return Parse_XmlError;
1126     }
1127     return Parse_Success;
1128 }
1129
1130 static ParseResult_t ParseRoutes(UcsXmlVal_t *v, PrivateData_t *vp)
1131 {
1132     uint16_t routeAmount = 0;
1133     struct UcsXmlRouteInfo *sourceRoute;
1134     assert(NULL != v && NULL != vp);
1135     //First: Count the amount of routes and allocate the correct amount
1136     sourceRoute = vp->pRtLst;
1137     while (NULL != sourceRoute)
1138     {
1139         if (!sourceRoute->isSource) //There can be more sinks than sources, so count them
1140         {
1141             ++routeAmount;
1142         }
1143         sourceRoute = sourceRoute->next;
1144     }
1145     if (0 == routeAmount)
1146         return Parse_Success; //Its okay to have no routes at all (e.g. MEP traffic only)
1147     v->pRoutes = MCalloc(&vp->objList, routeAmount, sizeof(Ucs_Rm_Route_t));
1148     if (NULL == v->pRoutes) return Parse_MemoryError;
1149     
1150     //Second: Fill allocated structure now
1151     sourceRoute = vp->pRtLst;
1152     while (NULL != sourceRoute)
1153     {
1154         if (sourceRoute->isSource)
1155         {
1156             struct UcsXmlRouteInfo *sinkRoute = vp->pRtLst;
1157             while (NULL != sinkRoute)
1158             {
1159                 if (sourceRoute != sinkRoute 
1160                     && !sinkRoute->isSource
1161                     && (0 == strncmp(sourceRoute->routeName, sinkRoute->routeName, sizeof(sourceRoute->routeName))))
1162                 {
1163                     Ucs_Rm_Route_t *route = &v->pRoutes[v->routesSize++];
1164                     route->source_endpoint_ptr = sourceRoute->ep;
1165                     route->sink_endpoint_ptr = sinkRoute->ep;
1166                     route->active = 1;
1167                 }
1168                 sinkRoute = sinkRoute->next;
1169             }
1170         }
1171         sourceRoute = sourceRoute->next;
1172     }
1173     return Parse_Success;
1174 }