96498ef3718552cd43eed59a23909e03fb4f788b
[apps/agl-service-unicens.git] / ucs2-interface / ucs-xml / UcsXml.c
1 /*------------------------------------------------------------------------------------------------*/\r
2 /* Unicens XML Parser                                                                             */\r
3 /* Copyright 2017, Microchip Technology Inc. and its subsidiaries.                                */\r
4 /*                                                                                                */\r
5 /* Redistribution and use in source and binary forms, with or without                             */\r
6 /* modification, are permitted provided that the following conditions are met:                    */\r
7 /*                                                                                                */\r
8 /* 1. Redistributions of source code must retain the above copyright notice, this                 */\r
9 /*    list of conditions and the following disclaimer.                                            */\r
10 /*                                                                                                */\r
11 /* 2. Redistributions in binary form must reproduce the above copyright notice,                   */\r
12 /*    this list of conditions and the following disclaimer in the documentation                   */\r
13 /*    and/or other materials provided with the distribution.                                      */\r
14 /*                                                                                                */\r
15 /* 3. Neither the name of the copyright holder nor the names of its                               */\r
16 /*    contributors may be used to endorse or promote products derived from                        */\r
17 /*    this software without specific prior written permission.                                    */\r
18 /*                                                                                                */\r
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"                    */\r
20 /* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE                      */\r
21 /* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                 */\r
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE                   */\r
23 /* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL                     */\r
24 /* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR                     */\r
25 /* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER                     */\r
26 /* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                  */\r
27 /* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE                  */\r
28 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */\r
29 /*------------------------------------------------------------------------------------------------*/\r
30 #include <assert.h>\r
31 #include <string.h>\r
32 #include "mxml.h"\r
33 #include "UcsXml_Private.h"\r
34 #include "UcsXml.h"\r
35 \r
36 /************************************************************************/\r
37 /* PRIVATE DECLARATIONS                                                 */\r
38 /************************************************************************/\r
39 \r
40 #define COMPILETIME_CHECK(cond)  (void)sizeof(int[2 * !!(cond) - 1])\r
41 #define RETURN_ASSERT(result) { assert(false); return result; }\r
42 #define MISC_HB(value)      ((uint8_t)((uint16_t)(value) >> 8))\r
43 #define MISC_LB(value)      ((uint8_t)((uint16_t)(value) & (uint16_t)0xFF))\r
44 \r
45 struct UcsXmlRoute\r
46 {\r
47     bool isSource;\r
48     bool isActive;\r
49     uint16_t routeId;\r
50     char routeName[32];\r
51     Ucs_Rm_EndPoint_t *ep;\r
52     struct UcsXmlRoute *next;\r
53 };\r
54 \r
55 struct UcsXmlScript\r
56 {\r
57     char scriptName[32];\r
58     Ucs_Rm_Node_t *node;\r
59     struct UcsXmlScript *next;\r
60 };\r
61 \r
62 struct UcsXmlJobList\r
63 {\r
64     Ucs_Xrm_ResObject_t *job;\r
65     struct UcsXmlJobList *next; \r
66 };\r
67 \r
68 typedef enum\r
69 {\r
70     MSocket_MOST = 20,\r
71     MSocket_USB,\r
72     MSocket_MLB,\r
73     MSocket_STRM,\r
74     MSocket_SPLITTER,\r
75     MSocket_COMBINER\r
76 } MSocketType_t;\r
77 \r
78 typedef enum\r
79 {\r
80     Parse_Success = 10,\r
81     Parse_MemoryError,\r
82     Parse_XmlError\r
83 } ParseResult_t;\r
84 \r
85 typedef struct\r
86 {\r
87     Ucs_Rm_Node_t *nod;\r
88     bool usbPortAddedToJobList; /* USB Port must be added only ONCE to connection job lists */\r
89     Ucs_Xrm_UsbPort_t *usbPort;\r
90     bool mlbPortAddedToJobList; /* MLB Port must be added only ONCE to connection job lists */\r
91     Ucs_Xrm_MlbPort_t *mlbPort;\r
92     bool strmPortsAddedToJobList; /* STRM Ports must be added only ONCE to connection job lists */\r
93     Ucs_Xrm_StrmPort_t *strmPortA;\r
94     Ucs_Xrm_StrmPort_t *strmPortB;\r
95 } NodeData_t;\r
96 \r
97 typedef struct\r
98 {\r
99     MDataType_t dataType;\r
100     uint8_t sockCnt;\r
101     bool syncOffsetNeeded;\r
102     bool isDeactivated;\r
103     uint16_t routeId;\r
104     uint16_t syncOffset;\r
105     const char *routeName;\r
106     Ucs_Xrm_ResObject_t *inSocket;\r
107     Ucs_Xrm_ResObject_t *outSocket;\r
108     struct UcsXmlJobList *jobList;\r
109     Ucs_Xrm_Combiner_t *combiner;\r
110     mxml_node_t *pendingCombinerMostSockets;\r
111     Ucs_Sync_MuteMode_t muteMode;\r
112     Ucs_Avp_IsocPacketSize_t isocPacketSize;\r
113 } ConnectionData_t;\r
114 \r
115 typedef struct\r
116 {\r
117     uint16_t pause;\r
118 } ScriptData_t;\r
119 \r
120 typedef struct {\r
121     uint16_t autoRouteId;\r
122     struct UcsXmlObjectList objList;\r
123     struct UcsXmlRoute *pRtLst;\r
124     struct UcsXmlScript *pScrLst;\r
125     NodeData_t nodeData;\r
126     ConnectionData_t conData;\r
127     ScriptData_t scriptData;\r
128 } PrivateData_t;\r
129 \r
130 /************************************************************************/\r
131 /* Constants                                                            */\r
132 /************************************************************************/\r
133 \r
134 /*Key section*/\r
135 static const char* UNICENS =                "Unicens";\r
136 static const char* PACKET_BW =              "AsyncBandwidth";\r
137 static const char* NAME =                   "Name";\r
138 static const char* ROUTE =                  "Route";\r
139 static const char* ROUTE_ID =               "RouteId";\r
140 static const char* ROUTE_IS_ACTIVE =        "IsActive";\r
141 static const char* ENDPOINT_ADDRESS =       "EndpointAddress";\r
142 static const char* CHANNEL_ADDRESS =        "ChannelAddress";\r
143 static const char* BANDWIDTH =              "Bandwidth";\r
144 static const char* BYTES_PER_FRAME =        "BytesPerFrame";\r
145 static const char* OFFSET =                 "Offset";\r
146 static const char* NODE =                   "Node";\r
147 static const char* CLOCK_CONFIG =           "ClockConfig";\r
148 static const char* ADDRESS =                "Address";\r
149 static const char* FRAMES_PER_TRANSACTION = "FramesPerTransaction";\r
150 static const char* MUTE_MODE =              "MuteMode";\r
151 static const char* MUTE_MODE_NO_MUTING =    "NoMuting";\r
152 static const char* MUTE_MODE_MUTE_SIGNAL =  "MuteSignal";\r
153 static const char* AVP_PACKET_SIZE =        "IsocPacketSize";\r
154 #define SYNC_CONNECTION                     "SyncConnection"\r
155 #define AVP_CONNECTION                      "AVPConnection"\r
156 #define DFP_CONNECTION                      "DFPhaseConnection"\r
157 #define QOS_CONNECTION                      "QoSConnection"\r
158 #define IPC_CONNECTION                      "IPCConnection"\r
159 \r
160 static const char* ALL_CONNECTIONS[] = { SYNC_CONNECTION, AVP_CONNECTION, \r
161                         DFP_CONNECTION, QOS_CONNECTION, IPC_CONNECTION, NULL };\r
162 \r
163 #define MOST_SOCKET                         "MOSTSocket"\r
164 #define USB_SOCKET                          "USBSocket"\r
165 #define MLB_SOCKET                          "MediaLBSocket"\r
166 #define STREAM_SOCKET                       "StreamSocket"\r
167 #define SPLITTER                            "Splitter"\r
168 #define COMBINER                            "Combiner"\r
169 static const char* ALL_SOCKETS[] = { MOST_SOCKET, USB_SOCKET, MLB_SOCKET, \r
170                         STREAM_SOCKET, SPLITTER, COMBINER, NULL };\r
171 \r
172 #define MLB_PORT                            "MediaLBPort"\r
173 #define USB_PORT                            "USBPort"\r
174 #define STRM_PORT                           "StreamPort"\r
175 static const char* ALL_PORTS[] = { MLB_PORT, USB_PORT, STRM_PORT };\r
176 \r
177 static const char* PHYSICAL_LAYER =         "PhysicalLayer";\r
178 static const char* DEVICE_INTERFACES =      "DeviceInterfaces";\r
179 static const char* STRM_IN_COUNT =          "StreamingIfEpInCount";\r
180 static const char* STRM_OUT_COUNT =         "StreamingIfEpOutCount";\r
181 \r
182 static const char* STRM_PIN =                "StreamPinID";\r
183 static const char* STRM_ALIGN =              "DataAlignment";\r
184 \r
185 static const char* SCRIPT =                 "Script";\r
186 static const char* FBLOCK_ID =              "FBlockId";\r
187 static const char* FUNCTION_ID =            "FunctionId";\r
188 static const char* OP_TYPE_REQUEST =        "OpTypeRequest";\r
189 static const char* OP_TYPE_RESPONSE =       "OpTypeResponse";\r
190 static const char* PAYLOAD_REQ_HEX =        "PayloadRequest";\r
191 static const char* PAYLOAD_RES_HEX =        "PayloadResponse";\r
192 static const char* PAUSE_MS =               "WaitTime";\r
193 static const char* DEBOUNCE_TIME =          "DebounceTime";\r
194 static const char* PIN_CONFIG =             "PinConfiguration";\r
195 static const char* PIN_MASK =               "Mask";\r
196 static const char* PIN_DATA =               "Data";\r
197 static const char* I2C_SPEED =              "Speed";\r
198 static const char* I2C_SPEED_SLOW =         "SlowMode";\r
199 static const char* I2C_SPEED_FAST =         "FastMode";\r
200 static const char* I2C_WRITE_MODE =         "Mode";\r
201 static const char* I2C_WRITE_MODE_DEFAULT = "DefaultMode";\r
202 static const char* I2C_WRITE_MODE_REPEAT =  "RepeatedStartMode";\r
203 static const char* I2C_WRITE_MODE_BURST =   "BurstMode";\r
204 static const char* I2C_WRITE_BLOCK_COUNT =  "BlockCount";\r
205 static const char* I2C_SLAVE_ADDRESS =      "Address";\r
206 static const char* I2C_PAYLOAD_LENGTH =     "Length";\r
207 static const char* I2C_PAYLOAD =            "Payload";\r
208 static const char* I2C_TIMEOUT =            "Timeout";\r
209 \r
210 #define SCRIPT_MSG_SEND                     "MsgSend"\r
211 #define SCRIPT_PAUSE                        "Pause"\r
212 #define SCRIPT_GPIO_PORT_CREATE             "GPIOPortCreate"\r
213 #define SCRIPT_GPIO_PORT_PIN_MODE           "GPIOPortPinMode"\r
214 #define SCRIPT_GPIO_PIN_STATE               "GPIOPinState"\r
215 #define SCRIPT_I2C_PORT_CREATE              "I2CPortCreate"\r
216 #define SCRIPT_I2C_PORT_WRITE               "I2CPortWrite"\r
217 #define SCRIPT_I2C_PORT_READ                "I2CPortRead"\r
218 static const char* ALL_SCRIPTS[] = { SCRIPT_MSG_SEND, SCRIPT_PAUSE, \r
219     SCRIPT_GPIO_PORT_CREATE, SCRIPT_GPIO_PORT_PIN_MODE, SCRIPT_GPIO_PIN_STATE,\r
220     SCRIPT_I2C_PORT_CREATE, SCRIPT_I2C_PORT_WRITE, SCRIPT_I2C_PORT_READ, NULL };\r
221 \r
222 static const char* VALUE_TRUE =             "true";\r
223 static const char* VALUE_FALSE =            "false";\r
224 static const char* VALUE_1 =                "1";\r
225 static const char* VALUE_0 =                "0";\r
226 \r
227 /************************************************************************/\r
228 /* Private Function Prototypes                                          */\r
229 /************************************************************************/\r
230 \r
231 static void FreeVal(UcsXmlVal_t *ucs);\r
232 static bool GetElement(mxml_node_t *element, const char *name, bool goDeep, mxml_node_t **out, bool mandatory);\r
233 static bool GetElementArray(mxml_node_t *element, const char *array[], const char **foundName, mxml_node_t **out);\r
234 static bool GetCount(mxml_node_t *element, const char *name, uint32_t *out, bool mandatory);\r
235 static bool GetCountArray(mxml_node_t *element, const char *array[], uint32_t *out, bool mandatory);\r
236 static bool GetString(mxml_node_t *element, const char *key, const char **out, bool mandatory);\r
237 static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory);\r
238 static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory);\r
239 static bool GetSocketType(const char *txt, MSocketType_t *out);\r
240 static bool GetPayload(mxml_node_t *element, const char *name, uint8_t **pPayload, uint8_t *len, uint8_t offset,\r
241             struct UcsXmlObjectList *obj, bool mandatory);\r
242 static bool AddJob(struct UcsXmlJobList **joblist, Ucs_Xrm_ResObject_t *job, struct UcsXmlObjectList *objList);\r
243 static Ucs_Xrm_ResObject_t **GetJobList(struct UcsXmlJobList *joblist, struct UcsXmlObjectList *objList);\r
244 static struct UcsXmlJobList *DeepCopyJobList(struct UcsXmlJobList *jobsIn, struct UcsXmlObjectList *objList);\r
245 static void AddRoute(struct UcsXmlRoute **pRtLst, struct UcsXmlRoute *route);\r
246 static void AddScript(struct UcsXmlScript **pScrLst, struct UcsXmlScript *script);\r
247 static ParseResult_t ParseAll(mxml_node_t *tree, UcsXmlVal_t *ucs, PrivateData_t *priv);\r
248 static ParseResult_t ParseNode(mxml_node_t * node, PrivateData_t *priv);\r
249 static ParseResult_t ParseConnection(mxml_node_t * node, const char *conType, PrivateData_t *priv);\r
250 static ParseResult_t ParseSocket(mxml_node_t *soc, bool isSource, MSocketType_t socketType, struct UcsXmlJobList **jobList, PrivateData_t *priv);\r
251 static ParseResult_t ParseScript(mxml_node_t *scr, PrivateData_t *priv);\r
252 static bool FillScriptInitialValues(Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
253 static ParseResult_t ParseScriptMsgSend(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
254 static ParseResult_t ParseScriptGpioPortCreate(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
255 static ParseResult_t ParseScriptGpioPinMode(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
256 static ParseResult_t ParseScriptGpioPinState(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
257 static ParseResult_t ParseScriptPortCreate(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
258 static ParseResult_t ParseScriptPortWrite(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
259 static ParseResult_t ParseScriptPortRead(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
260 static ParseResult_t ParseScriptPause(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
261 static ParseResult_t ParseRoutes(UcsXmlVal_t *ucs, PrivateData_t *priv);\r
262 \r
263 /************************************************************************/\r
264 /* Public Functions                                                     */\r
265 /************************************************************************/\r
266 \r
267 UcsXmlVal_t *UcsXml_Parse(const char *xmlString)\r
268 {\r
269     UcsXmlVal_t *val;\r
270     ParseResult_t result = Parse_MemoryError;\r
271     mxml_node_t *tree;\r
272     if (!(tree = mxmlLoadString(NULL, xmlString, MXML_NO_CALLBACK))) goto ERROR;\r
273     if (!GetElement(tree, UNICENS, true, &tree, true)) goto ERROR;\r
274     /*Do not use MCalloc for the root element*/\r
275     val = calloc(1, sizeof(UcsXmlVal_t));\r
276     if (!val) goto ERROR;\r
277     val->pInternal = calloc(1, sizeof(PrivateData_t));\r
278     if (!val->pInternal) goto ERROR;\r
279     result = ParseAll(tree, val, val->pInternal);\r
280     if (Parse_Success == result)\r
281         return val;\r
282 ERROR:\r
283     if (Parse_MemoryError == result)\r
284         UcsXml_CB_OnError("XML error, aborting..", 0);\r
285     else\r
286         UcsXml_CB_OnError("Allocation error, aborting..", 0);\r
287     assert(false);    \r
288     if (!tree)\r
289         mxmlDelete(tree);\r
290     FreeVal(val);\r
291     return NULL;\r
292 }\r
293 \r
294 void UcsXml_FreeVal(UcsXmlVal_t *val)\r
295 {\r
296     FreeVal(val);\r
297 }\r
298 \r
299 /************************************************************************/\r
300 /* Private Function Implementations                                     */\r
301 /************************************************************************/\r
302 \r
303 void FreeVal(UcsXmlVal_t *ucs)\r
304 {\r
305     PrivateData_t *priv;\r
306     if (NULL == ucs || NULL == ucs->pInternal)\r
307         return;\r
308     priv = ucs->pInternal;\r
309     FreeObjList(&priv->objList);\r
310     free(ucs->pInternal);\r
311     free(ucs);\r
312 }\r
313 \r
314 static bool GetElement(mxml_node_t *element, const char *name, bool goDeep, mxml_node_t **out, bool mandatory)\r
315 {\r
316     mxml_node_t *n = element;\r
317     if (NULL == n || NULL == name || NULL == out) return false;\r
318     if (goDeep)\r
319     {\r
320         *out = mxmlFindElement(n, n, name, NULL, NULL, MXML_DESCEND);\r
321         return (NULL != *out);\r
322     }\r
323     while ((n = n->next))\r
324     {\r
325         if (MXML_ELEMENT != n->type)\r
326             continue;\r
327         if (0 == strcmp(name, n->value.opaque))\r
328         {\r
329             *out = n;\r
330             return true;\r
331         }\r
332     }\r
333     if (mandatory)\r
334         UcsXml_CB_OnError("Can not find tag <%s>", 1, name);\r
335     return false;\r
336 }\r
337 \r
338 static bool GetElementArray(mxml_node_t *element, const char *array[], const char **foundName, mxml_node_t **out)\r
339 {\r
340     mxml_node_t *n = element;\r
341     if (NULL == n || NULL == array || NULL == foundName || NULL == out) return false;\r
342     while ((n = n->next))\r
343     {\r
344         uint32_t i;\r
345         if (MXML_ELEMENT != n->type)\r
346             continue;\r
347         for (i = 0; NULL != array[i]; i++)\r
348         {\r
349             if (0 == strcmp(array[i], n->value.opaque))\r
350             {\r
351                 *foundName = array[i];\r
352                 *out = n;\r
353                 return true;\r
354             }\r
355         }\r
356     }\r
357     return false;\r
358 }\r
359 \r
360 static bool GetCount(mxml_node_t *element, const char *name, uint32_t *out, bool mandatory)\r
361 {\r
362     uint32_t cnt = 0;\r
363     mxml_node_t *n;\r
364     if (NULL == element || NULL == name) return false;\r
365     if(!GetElement(element, name, true, &n, false))\r
366         return false;\r
367     while(NULL != n)\r
368     {\r
369         ++cnt;\r
370         if(!GetElement(n, name, false, &n, false))\r
371             break;\r
372     }\r
373     if (mandatory && 0 == cnt)\r
374     {\r
375         UcsXml_CB_OnError("element count of <%s> is zero", 1, name);\r
376         return false;\r
377     }\r
378     *out = cnt;\r
379     return true;\r
380 }\r
381 \r
382 static bool GetCountArray(mxml_node_t *element, const char *array[], uint32_t *out, bool mandatory)\r
383 {\r
384     const char *tmp;\r
385     uint32_t cnt = 0;\r
386     mxml_node_t *n;\r
387     if (NULL == element || NULL == array) return false;\r
388     n = element;\r
389     while(NULL != n)\r
390     {\r
391         if(!GetElementArray(n, array, &tmp, &n))\r
392             break;\r
393         ++cnt;\r
394     }\r
395     if (mandatory && 0 == cnt)\r
396     {\r
397         UcsXml_CB_OnError("element count is zero, searched with string array", 0);\r
398         return false;\r
399     }\r
400     *out = cnt;\r
401     return true;\r
402 }\r
403 \r
404 static bool GetString(mxml_node_t *element, const char *key, const char **out, bool mandatory)\r
405 {\r
406     int32_t i;\r
407     if (NULL == element || NULL == key) return false;\r
408     for (i = 0; i < element->value.element.num_attrs; i++)\r
409     {\r
410         mxml_attr_t *attr = &element->value.element.attrs[i];\r
411         if (0 == strcmp(key, attr->name))\r
412         {\r
413             *out = attr->value;\r
414             return true;\r
415         }\r
416     }\r
417     if (mandatory)\r
418         UcsXml_CB_OnError("Can not find attribute='%s' from element <%s>", \r
419             2, key, element->value.element.name);\r
420     return false;\r
421 }\r
422 \r
423 static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory)\r
424 {\r
425     const char* txt;\r
426     if (!GetString(element, key, &txt, mandatory)) return false;\r
427     *out = strtol( txt, NULL, 0 );\r
428     return true;\r
429 }\r
430 \r
431 static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory)\r
432 {\r
433     const char* txt;\r
434     if (!GetString(element, key, &txt, mandatory)) return false;\r
435     *out = strtol( txt, NULL, 0 );\r
436     return true;\r
437 }\r
438 \r
439 static bool GetDataType(const char *txt, MDataType_t *out)\r
440 {\r
441     if (NULL == txt || NULL == out) return false;\r
442     if (0 == strcmp(SYNC_CONNECTION, txt)) {\r
443         *out = SYNC_DATA;\r
444     } else if (0 == strcmp(AVP_CONNECTION, txt)) {\r
445         *out = AV_PACKETIZED;\r
446     } else if (0 == strcmp(QOS_CONNECTION, txt)) {\r
447         *out = QOS_IP;\r
448     } else if (0 == strcmp(DFP_CONNECTION, txt)) {\r
449         *out = DISC_FRAME_PHASE;\r
450     } else if (0 == strcmp(IPC_CONNECTION, txt)) {\r
451         *out = IPC_PACKET;\r
452     } else {\r
453         UcsXml_CB_OnError("Unknown data type : '%s'", 1, txt);\r
454         return false;\r
455     }\r
456     return true;\r
457 }\r
458 \r
459 static bool GetSocketType(const char *txt, MSocketType_t *out)\r
460 {\r
461     if (0 == strcmp(txt, MOST_SOCKET)) {\r
462             *out = MSocket_MOST;\r
463     } else if (0 == strcmp(txt, USB_SOCKET)) {\r
464         *out = MSocket_USB;\r
465     } else if (0 == strcmp(txt, MLB_SOCKET)) {\r
466         *out = MSocket_MLB;\r
467     } else if (0 == strcmp(txt, STREAM_SOCKET)) {\r
468         *out = MSocket_STRM;\r
469     } else if (0 == strcmp(txt, SPLITTER)) {\r
470         *out = MSocket_SPLITTER;\r
471     } else if (0 == strcmp(txt, COMBINER)) {\r
472         *out = MSocket_COMBINER;\r
473     } else {\r
474         UcsXml_CB_OnError("Unknown port : '%s'", 1, txt);\r
475         return false;\r
476     }\r
477     return true;\r
478 }\r
479 \r
480 static bool GetPayload(mxml_node_t *element, const char *name, uint8_t **pPayload, uint8_t *outLen, uint8_t offset, struct UcsXmlObjectList *obj, bool mandatory)\r
481 {\r
482     uint32_t tempLen, len = 0;\r
483     uint8_t *p;\r
484     const char *txt;\r
485     char *txtCopy;\r
486     char *tkPtr;\r
487     char *token;\r
488     if (!GetString(element, name, &txt, mandatory))\r
489         return false;\r
490     tempLen = strlen(txt) + 1;\r
491     txtCopy = malloc(tempLen);\r
492     if (NULL == txtCopy) \r
493         return false;\r
494     strncpy(txtCopy, txt, tempLen);\r
495     tempLen = tempLen / 3; /* 2 chars hex value plus space (AA )  */\r
496     p = MCalloc(obj, offset + tempLen, 1);\r
497     if (NULL == p)\r
498     {\r
499         free(txtCopy);\r
500         return false;\r
501     }\r
502     *pPayload = p;\r
503     token = strtok_r( txtCopy, " ,.-", &tkPtr );\r
504     while( NULL != token )\r
505     {\r
506         if( len >= tempLen )\r
507         {\r
508             UcsXml_CB_OnError("Script payload values must be stuffed to two characters", 0);\r
509             free(txtCopy);\r
510             assert(false);\r
511             return 0;\r
512         }\r
513         p[offset + len++] = strtol( token, NULL, 16 );\r
514         token = strtok_r( NULL, " ,.-", &tkPtr );\r
515     }\r
516     *outLen = len;\r
517     return true;\r
518 }\r
519 \r
520 static bool AddJob(struct UcsXmlJobList **joblist, Ucs_Xrm_ResObject_t *job, struct UcsXmlObjectList *objList)\r
521 {\r
522     struct UcsXmlJobList *tail;\r
523     if (NULL == joblist || NULL == job)\r
524         return false;\r
525     assert(UCS_XRM_RC_TYPE_QOS_CON >= *((Ucs_Xrm_ResourceType_t *)job));\r
526     if (NULL == joblist[0])\r
527     {\r
528         joblist[0] = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));\r
529         if (NULL == joblist[0]) return false;;\r
530         joblist[0]->job = job;\r
531         return true;\r
532     }\r
533     tail = joblist[0];\r
534     while(tail->next) tail = tail->next;\r
535     tail->next = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));\r
536     if (NULL == tail->next) return false;\r
537     tail->next->job = job;\r
538     return true;\r
539 }\r
540 \r
541 static Ucs_Xrm_ResObject_t **GetJobList(struct UcsXmlJobList *joblist, struct UcsXmlObjectList *objList)\r
542 {\r
543     Ucs_Xrm_ResObject_t **outJob;\r
544     uint32_t count = 0;\r
545     struct UcsXmlJobList *tail;\r
546     if (NULL == joblist)\r
547         return false;\r
548     /*First: Get amount of stored jobs by enumerate all*/\r
549     tail = joblist;\r
550     while(tail)\r
551     {\r
552         ++count;\r
553         tail = tail->next;\r
554     }\r
555     if (0 == count)\r
556         return false;\r
557     /*Second: Allocate count+1 elements (NULL terminated) and copy pointers*/\r
558     outJob = MCalloc(objList, (count + 1), sizeof(Ucs_Xrm_ResObject_t *));\r
559     if (NULL == outJob)\r
560         return false;\r
561     tail = joblist;\r
562     count = 0;\r
563     while(tail)\r
564     {\r
565         outJob[count++] = tail->job;\r
566         tail = tail->next;\r
567     }\r
568     return outJob;\r
569 }\r
570 \r
571 static struct UcsXmlJobList *DeepCopyJobList(struct UcsXmlJobList *jobsIn, struct UcsXmlObjectList *objList)\r
572 {\r
573     struct UcsXmlJobList *jobsOut, *tail;\r
574     if (NULL == jobsIn || NULL == objList)\r
575         return NULL;\r
576     jobsOut = tail = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));\r
577     if (NULL == jobsOut) { assert(false); return NULL; }\r
578     while(jobsIn)\r
579     {\r
580         tail->job = jobsIn->job;\r
581         if (jobsIn->next)\r
582         {\r
583             tail->next = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));\r
584             if (NULL == tail->next) { assert(false); return NULL; }\r
585             tail = tail->next;\r
586         }\r
587         jobsIn = jobsIn->next;\r
588     }\r
589     return jobsOut;\r
590 }\r
591 \r
592 static void AddRoute(struct UcsXmlRoute **pRtLst, struct UcsXmlRoute *route)\r
593 {\r
594     struct UcsXmlRoute *tail;\r
595     if (NULL == pRtLst || NULL == route)\r
596     {\r
597         assert(false);\r
598         return;\r
599     }\r
600     if (NULL == pRtLst[0])\r
601     {\r
602         pRtLst[0] = route;\r
603         return;\r
604     }\r
605     tail = pRtLst[0];\r
606     while(tail->next) tail = tail->next;\r
607     tail->next = route;\r
608 }\r
609 \r
610 static void AddScript(struct UcsXmlScript **pScrLst, struct UcsXmlScript *script)\r
611 {\r
612     struct UcsXmlScript *tail;\r
613     if (NULL == pScrLst || NULL == script)\r
614     {\r
615         assert(false);\r
616         return;\r
617     }\r
618     if (NULL == pScrLst[0])\r
619     {\r
620         pScrLst[0] = script;\r
621         return;\r
622     }\r
623     tail = pScrLst[0];\r
624     while(tail->next) tail = tail->next;\r
625     tail->next = script;\r
626 }\r
627 \r
628 static ParseResult_t ParseAll(mxml_node_t *tree, UcsXmlVal_t *ucs, PrivateData_t *priv)\r
629 {\r
630     uint32_t nodeCount;\r
631     mxml_node_t *sub;\r
632     ParseResult_t result;\r
633     priv->autoRouteId = 0x8000;\r
634     if (!GetCount(tree, NODE, &nodeCount, true))\r
635         RETURN_ASSERT(Parse_XmlError);\r
636     \r
637     ucs->pNod = MCalloc(&priv->objList, nodeCount, sizeof(Ucs_Rm_Node_t));\r
638     if (NULL == ucs->pNod) RETURN_ASSERT(Parse_MemoryError);\r
639 \r
640     if (!GetUInt16(tree, PACKET_BW, &ucs->packetBw, true))\r
641         RETURN_ASSERT(Parse_XmlError);\r
642 \r
643     /*Iterate all nodes*/\r
644     if (!GetElement(tree, NODE, true, &sub, true))\r
645         RETURN_ASSERT(Parse_XmlError);\r
646     while(sub)\r
647     {\r
648         const char *conType;\r
649         mxml_node_t *con;\r
650         memset(&priv->nodeData, 0, sizeof(NodeData_t));\r
651         priv->nodeData.nod = &ucs->pNod[ucs->nodSize];\r
652         if (Parse_Success != (result = ParseNode(sub, priv)))\r
653             return result;\r
654         /*/Iterate all connections. Node without any connection is also valid.*/\r
655         if (!GetElementArray(sub->child, ALL_CONNECTIONS, &conType, &con))\r
656             continue;\r
657         while(con)\r
658         {\r
659             const char *socTypeStr;\r
660             MSocketType_t socType;\r
661             mxml_node_t *soc;\r
662             memset(&priv->conData, 0, sizeof(ConnectionData_t));\r
663             if (Parse_Success != (result = ParseConnection(con, conType, priv)))\r
664                 return result;\r
665             /*Iterate all sockets*/\r
666             if(!GetElementArray(con->child, ALL_SOCKETS, &socTypeStr, &soc)) RETURN_ASSERT(Parse_XmlError);\r
667             while(soc)\r
668             {\r
669                 if (!GetSocketType(socTypeStr, &socType)) RETURN_ASSERT(Parse_XmlError);\r
670                 if (Parse_Success != (result = ParseSocket(soc, (0 == priv->conData.sockCnt), socType, &priv->conData.jobList, priv)))\r
671                     return result;\r
672                 ++priv->conData.sockCnt;\r
673                 if(!GetElementArray(soc, ALL_SOCKETS, &socTypeStr, &soc))\r
674                     break;\r
675             }\r
676             if(!GetElementArray(con, ALL_CONNECTIONS, &conType, &con))\r
677                 break;\r
678         }\r
679         ++ucs->nodSize;\r
680         if (!GetElement(sub, NODE, false, &sub, false))\r
681             break;\r
682     }\r
683 \r
684     /*Fill route structures*/\r
685     result = ParseRoutes(ucs, priv);\r
686     if (Parse_MemoryError == result) RETURN_ASSERT(Parse_MemoryError)\r
687     else if (Parse_XmlError == result) RETURN_ASSERT(Parse_XmlError);\r
688     \r
689     /*Iterate all scripts. No scripts at all is allowed*/\r
690     if(GetElement(tree, SCRIPT, true, &sub, false))\r
691     {\r
692         while(sub)\r
693         {\r
694             result = ParseScript(sub, priv);\r
695             if (Parse_MemoryError == result) RETURN_ASSERT(Parse_MemoryError)\r
696             else if (Parse_XmlError == result) RETURN_ASSERT(Parse_XmlError);\r
697             if(!GetElement(sub, SCRIPT, false, &sub, false))\r
698                 break;\r
699         }\r
700     }\r
701     return result;\r
702 }\r
703 \r
704 static ParseResult_t ParseNode(mxml_node_t *node, PrivateData_t *priv)\r
705 {\r
706     const char *txt;\r
707     mxml_node_t *port;\r
708     Ucs_Signature_t *signature;\r
709     assert(NULL != node && NULL != priv);\r
710     priv->nodeData.nod->signature_ptr = MCalloc(&priv->objList, 1, sizeof(Ucs_Signature_t));\r
711     signature = priv->nodeData.nod->signature_ptr;\r
712     if(NULL == signature) RETURN_ASSERT(Parse_MemoryError);\r
713     if (!GetUInt16(node, ADDRESS, &signature->node_address, true))\r
714         RETURN_ASSERT(Parse_XmlError);\r
715     if (GetString(node, SCRIPT, &txt, false))\r
716     {\r
717         struct UcsXmlScript *scr = MCalloc(&priv->objList, 1, sizeof(struct UcsXmlScript));\r
718         if (NULL == scr) RETURN_ASSERT(Parse_MemoryError);\r
719         scr->node = priv->nodeData.nod;\r
720         strncpy(scr->scriptName, txt, sizeof(scr->scriptName));\r
721         AddScript(&priv->pScrLst, scr);\r
722     }\r
723     /*Iterate all ports*/\r
724     if(GetElementArray(node->child, ALL_PORTS, &txt, &port))\r
725     {\r
726         while(port)\r
727         {\r
728             if (0 == (strcmp(txt, MLB_PORT)))\r
729             {\r
730                 struct MlbPortParameters p;\r
731                 p.list = &priv->objList;\r
732                 if (!GetString(port, CLOCK_CONFIG, &p.clockConfig, true)) RETURN_ASSERT(Parse_XmlError);\r
733                 if (!GetMlbPort(&priv->nodeData.mlbPort, &p)) RETURN_ASSERT(Parse_XmlError);\r
734             }\r
735             else if (0 == (strcmp(txt, USB_PORT)))\r
736             {\r
737                 struct UsbPortParameters p;\r
738                 p.list = &priv->objList;\r
739                 if (!GetString(port, PHYSICAL_LAYER, &p.physicalLayer, true)) RETURN_ASSERT(Parse_XmlError);\r
740                 if (!GetString(port, DEVICE_INTERFACES, &p.deviceInterfaces, true)) RETURN_ASSERT(Parse_XmlError);\r
741                 if (!GetString(port, STRM_IN_COUNT, &p.streamInCount, true)) RETURN_ASSERT(Parse_XmlError);\r
742                 if (!GetString(port, STRM_OUT_COUNT, &p.streamOutCount, true)) RETURN_ASSERT(Parse_XmlError);\r
743                 if (!GetUsbPort(&priv->nodeData.usbPort, &p)) RETURN_ASSERT(Parse_XmlError);\r
744             }\r
745             else if (0 == (strcmp(txt, STRM_PORT)))\r
746             {\r
747                 struct StrmPortParameters p;\r
748                 p.list = &priv->objList;\r
749                 p.index = 0;\r
750                 if (!GetString(port, CLOCK_CONFIG, &p.clockConfig, true)) RETURN_ASSERT(Parse_XmlError);\r
751                 if (!GetString(port, STRM_ALIGN, &p.dataAlignment, true)) RETURN_ASSERT(Parse_XmlError);\r
752                 if (!GetStrmPort(&priv->nodeData.strmPortA, &p)) RETURN_ASSERT(Parse_XmlError);\r
753                 p.index = 1;\r
754                 if (!GetStrmPort(&priv->nodeData.strmPortB, &p)) RETURN_ASSERT(Parse_XmlError);\r
755             }\r
756             else\r
757             {\r
758                 UcsXml_CB_OnError("Unknown Port:'%s'", 1, txt);\r
759                 RETURN_ASSERT(Parse_XmlError);\r
760             }\r
761             if(!GetElementArray(port, ALL_SOCKETS, &txt, &port))\r
762                 break;\r
763         }\r
764     }\r
765     return Parse_Success;;\r
766 }\r
767 \r
768 static ParseResult_t ParseConnection(mxml_node_t * node, const char *conType, PrivateData_t *priv)\r
769 {   \r
770     assert(NULL != node && NULL != priv);\r
771     if (NULL == conType) RETURN_ASSERT(Parse_XmlError);\r
772     if (!GetDataType(conType, &priv->conData.dataType)) RETURN_ASSERT(Parse_XmlError);\r
773     switch (priv->conData.dataType)\r
774     {\r
775     case SYNC_DATA:\r
776     {\r
777         const char *txt;\r
778         if (GetString(node, MUTE_MODE, &txt, false))\r
779         {\r
780             if (0 == strcmp(txt, MUTE_MODE_NO_MUTING))\r
781                 priv->conData.muteMode = UCS_SYNC_MUTE_MODE_NO_MUTING;\r
782             else if (0 == strcmp(txt, MUTE_MODE_MUTE_SIGNAL))\r
783                 priv->conData.muteMode = UCS_SYNC_MUTE_MODE_MUTE_SIGNAL;\r
784             else\r
785             {\r
786                 UcsXml_CB_OnError("ParseConnection: MuteMode='%s' not implemented", 1, txt);\r
787                 RETURN_ASSERT(Parse_XmlError);\r
788             }\r
789         }\r
790         else\r
791         {\r
792             /*Be tolerant, this is an optional feature*/\r
793             priv->conData.muteMode = UCS_SYNC_MUTE_MODE_NO_MUTING;\r
794         }\r
795         break;\r
796     }\r
797     case AV_PACKETIZED:\r
798     {\r
799         uint16_t size;\r
800         if (GetUInt16(node, AVP_PACKET_SIZE, &size, false))\r
801         {\r
802             switch(size)\r
803             {\r
804             case 188:\r
805                 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_188;\r
806                 break;\r
807             case 196:\r
808                 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_196;\r
809                 break;\r
810             case 206:\r
811                 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_206;\r
812                 break;\r
813             default:\r
814                 UcsXml_CB_OnError("ParseConnection: %s='%d' not implemented", 2, AVP_PACKET_SIZE, size);\r
815                 RETURN_ASSERT(Parse_XmlError);\r
816             }\r
817         }\r
818         else\r
819         {\r
820             /*Be tolerant, this is an optional feature*/\r
821             priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_188;\r
822         }\r
823         break;\r
824     }\r
825     default:\r
826         UcsXml_CB_OnError("ParseConnection: Datatype='%s' not implemented", 1, conType);\r
827         RETURN_ASSERT(Parse_XmlError);\r
828         break;\r
829     }\r
830     return Parse_Success;\r
831 }\r
832 \r
833 static ParseResult_t ParseSocket(mxml_node_t *soc, bool isSource, MSocketType_t socketType, struct UcsXmlJobList **jobList, PrivateData_t *priv)\r
834 {\r
835     Ucs_Xrm_ResObject_t **targetSock;\r
836     assert(NULL != soc && NULL != priv);\r
837     targetSock = isSource ? &priv->conData.inSocket : &priv->conData.outSocket;\r
838     switch(socketType)\r
839     {\r
840     case MSocket_MOST:\r
841     {\r
842         const char* txt;\r
843         struct MostSocketParameters p;\r
844         /* If there is an combiner stored, add it now into job list (right before MOST socket) */\r
845         if (priv->conData.combiner)\r
846             if (!AddJob(jobList, priv->conData.combiner, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
847         \r
848         p.list = &priv->objList;\r
849         p.isSource = isSource;\r
850         p.dataType = priv->conData.dataType;\r
851         if (!GetUInt16(soc, BANDWIDTH, &p.bandwidth, true)) RETURN_ASSERT(Parse_XmlError);\r
852         if (!GetString(soc, ROUTE, &priv->conData.routeName, true)) RETURN_ASSERT(Parse_XmlError);\r
853         if (GetString(soc, ROUTE_IS_ACTIVE, &txt, false))\r
854         {\r
855             if (0 == strcmp(txt, VALUE_TRUE) || 0 == strcmp(txt, VALUE_1))\r
856                 priv->conData.isDeactivated = false;\r
857             else if (0 == strcmp(txt, VALUE_FALSE) || 0 == strcmp(txt, VALUE_0))\r
858                 priv->conData.isDeactivated = true;\r
859             else RETURN_ASSERT(Parse_XmlError);\r
860         } else {\r
861             priv->conData.isDeactivated = false;\r
862         }\r
863         if (!GetUInt16(soc, ROUTE_ID, &priv->conData.routeId, false))\r
864             priv->conData.routeId = ++priv->autoRouteId;\r
865         if (priv->conData.syncOffsetNeeded)\r
866         {\r
867             if (!GetUInt16(soc, OFFSET, &priv->conData.syncOffset, true)) RETURN_ASSERT(Parse_XmlError);\r
868         }\r
869         if (!GetMostSocket((Ucs_Xrm_MostSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);\r
870         if (!AddJob(jobList, *targetSock, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
871         break;\r
872     }\r
873     case MSocket_USB:\r
874     {\r
875         struct UsbSocketParameters p;\r
876         p.list = &priv->objList;\r
877         p.isSource = isSource;\r
878         p.dataType = priv->conData.dataType;\r
879         if (priv->nodeData.usbPort)\r
880         {\r
881             p.usbPort = priv->nodeData.usbPort;\r
882         } else {\r
883             if (!GetUsbPortDefaultCreated(&p.usbPort, &priv->objList)) \r
884                 RETURN_ASSERT(Parse_XmlError);\r
885             priv->nodeData.usbPort = (Ucs_Xrm_UsbPort_t *)p.usbPort;\r
886         }\r
887         if (!priv->nodeData.usbPortAddedToJobList)\r
888         {\r
889             priv->nodeData.usbPortAddedToJobList = true;\r
890             if(!AddJob(jobList, p.usbPort, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
891         }\r
892         if (!GetString(soc, ENDPOINT_ADDRESS, &p.endpointAddress, true)) RETURN_ASSERT(Parse_XmlError);\r
893         if (!GetString(soc, FRAMES_PER_TRANSACTION, &p.framesPerTrans, true)) RETURN_ASSERT(Parse_XmlError);\r
894         if (!GetUsbSocket((Ucs_Xrm_UsbSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);\r
895         if (!AddJob(jobList, *targetSock, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
896         break;\r
897     }\r
898     case MSocket_MLB:\r
899     {\r
900         struct MlbSocketParameters p;\r
901         p.list = &priv->objList;\r
902         p.isSource = isSource;\r
903         p.dataType = priv->conData.dataType;\r
904         if (priv->nodeData.mlbPort)\r
905         {\r
906             p.mlbPort = priv->nodeData.mlbPort;\r
907         } else {\r
908             if (!GetMlbPortDefaultCreated(&p.mlbPort, &priv->objList)) \r
909                 RETURN_ASSERT(Parse_XmlError);\r
910             priv->nodeData.mlbPort = (Ucs_Xrm_MlbPort_t *)p.mlbPort;\r
911         }\r
912         if (!priv->nodeData.mlbPortAddedToJobList)\r
913         {\r
914             priv->nodeData.mlbPortAddedToJobList = true;\r
915             if (!AddJob(jobList, p.mlbPort, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
916         }\r
917         if (!GetUInt16(soc, BANDWIDTH, &p.bandwidth, true)) RETURN_ASSERT(Parse_XmlError);\r
918         if (!GetString(soc, CHANNEL_ADDRESS, &p.channelAddress, true)) RETURN_ASSERT(Parse_XmlError);\r
919         if (!GetMlbSocket((Ucs_Xrm_MlbSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);\r
920         if (!AddJob(jobList, *targetSock, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
921         break;\r
922     }\r
923     case MSocket_STRM:\r
924     {\r
925         struct StrmSocketParameters p;\r
926         p.list = &priv->objList;\r
927         p.isSource = isSource;\r
928         p.dataType = priv->conData.dataType;\r
929         p.streamPortA = priv->nodeData.strmPortA;\r
930         p.streamPortB = priv->nodeData.strmPortB;\r
931         if (!priv->nodeData.strmPortsAddedToJobList)\r
932         {\r
933             priv->nodeData.strmPortsAddedToJobList = true;\r
934             if (!AddJob(jobList, p.streamPortA, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
935             if (!AddJob(jobList, p.streamPortB, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
936         }\r
937         if (!GetUInt16(soc, BANDWIDTH, &p.bandwidth, true)) RETURN_ASSERT(Parse_XmlError);\r
938         if (!GetString(soc, STRM_PIN, &p.streamPin, true)) RETURN_ASSERT(Parse_XmlError);\r
939         if (!GetStrmSocket((Ucs_Xrm_StrmSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);\r
940         if (!AddJob(jobList, *targetSock, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
941         break;\r
942     }\r
943     case MSocket_SPLITTER:\r
944     {\r
945         mxml_node_t *mostSoc;\r
946         struct SplitterParameters p;\r
947         if (isSource)\r
948         {\r
949             UcsXml_CB_OnError("Splitter can not be used as input socket", 0);\r
950             RETURN_ASSERT(Parse_XmlError);\r
951         }\r
952         p.list = &priv->objList;\r
953         if (!GetUInt16(soc, BYTES_PER_FRAME, &p.bytesPerFrame, true)) RETURN_ASSERT(Parse_XmlError);\r
954         /* Current input socket will be stored inside splitter \r
955          * and splitter will become the new input socket */\r
956         if (!(p.inSoc = priv->conData.inSocket)) RETURN_ASSERT(Parse_XmlError);\r
957         if (!GetSplitter((Ucs_Xrm_Splitter_t **)&priv->conData.inSocket, &p)) RETURN_ASSERT(Parse_XmlError);\r
958         if (!AddJob(jobList, priv->conData.inSocket, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
959         if (!GetElement(soc->child, MOST_SOCKET, false, &mostSoc, true))\r
960             RETURN_ASSERT(Parse_XmlError);\r
961         priv->conData.syncOffsetNeeded = true;\r
962         \r
963         while(mostSoc)\r
964         {\r
965             struct UcsXmlJobList *jobListCopy = DeepCopyJobList(*jobList, &priv->objList);\r
966             if (!ParseSocket(mostSoc, false, MSocket_MOST, &jobListCopy, priv)) RETURN_ASSERT(Parse_XmlError);\r
967             if (!GetElement(mostSoc, MOST_SOCKET, false, &mostSoc, false))\r
968                 return Parse_Success; /* Do not break here, otherwise an additional invalid route will be created */\r
969         }\r
970         break;\r
971     }\r
972     case MSocket_COMBINER:\r
973     {\r
974         struct CombinerParameters p;\r
975         if (!isSource)\r
976         {\r
977             UcsXml_CB_OnError("Combiner can not be used as output socket", 0);\r
978             RETURN_ASSERT(Parse_XmlError);\r
979         }\r
980         p.list = &priv->objList;\r
981         if (!GetUInt16(soc, BYTES_PER_FRAME, &p.bytesPerFrame, true)) RETURN_ASSERT(Parse_XmlError);\r
982         if (!GetCombiner(&priv->conData.combiner, &p)) RETURN_ASSERT(Parse_XmlError);\r
983         priv->conData.syncOffsetNeeded = true;\r
984         if (!GetElement(soc->child, MOST_SOCKET, false, &priv->conData.pendingCombinerMostSockets, true))\r
985             RETURN_ASSERT(Parse_XmlError);\r
986         break;\r
987     }\r
988     default:\r
989         RETURN_ASSERT(Parse_XmlError);\r
990     }\r
991     /*Handle Pending Combiner Tasks*/\r
992     if (NULL != priv->conData.outSocket && NULL != priv->conData.combiner && \r
993         NULL != priv->conData.pendingCombinerMostSockets)\r
994     {\r
995         mxml_node_t *tmp = priv->conData.pendingCombinerMostSockets;\r
996         priv->conData.pendingCombinerMostSockets = NULL;\r
997         /* Current output socket will be stored inside combiner \r
998          * and combiner will become the new output socket */\r
999         priv->conData.combiner->port_socket_obj_ptr = priv->conData.outSocket;\r
1000         priv->conData.outSocket = priv->conData.combiner;\r
1001         while(tmp)\r
1002         {\r
1003             struct UcsXmlJobList *jobListCopy = DeepCopyJobList(*jobList, &priv->objList);\r
1004             if (!ParseSocket(tmp, true, MSocket_MOST, &jobListCopy, priv)) RETURN_ASSERT(Parse_XmlError);\r
1005             if (!GetElement(tmp, MOST_SOCKET, false, &tmp, false))\r
1006                 return Parse_Success; /* Do not break here, otherwise an additional invalid route will be created */\r
1007         }\r
1008     }\r
1009     /*Connect in and out socket once they are created*/\r
1010     if (priv->conData.inSocket && priv->conData.outSocket)\r
1011     {\r
1012         bool mostIsOutput;\r
1013         Ucs_Rm_EndPoint_t *ep;\r
1014         struct UcsXmlRoute *route;\r
1015         switch(priv->conData.dataType)\r
1016         {\r
1017         case SYNC_DATA:\r
1018         {\r
1019             Ucs_Xrm_SyncCon_t *con = MCalloc(&priv->objList, 1, sizeof(Ucs_Xrm_SyncCon_t));\r
1020             if (NULL == con) RETURN_ASSERT(Parse_MemoryError);\r
1021             if (!AddJob(jobList, con, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
1022             con->resource_type = UCS_XRM_RC_TYPE_SYNC_CON;\r
1023             con->socket_in_obj_ptr = priv->conData.inSocket;\r
1024             con->socket_out_obj_ptr = priv->conData.outSocket;\r
1025             con->mute_mode = priv->conData.muteMode;\r
1026             con->offset = priv->conData.syncOffset;\r
1027             break;\r
1028         }\r
1029         case AV_PACKETIZED:\r
1030         {\r
1031             Ucs_Xrm_AvpCon_t *con = MCalloc(&priv->objList, 1, sizeof(Ucs_Xrm_AvpCon_t));\r
1032             if (NULL == con) RETURN_ASSERT(Parse_MemoryError);\r
1033             if (!AddJob(jobList, con, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
1034             con->resource_type = UCS_XRM_RC_TYPE_AVP_CON;\r
1035             con->socket_in_obj_ptr = priv->conData.inSocket;\r
1036             con->socket_out_obj_ptr = priv->conData.outSocket;\r
1037             con->isoc_packet_size = priv->conData.isocPacketSize;\r
1038             break;\r
1039         }\r
1040         default:\r
1041             UcsXml_CB_OnError("Could not connect sockets, data type not implemented: %d", 1, priv->conData.dataType);\r
1042             RETURN_ASSERT(Parse_XmlError);\r
1043             break;\r
1044         }\r
1045         ep = MCalloc(&priv->objList, 1, sizeof(Ucs_Rm_EndPoint_t));\r
1046         if (NULL == ep) RETURN_ASSERT(Parse_MemoryError);\r
1047 \r
1048         mostIsOutput = (UCS_XRM_RC_TYPE_MOST_SOCKET == *((Ucs_Xrm_ResourceType_t *)priv->conData.outSocket));\r
1049         ep->endpoint_type = mostIsOutput ? UCS_RM_EP_SOURCE : UCS_RM_EP_SINK;\r
1050         ep->jobs_list_ptr = GetJobList(*jobList, &priv->objList);\r
1051         if(NULL == ep->jobs_list_ptr) RETURN_ASSERT(Parse_MemoryError);\r
1052         ep->node_obj_ptr = priv->nodeData.nod;\r
1053         route = MCalloc(&priv->objList, 1, sizeof(struct UcsXmlRoute));\r
1054         if (NULL == route) RETURN_ASSERT(Parse_MemoryError);\r
1055         route->isSource = mostIsOutput;\r
1056         route->isActive = !priv->conData.isDeactivated;\r
1057         route->routeId = priv->conData.routeId;\r
1058         route->ep = ep;\r
1059         assert(NULL != priv->conData.routeName);\r
1060         strncpy(route->routeName, priv->conData.routeName, sizeof(route->routeName));\r
1061         AddRoute(&priv->pRtLst, route);\r
1062     }\r
1063     return Parse_Success;\r
1064 }\r
1065 \r
1066 static ParseResult_t ParseScript(mxml_node_t *scr, PrivateData_t *priv)\r
1067 {\r
1068     bool found = false;\r
1069     mxml_node_t *act;\r
1070     uint32_t actCnt;\r
1071     uint32_t i = 0;\r
1072     const char *txt;\r
1073     struct UcsXmlScript *scrlist;\r
1074     Ucs_Ns_Script_t *script;\r
1075     assert(NULL != scr && NULL != priv);\r
1076     priv->scriptData.pause = 0;\r
1077     scrlist = priv->pScrLst;\r
1078     if (!GetCountArray(scr->child, ALL_SCRIPTS, &actCnt, false)) RETURN_ASSERT(Parse_XmlError);\r
1079     if (NULL == (script = MCalloc(&priv->objList, actCnt, sizeof(Ucs_Ns_Script_t))))\r
1080         RETURN_ASSERT(Parse_MemoryError);\r
1081     actCnt = 0;\r
1082     /*Iterate all actions*/\r
1083     if (!GetElementArray(scr->child, ALL_SCRIPTS, &txt, &act)) RETURN_ASSERT(Parse_XmlError);\r
1084     while(act)\r
1085     {\r
1086         if (0 == strcmp(txt, SCRIPT_MSG_SEND)) {\r
1087             ParseResult_t result = ParseScriptMsgSend(act, &script[i], priv);\r
1088             if (Parse_Success != result) return result;\r
1089             ++actCnt;\r
1090         } else if (0 == strcmp(txt, SCRIPT_GPIO_PORT_CREATE)) {\r
1091             ParseResult_t result = ParseScriptGpioPortCreate(act, &script[i], priv);\r
1092             if (Parse_Success != result) return result;\r
1093             ++actCnt;\r
1094         } else if (0 == strcmp(txt, SCRIPT_GPIO_PORT_PIN_MODE)) {\r
1095             ParseResult_t result = ParseScriptGpioPinMode(act, &script[i], priv);\r
1096             if (Parse_Success != result) return result;\r
1097             ++actCnt;\r
1098         } else if (0 == strcmp(txt, SCRIPT_GPIO_PIN_STATE)) {\r
1099             ParseResult_t result = ParseScriptGpioPinState(act, &script[i], priv);\r
1100             if (Parse_Success != result) return result;\r
1101             ++actCnt;\r
1102         } else if (0 == strcmp(txt, SCRIPT_I2C_PORT_CREATE)) {\r
1103             ParseResult_t result = ParseScriptPortCreate(act, &script[i], priv);\r
1104             if (Parse_Success != result) return result;\r
1105             ++actCnt;\r
1106         } else if (0 == strcmp(txt, SCRIPT_I2C_PORT_WRITE)) {\r
1107             ParseResult_t result = ParseScriptPortWrite(act, &script[i], priv);\r
1108             if (Parse_Success != result) return result;\r
1109             ++actCnt;\r
1110         } else if (0 == strcmp(txt, SCRIPT_I2C_PORT_READ)) {\r
1111             ParseResult_t result = ParseScriptPortRead(act, &script[i], priv);\r
1112             if (Parse_Success != result) return result;\r
1113             ++actCnt;\r
1114         } else if (0 == strcmp(txt, SCRIPT_PAUSE)) {\r
1115             ParseResult_t result = ParseScriptPause(act, &script[i], priv);\r
1116             if (Parse_Success != result) return result;\r
1117         } else {\r
1118             UcsXml_CB_OnError("Unknown script action:'%s'", 1, txt);\r
1119             /*RETURN_ASSERT(Parse_XmlError);*/\r
1120         }\r
1121         if (!GetElementArray(act, ALL_SCRIPTS, &txt, &act))\r
1122             break;\r
1123         ++i;\r
1124     }\r
1125     if (!GetString(scr, NAME, &txt, true))\r
1126         RETURN_ASSERT(Parse_XmlError);\r
1127     while(NULL != scrlist)\r
1128     {\r
1129         if (0 == strcmp(txt, scrlist->scriptName))\r
1130         {\r
1131             Ucs_Rm_Node_t *node = scrlist->node;\r
1132             node->script_list_ptr = script;\r
1133             node->script_list_size = actCnt;\r
1134             found = true;\r
1135         }\r
1136         scrlist = scrlist->next;\r
1137     }\r
1138     if(!found)\r
1139     {\r
1140         UcsXml_CB_OnError("Script defined:'%s', which was never referenced", 1, txt);\r
1141         RETURN_ASSERT(Parse_XmlError);\r
1142     }\r
1143     return Parse_Success;\r
1144 }\r
1145 \r
1146 static bool FillScriptInitialValues(Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1147 {\r
1148     assert(NULL != scr && NULL != priv);\r
1149     scr->send_cmd = MCalloc(&priv->objList, 1, sizeof(Ucs_Ns_ConfigMsg_t));\r
1150     scr->exp_result = MCalloc(&priv->objList, 1, sizeof(Ucs_Ns_ConfigMsg_t));\r
1151     assert(scr->send_cmd && scr->exp_result);\r
1152     if (NULL == scr->send_cmd || NULL == scr->exp_result) return false;\r
1153     scr->pause = priv->scriptData.pause;\r
1154     priv->scriptData.pause = 0;\r
1155     return true;\r
1156 }\r
1157 \r
1158 static ParseResult_t ParseScriptMsgSend(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1159 {\r
1160     Ucs_Ns_ConfigMsg_t *req, *res;\r
1161     assert(NULL != act && NULL != scr && NULL != priv);\r
1162     if (!FillScriptInitialValues(scr, priv)) return Parse_MemoryError;\r
1163     req = scr->send_cmd;\r
1164     res = scr->exp_result;\r
1165     req->InstId = res->InstId = 1;\r
1166     if (!GetUInt8(act, FBLOCK_ID, &req->FBlockId, true))\r
1167         RETURN_ASSERT(Parse_XmlError);\r
1168 \r
1169     if (!GetUInt16(act, FUNCTION_ID, &req->FunktId, true))\r
1170         RETURN_ASSERT(Parse_XmlError);\r
1171 \r
1172     if (!GetUInt8(act, OP_TYPE_REQUEST, &req->OpCode, true))\r
1173         RETURN_ASSERT(Parse_XmlError);\r
1174 \r
1175     if (!GetUInt8(act, OP_TYPE_RESPONSE, &res->OpCode, true))\r
1176         RETURN_ASSERT(Parse_XmlError);\r
1177     \r
1178     res->FBlockId = req->FBlockId;\r
1179     res->FunktId = req->FunktId;\r
1180     GetPayload(act, PAYLOAD_RES_HEX, &res->DataPtr, &res->DataLen, 0, &priv->objList, false);\r
1181     \r
1182     if (!GetPayload(act, PAYLOAD_REQ_HEX, &req->DataPtr, &req->DataLen, 0, &priv->objList, true))\r
1183         RETURN_ASSERT(Parse_XmlError);\r
1184     if (0 == req->DataLen || NULL == req->DataPtr)\r
1185         RETURN_ASSERT(Parse_XmlError);\r
1186     return Parse_Success;\r
1187 }\r
1188 \r
1189 static ParseResult_t ParseScriptGpioPortCreate(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1190 {\r
1191     uint16_t debounce;\r
1192     Ucs_Ns_ConfigMsg_t *req, *res;\r
1193     assert(NULL != act && NULL != scr && NULL != priv);\r
1194     if (!FillScriptInitialValues(scr, priv))\r
1195         RETURN_ASSERT(Parse_MemoryError);\r
1196     if (!GetUInt16(act, DEBOUNCE_TIME, &debounce, true))\r
1197         RETURN_ASSERT(Parse_XmlError);\r
1198     req = scr->send_cmd;\r
1199     res = scr->exp_result;\r
1200     req->InstId = res->InstId = 1;\r
1201     req->FunktId = res->FunktId = 0x701;\r
1202     req->OpCode = 0x2;\r
1203     res->OpCode = 0xC;\r
1204     req->DataLen = 3;\r
1205     res->DataLen = 2;\r
1206     req->DataPtr = MCalloc(&priv->objList, req->DataLen, 1);\r
1207     if (NULL == req->DataPtr) return Parse_MemoryError;\r
1208     res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);\r
1209     if (NULL == res->DataPtr) return Parse_MemoryError;\r
1210     req->DataPtr[0] = 0; /*GPIO Port instance, always 0*/\r
1211     req->DataPtr[1] = MISC_HB(debounce);\r
1212     req->DataPtr[2] = MISC_LB(debounce);\r
1213 \r
1214     res->DataPtr[0] = 0x1D;\r
1215     res->DataPtr[1] = 0x00;\r
1216     return Parse_Success;\r
1217 }\r
1218 \r
1219 static ParseResult_t ParseScriptGpioPinMode(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1220 {\r
1221 #define PORT_HANDLE_OFFSET (2)\r
1222     uint8_t *payload;\r
1223     uint8_t payloadLen = 0;\r
1224     Ucs_Ns_ConfigMsg_t *req, *res;\r
1225     assert(NULL != act && NULL != scr && NULL != priv);\r
1226     if (!FillScriptInitialValues(scr, priv))\r
1227         RETURN_ASSERT(Parse_MemoryError);\r
1228     req = scr->send_cmd;\r
1229     res = scr->exp_result;\r
1230     req->InstId = res->InstId = 1;\r
1231     req->FunktId = res->FunktId = 0x703;\r
1232     req->OpCode = 0x2;\r
1233     res->OpCode = 0xC;\r
1234     if (!GetPayload(act, PIN_CONFIG, &payload, &payloadLen, \r
1235         PORT_HANDLE_OFFSET, /* First two bytes are reserved for port handle */\r
1236         &priv->objList, true)) RETURN_ASSERT(Parse_XmlError);\r
1237     payload[0] = 0x1D;\r
1238     payload[1] = 0x00;\r
1239     req->DataPtr = payload;\r
1240     res->DataPtr = payload;\r
1241     req->DataLen = payloadLen + PORT_HANDLE_OFFSET;\r
1242     res->DataLen = payloadLen + PORT_HANDLE_OFFSET;\r
1243     return Parse_Success;\r
1244 }\r
1245 \r
1246 static ParseResult_t ParseScriptGpioPinState(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1247 {\r
1248     uint16_t mask, data;\r
1249     Ucs_Ns_ConfigMsg_t *req, *res;\r
1250     assert(NULL != act && NULL != scr && NULL != priv);\r
1251     if (!FillScriptInitialValues(scr, priv))\r
1252         RETURN_ASSERT(Parse_MemoryError);\r
1253     if (!GetUInt16(act, PIN_MASK, &mask, true))\r
1254         RETURN_ASSERT(Parse_XmlError);\r
1255     if (!GetUInt16(act, PIN_DATA, &data, true))\r
1256         RETURN_ASSERT(Parse_XmlError);\r
1257     req = scr->send_cmd;\r
1258     res = scr->exp_result;\r
1259     req->InstId = res->InstId = 1;\r
1260     req->FunktId = res->FunktId = 0x704;\r
1261     req->OpCode = 0x2;\r
1262     res->OpCode = 0xC;\r
1263     req->DataLen = 6;\r
1264     res->DataLen = 8;\r
1265     req->DataPtr = MCalloc(&priv->objList, req->DataLen, 1);\r
1266     if (NULL == req->DataPtr) return Parse_MemoryError;\r
1267     res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);\r
1268     if (NULL == res->DataPtr) return Parse_MemoryError;\r
1269     req->DataPtr[0] = 0x1D;\r
1270     req->DataPtr[1] = 0x00;\r
1271     req->DataPtr[2] = MISC_HB(mask);\r
1272     req->DataPtr[3] = MISC_LB(mask);\r
1273     req->DataPtr[4] = MISC_HB(data);\r
1274     req->DataPtr[5] = MISC_LB(data);\r
1275     memcpy(res->DataPtr, req->DataPtr, req->DataLen);\r
1276     res->DataPtr[6] = 0x00;\r
1277     res->DataPtr[7] = 0x00;\r
1278     return Parse_Success;\r
1279 }\r
1280 \r
1281 static ParseResult_t ParseScriptPortCreate(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1282 {\r
1283     const char *txt;\r
1284     uint8_t speed;\r
1285     Ucs_Ns_ConfigMsg_t *req, *res;\r
1286     assert(NULL != act && NULL != scr && NULL != priv);\r
1287     if (!FillScriptInitialValues(scr, priv))\r
1288         RETURN_ASSERT(Parse_MemoryError);\r
1289     if (!GetString(act, I2C_SPEED, &txt, true))\r
1290         RETURN_ASSERT(Parse_XmlError);\r
1291     if (0 == strcmp(txt, I2C_SPEED_SLOW))\r
1292         speed = 0;\r
1293     else if (0 == strcmp(txt, I2C_SPEED_FAST))\r
1294         speed = 1;\r
1295     else RETURN_ASSERT(Parse_XmlError);\r
1296     req = scr->send_cmd;\r
1297     res = scr->exp_result;\r
1298     req->InstId = res->InstId = 1;\r
1299     req->FunktId = res->FunktId = 0x6C1;\r
1300     req->OpCode = 0x2;\r
1301     res->OpCode = 0xC;\r
1302     req->DataLen = 4;\r
1303     res->DataLen = 2;\r
1304     req->DataPtr = MCalloc(&priv->objList, req->DataLen, 1);\r
1305     if (NULL == req->DataPtr) return Parse_MemoryError;\r
1306     res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);\r
1307     if (NULL == res->DataPtr) return Parse_MemoryError;\r
1308     req->DataPtr[0] = 0x00; /* I2C Port Instance always 0 */\r
1309     req->DataPtr[1] = 0x00; /* I2C slave address, always 0, because we are Master */\r
1310     req->DataPtr[2] = 0x01; /* We are Master */\r
1311     req->DataPtr[3] = speed;\r
1312 \r
1313     res->DataPtr[0] = 0x0F;\r
1314     res->DataPtr[1] = 0x00;\r
1315     return Parse_Success;\r
1316 }\r
1317 \r
1318 static ParseResult_t ParseScriptPortWrite(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1319 {\r
1320 #define HEADER_OFFSET 8\r
1321     const char *txt;\r
1322     uint8_t mode, blockCount, address, length, payloadLength;\r
1323     uint16_t timeout;\r
1324     uint8_t *payload;\r
1325     Ucs_Ns_ConfigMsg_t *req, *res;\r
1326     assert(NULL != act && NULL != scr && NULL != priv);\r
1327     if (GetString(act, I2C_WRITE_MODE, &txt, false))\r
1328     {\r
1329         if (0 == strcmp(txt, I2C_WRITE_MODE_DEFAULT))\r
1330             mode = 0;\r
1331         else if (0 == strcmp(txt, I2C_WRITE_MODE_REPEAT))\r
1332             mode = 1;\r
1333         else if (0 == strcmp(txt, I2C_WRITE_MODE_BURST))\r
1334             mode = 2;\r
1335     } else {\r
1336         mode = 0;\r
1337     }\r
1338     if (!GetUInt8(act, I2C_WRITE_BLOCK_COUNT, &blockCount, false))\r
1339         blockCount = 0;\r
1340     if (!GetUInt8(act, I2C_SLAVE_ADDRESS, &address, true))\r
1341         RETURN_ASSERT(Parse_XmlError);\r
1342     if (!GetUInt8(act, I2C_PAYLOAD_LENGTH, &length, false))\r
1343         length = 0;\r
1344     if (!GetUInt16(act, I2C_TIMEOUT, &timeout, false))\r
1345         timeout = 100;\r
1346     if (!GetPayload(act, I2C_PAYLOAD, &payload, &payloadLength, HEADER_OFFSET, &priv->objList, true))\r
1347         RETURN_ASSERT(Parse_XmlError);\r
1348     if (0 == length)\r
1349         length = payloadLength;\r
1350     if (!FillScriptInitialValues(scr, priv))\r
1351         RETURN_ASSERT(Parse_MemoryError);\r
1352     req = scr->send_cmd;\r
1353     res = scr->exp_result;\r
1354     req->InstId = res->InstId = 1;\r
1355     req->FunktId = res->FunktId = 0x6C4;\r
1356     req->OpCode = 0x2;\r
1357     res->OpCode = 0xC;\r
1358     req->DataLen = payloadLength + HEADER_OFFSET;\r
1359     res->DataLen = 4;\r
1360     req->DataPtr = payload;\r
1361     res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);\r
1362     if (NULL == res->DataPtr) return Parse_MemoryError;\r
1363 \r
1364     req->DataPtr[0] = 0x0F;\r
1365     req->DataPtr[1] = 0x00;\r
1366     req->DataPtr[2] = mode;\r
1367     req->DataPtr[3] = blockCount;\r
1368     req->DataPtr[4] = address;\r
1369     req->DataPtr[5] = length;\r
1370     req->DataPtr[6] = MISC_HB(timeout);\r
1371     req->DataPtr[7] = MISC_LB(timeout);\r
1372 \r
1373     res->DataPtr[0] = 0x0F;\r
1374     res->DataPtr[1] = 0x00;\r
1375     res->DataPtr[2] = address;\r
1376     if (2 == mode)\r
1377         res->DataPtr[3] = blockCount * length;\r
1378     else\r
1379         res->DataPtr[3] = length;\r
1380     return Parse_Success;\r
1381 }\r
1382 \r
1383 static ParseResult_t ParseScriptPortRead(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1384 {\r
1385     uint8_t address, length;\r
1386     uint16_t timeout;\r
1387     Ucs_Ns_ConfigMsg_t *req, *res;\r
1388     assert(NULL != act && NULL != scr && NULL != priv);\r
1389     if (!GetUInt8(act, I2C_SLAVE_ADDRESS, &address, true))\r
1390         RETURN_ASSERT(Parse_XmlError);\r
1391     if (!GetUInt8(act, I2C_PAYLOAD_LENGTH, &length, true))\r
1392         RETURN_ASSERT(Parse_XmlError);\r
1393     if (!GetUInt16(act, I2C_TIMEOUT, &timeout, false))\r
1394         timeout = 100;\r
1395     if (!FillScriptInitialValues(scr, priv))\r
1396         RETURN_ASSERT(Parse_MemoryError);\r
1397     req = scr->send_cmd;\r
1398     res = scr->exp_result;\r
1399     req->InstId = res->InstId = 1;\r
1400     req->FunktId = res->FunktId = 0x6C3;\r
1401     req->OpCode = 0x2;\r
1402     res->OpCode = 0xC;\r
1403     req->DataLen = 6;\r
1404     res->DataLen = 4;\r
1405     req->DataPtr = MCalloc(&priv->objList, req->DataLen, 1);\r
1406     if (NULL == req->DataPtr) return Parse_MemoryError;\r
1407     res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);\r
1408     if (NULL == res->DataPtr) return Parse_MemoryError;\r
1409 \r
1410     req->DataPtr[0] = 0x0F;\r
1411     req->DataPtr[1] = 0x00;\r
1412     req->DataPtr[2] = address;\r
1413     req->DataPtr[3] = length;\r
1414     req->DataPtr[4] = MISC_HB(timeout);\r
1415     req->DataPtr[5] = MISC_LB(timeout);\r
1416 \r
1417     res->DataPtr[0] = 0x0F;\r
1418     res->DataPtr[1] = 0x00;\r
1419     res->DataPtr[2] = address;\r
1420     res->DataPtr[3] = length;\r
1421     return Parse_Success;\r
1422 }\r
1423 \r
1424 static ParseResult_t ParseScriptPause(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1425 {\r
1426     assert(NULL != act && NULL != priv);\r
1427     if (!GetUInt16(act, PAUSE_MS, &priv->scriptData.pause, true))\r
1428             RETURN_ASSERT(Parse_XmlError);\r
1429     return Parse_Success;\r
1430 }\r
1431 \r
1432 static ParseResult_t ParseRoutes(UcsXmlVal_t *ucs, PrivateData_t *priv)\r
1433 {\r
1434     uint16_t routeAmount = 0;\r
1435     struct UcsXmlRoute *sourceRoute;\r
1436     assert(NULL != ucs && NULL != priv);\r
1437     /*First: Count the amount of routes and allocate the correct amount*/\r
1438     sourceRoute = priv->pRtLst;\r
1439     while (NULL != sourceRoute)\r
1440     {\r
1441         if (!sourceRoute->isSource) /*There can be more sinks than sources, so count them*/\r
1442         {\r
1443             ++routeAmount;\r
1444         }\r
1445         sourceRoute = sourceRoute->next;\r
1446     }\r
1447     if (0 == routeAmount)\r
1448         return Parse_Success; /*Its okay to have no routes at all (e.g. MEP traffic only)*/\r
1449     ucs->pRoutes = MCalloc(&priv->objList, routeAmount, sizeof(Ucs_Rm_Route_t));\r
1450     if (NULL == ucs->pRoutes) RETURN_ASSERT(Parse_MemoryError);\r
1451     \r
1452     /*Second: Fill allocated structure now*/\r
1453     sourceRoute = priv->pRtLst;\r
1454     while (NULL != sourceRoute)\r
1455     {\r
1456         if (sourceRoute->isSource)\r
1457         {\r
1458             struct UcsXmlRoute *sinkRoute = priv->pRtLst;\r
1459             while (NULL != sinkRoute)\r
1460             {\r
1461                 if (sourceRoute != sinkRoute\r
1462                     && !sinkRoute->isSource\r
1463                     && (0 == strncmp(sourceRoute->routeName, sinkRoute->routeName, sizeof(sourceRoute->routeName))))\r
1464                 {\r
1465                     Ucs_Rm_Route_t *route = &ucs->pRoutes[ucs->routesSize++];\r
1466                     route->source_endpoint_ptr = sourceRoute->ep;\r
1467                     route->sink_endpoint_ptr = sinkRoute->ep;\r
1468                     route->active = sinkRoute->isActive;\r
1469                     route->route_id = sinkRoute->routeId;\r
1470                 }\r
1471                 sinkRoute = sinkRoute->next;\r
1472             }\r
1473         }\r
1474         sourceRoute = sourceRoute->next;\r
1475     }\r
1476     assert(routeAmount == ucs->routesSize);\r
1477     \r
1478 #ifdef DEBUG\r
1479     /* Third perform checks when running in debug mode*/\r
1480     {\r
1481         Ucs_Xrm_ResourceType_t *job;\r
1482         uint16_t i, j;\r
1483         for (i = 0; i < routeAmount; i++)\r
1484         {\r
1485             Ucs_Rm_Route_t *route = &ucs->pRoutes[i];\r
1486             assert(NULL != route->source_endpoint_ptr);\r
1487             assert(NULL != route->sink_endpoint_ptr);\r
1488             assert(NULL != route->source_endpoint_ptr->jobs_list_ptr);\r
1489             assert(UCS_RM_EP_SOURCE == route->source_endpoint_ptr->endpoint_type);\r
1490             assert(UCS_RM_EP_SINK == route->sink_endpoint_ptr->endpoint_type);\r
1491             assert(NULL != route->source_endpoint_ptr->node_obj_ptr);\r
1492             assert(NULL != route->sink_endpoint_ptr->node_obj_ptr);\r
1493             assert(NULL != route->source_endpoint_ptr->node_obj_ptr->signature_ptr);\r
1494             assert(NULL != route->sink_endpoint_ptr->node_obj_ptr->signature_ptr);\r
1495             j = 0;\r
1496             while((job = ((Ucs_Xrm_ResourceType_t *)route->source_endpoint_ptr->jobs_list_ptr[j])))\r
1497             {\r
1498                 assert(UCS_XRM_RC_TYPE_QOS_CON >= *job);\r
1499                 ++j;\r
1500             }\r
1501             j = 0;\r
1502             while((job = ((Ucs_Xrm_ResourceType_t *)route->sink_endpoint_ptr->jobs_list_ptr[j])))\r
1503             {\r
1504                 assert(UCS_XRM_RC_TYPE_QOS_CON >= *job);\r
1505                 ++j;\r
1506             }\r
1507         }\r
1508     }\r
1509 #endif\r
1510     return Parse_Success;\r
1511 }\r