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