4c392cde4c73339b60b3d507d6f52f27b535424d
[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 CheckInteger(const char *val, bool forceHex);\r
236 static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory);\r
237 static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory);\r
238 static bool GetSocketType(const char *txt, MSocketType_t *out);\r
239 static bool GetPayload(mxml_node_t *element, const char *name, uint8_t **pPayload, uint8_t *len, uint8_t offset,\r
240             struct UcsXmlObjectList *obj, bool mandatory);\r
241 static bool AddJob(struct UcsXmlJobList **joblist, Ucs_Xrm_ResObject_t *job, struct UcsXmlObjectList *objList);\r
242 static Ucs_Xrm_ResObject_t **GetJobList(struct UcsXmlJobList *joblist, struct UcsXmlObjectList *objList);\r
243 static struct UcsXmlJobList *DeepCopyJobList(struct UcsXmlJobList *jobsIn, struct UcsXmlObjectList *objList);\r
244 static void AddRoute(struct UcsXmlRoute **pRtLst, struct UcsXmlRoute *route);\r
245 static void AddScript(struct UcsXmlScript **pScrLst, struct UcsXmlScript *script);\r
246 static ParseResult_t ParseAll(mxml_node_t *tree, UcsXmlVal_t *ucs, PrivateData_t *priv);\r
247 static ParseResult_t ParseNode(mxml_node_t * node, PrivateData_t *priv);\r
248 static ParseResult_t ParseConnection(mxml_node_t * node, const char *conType, PrivateData_t *priv);\r
249 static ParseResult_t ParseSocket(mxml_node_t *soc, bool isSource, MSocketType_t socketType, struct UcsXmlJobList **jobList, PrivateData_t *priv);\r
250 static ParseResult_t ParseScript(mxml_node_t *scr, PrivateData_t *priv);\r
251 static bool FillScriptInitialValues(Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
252 static ParseResult_t ParseScriptMsgSend(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
253 static ParseResult_t ParseScriptGpioPortCreate(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
254 static ParseResult_t ParseScriptGpioPinMode(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
255 static ParseResult_t ParseScriptGpioPinState(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
256 static ParseResult_t ParseScriptPortCreate(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
257 static ParseResult_t ParseScriptPortWrite(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
258 static ParseResult_t ParseScriptPortRead(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
259 static ParseResult_t ParseScriptPause(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);\r
260 static ParseResult_t ParseRoutes(UcsXmlVal_t *ucs, PrivateData_t *priv);\r
261 \r
262 /************************************************************************/\r
263 /* Public Functions                                                     */\r
264 /************************************************************************/\r
265 \r
266 UcsXmlVal_t *UcsXml_Parse(const char *xmlString)\r
267 {\r
268     UcsXmlVal_t *val = NULL;\r
269     ParseResult_t result = Parse_MemoryError;\r
270     mxml_node_t *tree;\r
271     if (!(tree = mxmlLoadString(NULL, xmlString, MXML_NO_CALLBACK))) goto ERROR;\r
272     if (!GetElement(tree, UNICENS, true, &tree, true)) goto ERROR;\r
273     /*Do not use MCalloc for the root element*/\r
274     val = calloc(1, sizeof(UcsXmlVal_t));\r
275     if (!val) goto ERROR;\r
276     val->pInternal = calloc(1, sizeof(PrivateData_t));\r
277     if (!val->pInternal) goto ERROR;\r
278     result = ParseAll(tree, val, val->pInternal);\r
279     if (Parse_Success == result)\r
280         return val;\r
281 ERROR:\r
282     if (Parse_MemoryError == result)\r
283         UcsXml_CB_OnError("XML memory error, aborting..", 0);\r
284     else\r
285         UcsXml_CB_OnError("XML parsing error, aborting..", 0);\r
286     assert(false);\r
287     if (!tree)\r
288         mxmlDelete(tree);\r
289     if (val)\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 CheckInteger(const char *value, bool forceHex)\r
424 {\r
425     bool hex = forceHex;\r
426     int32_t len;\r
427     if (!value) return false;\r
428     len = strlen(value);\r
429     if (len >= 3 && '0' == value[0] && 'x' == value[1])\r
430     {\r
431         hex = true;\r
432         value += 2;\r
433     }\r
434     while(value[0])\r
435     {\r
436         bool valid = false;\r
437         uint8_t v = value[0];\r
438         if (v >= '0' && v <= '9') valid = true;\r
439         if (hex)\r
440         {\r
441             if (v >= 'a' && v <= 'f') valid = true;\r
442             if (v >= 'A' && v <= 'F') valid = true;\r
443         }\r
444         if (!valid) return false;\r
445         ++value;\r
446     }\r
447     return true;\r
448 }\r
449 \r
450 static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory)\r
451 {\r
452     long int value;\r
453     const char* txt;\r
454     if (!GetString(element, key, &txt, mandatory)) return false;\r
455     if (!CheckInteger(txt, false))\r
456     {\r
457         UcsXml_CB_OnError("key='%s' contained invalid integer='%s'", 2, key, txt);\r
458         return false;\r
459     }\r
460     value = strtol( txt, NULL, 0 );\r
461     if (value > 0xFFFF)\r
462     {\r
463         UcsXml_CB_OnError("key='%s' is out of range='%d'", 2, key, value);\r
464         return false;\r
465     }\r
466     *out = value;\r
467     return true;\r
468 }\r
469 \r
470 static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory)\r
471 {\r
472     long int value;\r
473     const char* txt;\r
474     if (!GetString(element, key, &txt, mandatory)) return false;\r
475     if (!CheckInteger(txt, false))\r
476     {\r
477         UcsXml_CB_OnError("key='%s' contained invalid integer='%s'", 2, key, txt);\r
478         return false;\r
479     }\r
480     value = strtol( txt, NULL, 0 );\r
481     if (value > 0xFF)\r
482     {\r
483         UcsXml_CB_OnError("key='%s' is out of range='%d'", 2, key, value);\r
484         return false;\r
485     }\r
486     *out = value;\r
487     return true;\r
488 }\r
489 \r
490 static bool GetDataType(const char *txt, MDataType_t *out)\r
491 {\r
492     if (NULL == txt || NULL == out) return false;\r
493     if (0 == strcmp(SYNC_CONNECTION, txt)) {\r
494         *out = SYNC_DATA;\r
495     } else if (0 == strcmp(AVP_CONNECTION, txt)) {\r
496         *out = AV_PACKETIZED;\r
497     } else if (0 == strcmp(QOS_CONNECTION, txt)) {\r
498         *out = QOS_IP;\r
499     } else if (0 == strcmp(DFP_CONNECTION, txt)) {\r
500         *out = DISC_FRAME_PHASE;\r
501     } else if (0 == strcmp(IPC_CONNECTION, txt)) {\r
502         *out = IPC_PACKET;\r
503     } else {\r
504         UcsXml_CB_OnError("Unknown data type : '%s'", 1, txt);\r
505         return false;\r
506     }\r
507     return true;\r
508 }\r
509 \r
510 static bool GetSocketType(const char *txt, MSocketType_t *out)\r
511 {\r
512     if (0 == strcmp(txt, MOST_SOCKET)) {\r
513             *out = MSocket_MOST;\r
514     } else if (0 == strcmp(txt, USB_SOCKET)) {\r
515         *out = MSocket_USB;\r
516     } else if (0 == strcmp(txt, MLB_SOCKET)) {\r
517         *out = MSocket_MLB;\r
518     } else if (0 == strcmp(txt, STREAM_SOCKET)) {\r
519         *out = MSocket_STRM;\r
520     } else if (0 == strcmp(txt, SPLITTER)) {\r
521         *out = MSocket_SPLITTER;\r
522     } else if (0 == strcmp(txt, COMBINER)) {\r
523         *out = MSocket_COMBINER;\r
524     } else {\r
525         UcsXml_CB_OnError("Unknown port : '%s'", 1, txt);\r
526         return false;\r
527     }\r
528     return true;\r
529 }\r
530 \r
531 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
532 {\r
533     uint32_t tempLen, len = 0;\r
534     uint8_t *p;\r
535     const char *txt;\r
536     char *txtCopy;\r
537     char *tkPtr;\r
538     char *token;\r
539     if (!GetString(element, name, &txt, mandatory))\r
540         return false;\r
541     tempLen = strlen(txt) + 1;\r
542     txtCopy = malloc(tempLen);\r
543     if (NULL == txtCopy)\r
544         return false;\r
545     strncpy(txtCopy, txt, tempLen);\r
546     tempLen = tempLen / 3; /* 2 chars hex value plus space (AA )  */\r
547     p = MCalloc(obj, offset + tempLen, 1);\r
548     if (NULL == p)\r
549     {\r
550         free(txtCopy);\r
551         return false;\r
552     }\r
553     *pPayload = p;\r
554     token = strtok_r( txtCopy, " ,.-", &tkPtr );\r
555     while( NULL != token )\r
556     {\r
557         if( len >= tempLen )\r
558         {\r
559             UcsXml_CB_OnError("Script payload values must be stuffed to two characters", 0);\r
560             free(txtCopy);\r
561             assert(false);\r
562             return 0;\r
563         }\r
564         if (!CheckInteger(token, true))\r
565         {\r
566             UcsXml_CB_OnError("Script payload contains non valid hex number='%s'", 1, token);\r
567             free(txtCopy);\r
568             assert(false);\r
569             return 0;\r
570         }\r
571         p[offset + len++] = strtol( token, NULL, 16 );\r
572         token = strtok_r( NULL, " ,.-", &tkPtr );\r
573     }\r
574     *outLen = len;\r
575     return true;\r
576 }\r
577 \r
578 static bool AddJob(struct UcsXmlJobList **joblist, Ucs_Xrm_ResObject_t *job, struct UcsXmlObjectList *objList)\r
579 {\r
580     struct UcsXmlJobList *tail;\r
581     if (NULL == joblist || NULL == job)\r
582         return false;\r
583     assert(UCS_XRM_RC_TYPE_QOS_CON >= *((Ucs_Xrm_ResourceType_t *)job));\r
584     if (NULL == joblist[0])\r
585     {\r
586         joblist[0] = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));\r
587         if (NULL == joblist[0]) return false;;\r
588         joblist[0]->job = job;\r
589         return true;\r
590     }\r
591     tail = joblist[0];\r
592     while(tail->next) tail = tail->next;\r
593     tail->next = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));\r
594     if (NULL == tail->next) return false;\r
595     tail->next->job = job;\r
596     return true;\r
597 }\r
598 \r
599 static Ucs_Xrm_ResObject_t **GetJobList(struct UcsXmlJobList *joblist, struct UcsXmlObjectList *objList)\r
600 {\r
601     Ucs_Xrm_ResObject_t **outJob;\r
602     uint32_t count = 0;\r
603     struct UcsXmlJobList *tail;\r
604     if (NULL == joblist)\r
605         return false;\r
606     /*First: Get amount of stored jobs by enumerate all*/\r
607     tail = joblist;\r
608     while(tail)\r
609     {\r
610         ++count;\r
611         tail = tail->next;\r
612     }\r
613     if (0 == count)\r
614         return false;\r
615     /*Second: Allocate count+1 elements (NULL terminated) and copy pointers*/\r
616     outJob = MCalloc(objList, (count + 1), sizeof(Ucs_Xrm_ResObject_t *));\r
617     if (NULL == outJob)\r
618         return false;\r
619     tail = joblist;\r
620     count = 0;\r
621     while(tail)\r
622     {\r
623         outJob[count++] = tail->job;\r
624         tail = tail->next;\r
625     }\r
626     return outJob;\r
627 }\r
628 \r
629 static struct UcsXmlJobList *DeepCopyJobList(struct UcsXmlJobList *jobsIn, struct UcsXmlObjectList *objList)\r
630 {\r
631     struct UcsXmlJobList *jobsOut, *tail;\r
632     if (NULL == jobsIn || NULL == objList)\r
633         return NULL;\r
634     jobsOut = tail = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));\r
635     if (NULL == jobsOut) { assert(false); return NULL; }\r
636     while(jobsIn)\r
637     {\r
638         tail->job = jobsIn->job;\r
639         if (jobsIn->next)\r
640         {\r
641             tail->next = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));\r
642             if (NULL == tail->next) { assert(false); return NULL; }\r
643             tail = tail->next;\r
644         }\r
645         jobsIn = jobsIn->next;\r
646     }\r
647     return jobsOut;\r
648 }\r
649 \r
650 static void AddRoute(struct UcsXmlRoute **pRtLst, struct UcsXmlRoute *route)\r
651 {\r
652     struct UcsXmlRoute *tail;\r
653     if (NULL == pRtLst || NULL == route)\r
654     {\r
655         assert(false);\r
656         return;\r
657     }\r
658     if (NULL == pRtLst[0])\r
659     {\r
660         pRtLst[0] = route;\r
661         return;\r
662     }\r
663     tail = pRtLst[0];\r
664     while(tail->next) tail = tail->next;\r
665     tail->next = route;\r
666 }\r
667 \r
668 static void AddScript(struct UcsXmlScript **pScrLst, struct UcsXmlScript *script)\r
669 {\r
670     struct UcsXmlScript *tail;\r
671     if (NULL == pScrLst || NULL == script)\r
672     {\r
673         assert(false);\r
674         return;\r
675     }\r
676     if (NULL == pScrLst[0])\r
677     {\r
678         pScrLst[0] = script;\r
679         return;\r
680     }\r
681     tail = pScrLst[0];\r
682     while(tail->next) tail = tail->next;\r
683     tail->next = script;\r
684 }\r
685 \r
686 static ParseResult_t ParseAll(mxml_node_t *tree, UcsXmlVal_t *ucs, PrivateData_t *priv)\r
687 {\r
688     uint32_t nodeCount;\r
689     mxml_node_t *sub;\r
690     ParseResult_t result;\r
691     priv->autoRouteId = 0x8000;\r
692     if (!GetCount(tree, NODE, &nodeCount, true))\r
693         RETURN_ASSERT(Parse_XmlError);\r
694 \r
695     ucs->pNod = MCalloc(&priv->objList, nodeCount, sizeof(Ucs_Rm_Node_t));\r
696     if (NULL == ucs->pNod) RETURN_ASSERT(Parse_MemoryError);\r
697 \r
698     if (!GetUInt16(tree, PACKET_BW, &ucs->packetBw, true))\r
699         RETURN_ASSERT(Parse_XmlError);\r
700 \r
701     /*Iterate all nodes*/\r
702     if (!GetElement(tree, NODE, true, &sub, true))\r
703         RETURN_ASSERT(Parse_XmlError);\r
704     while(sub)\r
705     {\r
706         const char *conType;\r
707         mxml_node_t *con;\r
708         memset(&priv->nodeData, 0, sizeof(NodeData_t));\r
709         priv->nodeData.nod = &ucs->pNod[ucs->nodSize];\r
710         if (Parse_Success != (result = ParseNode(sub, priv)))\r
711             return result;\r
712         /*/Iterate all connections. Node without any connection is also valid.*/\r
713         if (GetElementArray(sub->child, ALL_CONNECTIONS, &conType, &con))\r
714         {\r
715             while(con)\r
716             {\r
717                 const char *socTypeStr;\r
718                 MSocketType_t socType;\r
719                 mxml_node_t *soc;\r
720                 memset(&priv->conData, 0, sizeof(ConnectionData_t));\r
721                 if (Parse_Success != (result = ParseConnection(con, conType, priv)))\r
722                     return result;\r
723                 /*Iterate all sockets*/\r
724                 if(!GetElementArray(con->child, ALL_SOCKETS, &socTypeStr, &soc)) RETURN_ASSERT(Parse_XmlError);\r
725                 while(soc)\r
726                 {\r
727                     if (!GetSocketType(socTypeStr, &socType)) RETURN_ASSERT(Parse_XmlError);\r
728                     if (Parse_Success != (result = ParseSocket(soc, (0 == priv->conData.sockCnt), socType, &priv->conData.jobList, priv)))\r
729                         return result;\r
730                     ++priv->conData.sockCnt;\r
731                     if(!GetElementArray(soc, ALL_SOCKETS, &socTypeStr, &soc))\r
732                         break;\r
733                 }\r
734                 if(!GetElementArray(con, ALL_CONNECTIONS, &conType, &con))\r
735                     break;\r
736             }\r
737         }\r
738         ++ucs->nodSize;\r
739         if (!GetElement(sub, NODE, false, &sub, false))\r
740             break;\r
741     }\r
742 \r
743     /*Fill route structures*/\r
744     result = ParseRoutes(ucs, priv);\r
745     if (Parse_MemoryError == result) RETURN_ASSERT(Parse_MemoryError)\r
746     else if (Parse_XmlError == result) RETURN_ASSERT(Parse_XmlError);\r
747 \r
748     /*Iterate all scripts. No scripts at all is allowed*/\r
749     if(GetElement(tree, SCRIPT, true, &sub, false))\r
750     {\r
751         bool found = true;\r
752         struct UcsXmlScript *scrlist = priv->pScrLst;\r
753         while(sub)\r
754         {\r
755             result = ParseScript(sub, priv);\r
756             if (Parse_MemoryError == result) RETURN_ASSERT(Parse_MemoryError)\r
757             else if (Parse_XmlError == result) RETURN_ASSERT(Parse_XmlError);\r
758             if(!GetElement(sub, SCRIPT, false, &sub, false))\r
759                 break;\r
760         }\r
761         /* Check if all scripts where referenced */\r
762         while(NULL != scrlist)\r
763         {\r
764             if (!scrlist->inUse)\r
765             {\r
766                 UcsXml_CB_OnError("Script not defined:'%s', used by node=0x%X", 1, scrlist->scriptName, scrlist->node->signature_ptr->node_address);\r
767                 found = false;\r
768             }\r
769             scrlist = scrlist->next;\r
770         }\r
771         if (!found)\r
772             RETURN_ASSERT(Parse_XmlError);\r
773     }\r
774     return result;\r
775 }\r
776 \r
777 static ParseResult_t ParseNode(mxml_node_t *node, PrivateData_t *priv)\r
778 {\r
779     const char *txt;\r
780     mxml_node_t *port;\r
781     Ucs_Signature_t *signature;\r
782     assert(NULL != node && NULL != priv);\r
783     priv->nodeData.nod->signature_ptr = MCalloc(&priv->objList, 1, sizeof(Ucs_Signature_t));\r
784     signature = priv->nodeData.nod->signature_ptr;\r
785     if(NULL == signature) RETURN_ASSERT(Parse_MemoryError);\r
786     if (!GetUInt16(node, ADDRESS, &signature->node_address, true))\r
787         RETURN_ASSERT(Parse_XmlError);\r
788     if (GetString(node, SCRIPT, &txt, false))\r
789     {\r
790         struct UcsXmlScript *scr = MCalloc(&priv->objList, 1, sizeof(struct UcsXmlScript));\r
791         if (NULL == scr) RETURN_ASSERT(Parse_MemoryError);\r
792         scr->node = priv->nodeData.nod;\r
793         strncpy(scr->scriptName, txt, sizeof(scr->scriptName));\r
794         AddScript(&priv->pScrLst, scr);\r
795     }\r
796     /*Iterate all ports*/\r
797     if(GetElementArray(node->child, ALL_PORTS, &txt, &port))\r
798     {\r
799         while(port)\r
800         {\r
801             if (0 == (strcmp(txt, MLB_PORT)))\r
802             {\r
803                 struct MlbPortParameters p;\r
804                 p.list = &priv->objList;\r
805                 if (!GetString(port, CLOCK_CONFIG, &p.clockConfig, true)) RETURN_ASSERT(Parse_XmlError);\r
806                 if (!GetMlbPort(&priv->nodeData.mlbPort, &p)) RETURN_ASSERT(Parse_XmlError);\r
807             }\r
808             else if (0 == (strcmp(txt, USB_PORT)))\r
809             {\r
810                 struct UsbPortParameters p;\r
811                 p.list = &priv->objList;\r
812                 if (!GetString(port, PHYSICAL_LAYER, &p.physicalLayer, true)) RETURN_ASSERT(Parse_XmlError);\r
813                 if (!GetString(port, DEVICE_INTERFACES, &p.deviceInterfaces, true)) RETURN_ASSERT(Parse_XmlError);\r
814                 if (!GetString(port, STRM_IN_COUNT, &p.streamInCount, true)) RETURN_ASSERT(Parse_XmlError);\r
815                 if (!GetString(port, STRM_OUT_COUNT, &p.streamOutCount, true)) RETURN_ASSERT(Parse_XmlError);\r
816                 if (!GetUsbPort(&priv->nodeData.usbPort, &p)) RETURN_ASSERT(Parse_XmlError);\r
817             }\r
818             else if (0 == (strcmp(txt, STRM_PORT)))\r
819             {\r
820                 struct StrmPortParameters p;\r
821                 p.list = &priv->objList;\r
822                 p.index = 0;\r
823                 if (!GetString(port, CLOCK_CONFIG, &p.clockConfig, true)) RETURN_ASSERT(Parse_XmlError);\r
824                 if (!GetString(port, STRM_ALIGN, &p.dataAlignment, true)) RETURN_ASSERT(Parse_XmlError);\r
825                 if (!GetStrmPort(&priv->nodeData.strmPortA, &p)) RETURN_ASSERT(Parse_XmlError);\r
826                 p.index = 1;\r
827                 if (!GetStrmPort(&priv->nodeData.strmPortB, &p)) RETURN_ASSERT(Parse_XmlError);\r
828             }\r
829             else\r
830             {\r
831                 UcsXml_CB_OnError("Unknown Port:'%s'", 1, txt);\r
832                 RETURN_ASSERT(Parse_XmlError);\r
833             }\r
834             if(!GetElementArray(port, ALL_PORTS, &txt, &port))\r
835                 break;\r
836         }\r
837     }\r
838     return Parse_Success;;\r
839 }\r
840 \r
841 static ParseResult_t ParseConnection(mxml_node_t * node, const char *conType, PrivateData_t *priv)\r
842 {\r
843     assert(NULL != node && NULL != priv);\r
844     if (NULL == conType) RETURN_ASSERT(Parse_XmlError);\r
845     if (!GetDataType(conType, &priv->conData.dataType)) RETURN_ASSERT(Parse_XmlError);\r
846     switch (priv->conData.dataType)\r
847     {\r
848     case SYNC_DATA:\r
849     {\r
850         const char *txt;\r
851         if (GetString(node, MUTE_MODE, &txt, false))\r
852         {\r
853             if (0 == strcmp(txt, MUTE_MODE_NO_MUTING))\r
854                 priv->conData.muteMode = UCS_SYNC_MUTE_MODE_NO_MUTING;\r
855             else if (0 == strcmp(txt, MUTE_MODE_MUTE_SIGNAL))\r
856                 priv->conData.muteMode = UCS_SYNC_MUTE_MODE_MUTE_SIGNAL;\r
857             else\r
858             {\r
859                 UcsXml_CB_OnError("ParseConnection: MuteMode='%s' not implemented", 1, txt);\r
860                 RETURN_ASSERT(Parse_XmlError);\r
861             }\r
862         }\r
863         else\r
864         {\r
865             /*Be tolerant, this is an optional feature*/\r
866             priv->conData.muteMode = UCS_SYNC_MUTE_MODE_NO_MUTING;\r
867         }\r
868         break;\r
869     }\r
870     case AV_PACKETIZED:\r
871     {\r
872         uint16_t size;\r
873         if (GetUInt16(node, AVP_PACKET_SIZE, &size, false))\r
874         {\r
875             switch(size)\r
876             {\r
877             case 188:\r
878                 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_188;\r
879                 break;\r
880             case 196:\r
881                 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_196;\r
882                 break;\r
883             case 206:\r
884                 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_206;\r
885                 break;\r
886             default:\r
887                 UcsXml_CB_OnError("ParseConnection: %s='%d' not implemented", 2, AVP_PACKET_SIZE, size);\r
888                 RETURN_ASSERT(Parse_XmlError);\r
889             }\r
890         }\r
891         else\r
892         {\r
893             /*Be tolerant, this is an optional feature*/\r
894             priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_188;\r
895         }\r
896         break;\r
897     }\r
898     default:\r
899         UcsXml_CB_OnError("ParseConnection: Datatype='%s' not implemented", 1, conType);\r
900         RETURN_ASSERT(Parse_XmlError);\r
901         break;\r
902     }\r
903     return Parse_Success;\r
904 }\r
905 \r
906 static ParseResult_t ParseSocket(mxml_node_t *soc, bool isSource, MSocketType_t socketType, struct UcsXmlJobList **jobList, PrivateData_t *priv)\r
907 {\r
908     Ucs_Xrm_ResObject_t **targetSock;\r
909     assert(NULL != soc && NULL != priv);\r
910     targetSock = isSource ? &priv->conData.inSocket : &priv->conData.outSocket;\r
911     switch(socketType)\r
912     {\r
913     case MSocket_MOST:\r
914     {\r
915         const char* txt;\r
916         struct MostSocketParameters p;\r
917         /* If there is an combiner stored, add it now into job list (right before MOST socket) */\r
918         if (priv->conData.combiner)\r
919             if (!AddJob(jobList, priv->conData.combiner, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
920 \r
921         p.list = &priv->objList;\r
922         p.isSource = isSource;\r
923         p.dataType = priv->conData.dataType;\r
924         if (!GetUInt16(soc, BANDWIDTH, &p.bandwidth, true)) RETURN_ASSERT(Parse_XmlError);\r
925         if (!GetString(soc, ROUTE, &priv->conData.routeName, true)) RETURN_ASSERT(Parse_XmlError);\r
926         if (GetString(soc, ROUTE_IS_ACTIVE, &txt, false))\r
927         {\r
928             if (0 == strcmp(txt, VALUE_TRUE) || 0 == strcmp(txt, VALUE_1))\r
929                 priv->conData.isDeactivated = false;\r
930             else if (0 == strcmp(txt, VALUE_FALSE) || 0 == strcmp(txt, VALUE_0))\r
931                 priv->conData.isDeactivated = true;\r
932             else RETURN_ASSERT(Parse_XmlError);\r
933         } else {\r
934             priv->conData.isDeactivated = false;\r
935         }\r
936         if (!GetUInt16(soc, ROUTE_ID, &priv->conData.routeId, false))\r
937             priv->conData.routeId = ++priv->autoRouteId;\r
938         if (priv->conData.syncOffsetNeeded)\r
939         {\r
940             if (!GetUInt16(soc, OFFSET, &priv->conData.syncOffset, true)) RETURN_ASSERT(Parse_XmlError);\r
941         }\r
942         if (!GetMostSocket((Ucs_Xrm_MostSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);\r
943         if (!AddJob(jobList, *targetSock, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
944         break;\r
945     }\r
946     case MSocket_USB:\r
947     {\r
948         struct UsbSocketParameters p;\r
949         p.list = &priv->objList;\r
950         p.isSource = isSource;\r
951         p.dataType = priv->conData.dataType;\r
952         if (priv->nodeData.usbPort)\r
953         {\r
954             p.usbPort = priv->nodeData.usbPort;\r
955         } else {\r
956             if (!GetUsbPortDefaultCreated(&p.usbPort, &priv->objList))\r
957                 RETURN_ASSERT(Parse_XmlError);\r
958             priv->nodeData.usbPort = (Ucs_Xrm_UsbPort_t *)p.usbPort;\r
959         }\r
960         if(!AddJob(jobList, p.usbPort, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
961         if (!GetString(soc, ENDPOINT_ADDRESS, &p.endpointAddress, true)) RETURN_ASSERT(Parse_XmlError);\r
962         if (!GetString(soc, FRAMES_PER_TRANSACTION, &p.framesPerTrans, true)) RETURN_ASSERT(Parse_XmlError);\r
963         if (!GetUsbSocket((Ucs_Xrm_UsbSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);\r
964         if (!AddJob(jobList, *targetSock, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
965         break;\r
966     }\r
967     case MSocket_MLB:\r
968     {\r
969         struct MlbSocketParameters p;\r
970         p.list = &priv->objList;\r
971         p.isSource = isSource;\r
972         p.dataType = priv->conData.dataType;\r
973         if (priv->nodeData.mlbPort)\r
974         {\r
975             p.mlbPort = priv->nodeData.mlbPort;\r
976         } else {\r
977             if (!GetMlbPortDefaultCreated(&p.mlbPort, &priv->objList))\r
978                 RETURN_ASSERT(Parse_XmlError);\r
979             priv->nodeData.mlbPort = (Ucs_Xrm_MlbPort_t *)p.mlbPort;\r
980         }\r
981         if (!AddJob(jobList, p.mlbPort, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
982         if (!GetUInt16(soc, BANDWIDTH, &p.bandwidth, true)) RETURN_ASSERT(Parse_XmlError);\r
983         if (!GetString(soc, CHANNEL_ADDRESS, &p.channelAddress, true)) RETURN_ASSERT(Parse_XmlError);\r
984         if (!GetMlbSocket((Ucs_Xrm_MlbSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);\r
985         if (!AddJob(jobList, *targetSock, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
986         break;\r
987     }\r
988     case MSocket_STRM:\r
989     {\r
990         struct StrmSocketParameters p;\r
991         p.list = &priv->objList;\r
992         p.isSource = isSource;\r
993         p.dataType = priv->conData.dataType;\r
994         p.streamPortA = priv->nodeData.strmPortA;\r
995         p.streamPortB = priv->nodeData.strmPortB;\r
996         if (!AddJob(jobList, p.streamPortA, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
997         if (!AddJob(jobList, p.streamPortB, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
998         if (!GetUInt16(soc, BANDWIDTH, &p.bandwidth, true)) RETURN_ASSERT(Parse_XmlError);\r
999         if (!GetString(soc, STRM_PIN, &p.streamPin, true)) RETURN_ASSERT(Parse_XmlError);\r
1000         if (!GetStrmSocket((Ucs_Xrm_StrmSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);\r
1001         if (!AddJob(jobList, *targetSock, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
1002         break;\r
1003     }\r
1004     case MSocket_SPLITTER:\r
1005     {\r
1006         mxml_node_t *mostSoc;\r
1007         struct SplitterParameters p;\r
1008         if (isSource)\r
1009         {\r
1010             UcsXml_CB_OnError("Splitter can not be used as input socket", 0);\r
1011             RETURN_ASSERT(Parse_XmlError);\r
1012         }\r
1013         p.list = &priv->objList;\r
1014         if (!GetUInt16(soc, BYTES_PER_FRAME, &p.bytesPerFrame, true)) RETURN_ASSERT(Parse_XmlError);\r
1015         /* Current input socket will be stored inside splitter\r
1016          * and splitter will become the new input socket */\r
1017         if (!(p.inSoc = priv->conData.inSocket)) RETURN_ASSERT(Parse_XmlError);\r
1018         if (!GetSplitter((Ucs_Xrm_Splitter_t **)&priv->conData.inSocket, &p)) RETURN_ASSERT(Parse_XmlError);\r
1019         if (!AddJob(jobList, priv->conData.inSocket, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
1020         if (!GetElement(soc->child, MOST_SOCKET, false, &mostSoc, true))\r
1021             RETURN_ASSERT(Parse_XmlError);\r
1022         priv->conData.syncOffsetNeeded = true;\r
1023 \r
1024         while(mostSoc)\r
1025         {\r
1026             struct UcsXmlJobList *jobListCopy = DeepCopyJobList(*jobList, &priv->objList);\r
1027             if (!ParseSocket(mostSoc, false, MSocket_MOST, &jobListCopy, priv)) RETURN_ASSERT(Parse_XmlError);\r
1028             if (!GetElement(mostSoc, MOST_SOCKET, false, &mostSoc, false))\r
1029                 return Parse_Success; /* Do not break here, otherwise an additional invalid route will be created */\r
1030         }\r
1031         break;\r
1032     }\r
1033     case MSocket_COMBINER:\r
1034     {\r
1035         struct CombinerParameters p;\r
1036         if (!isSource)\r
1037         {\r
1038             UcsXml_CB_OnError("Combiner can not be used as output socket", 0);\r
1039             RETURN_ASSERT(Parse_XmlError);\r
1040         }\r
1041         p.list = &priv->objList;\r
1042         if (!GetUInt16(soc, BYTES_PER_FRAME, &p.bytesPerFrame, true)) RETURN_ASSERT(Parse_XmlError);\r
1043         if (!GetCombiner(&priv->conData.combiner, &p)) RETURN_ASSERT(Parse_XmlError);\r
1044         priv->conData.syncOffsetNeeded = true;\r
1045         if (!GetElement(soc->child, MOST_SOCKET, false, &priv->conData.pendingCombinerMostSockets, true))\r
1046             RETURN_ASSERT(Parse_XmlError);\r
1047         break;\r
1048     }\r
1049     default:\r
1050         RETURN_ASSERT(Parse_XmlError);\r
1051     }\r
1052     /*Handle Pending Combiner Tasks*/\r
1053     if (NULL != priv->conData.outSocket && NULL != priv->conData.combiner &&\r
1054         NULL != priv->conData.pendingCombinerMostSockets)\r
1055     {\r
1056         mxml_node_t *tmp = priv->conData.pendingCombinerMostSockets;\r
1057         priv->conData.pendingCombinerMostSockets = NULL;\r
1058         /* Current output socket will be stored inside combiner\r
1059          * and combiner will become the new output socket */\r
1060         priv->conData.combiner->port_socket_obj_ptr = priv->conData.outSocket;\r
1061         priv->conData.outSocket = priv->conData.combiner;\r
1062         while(tmp)\r
1063         {\r
1064             struct UcsXmlJobList *jobListCopy = DeepCopyJobList(*jobList, &priv->objList);\r
1065             if (!ParseSocket(tmp, true, MSocket_MOST, &jobListCopy, priv)) RETURN_ASSERT(Parse_XmlError);\r
1066             if (!GetElement(tmp, MOST_SOCKET, false, &tmp, false))\r
1067                 return Parse_Success; /* Do not break here, otherwise an additional invalid route will be created */\r
1068         }\r
1069     }\r
1070     /*Connect in and out socket once they are created*/\r
1071     if (priv->conData.inSocket && priv->conData.outSocket)\r
1072     {\r
1073         bool mostIsInput;\r
1074         bool mostIsOutput;\r
1075         Ucs_Rm_EndPoint_t *ep;\r
1076         struct UcsXmlRoute *route;\r
1077         switch(priv->conData.dataType)\r
1078         {\r
1079         case SYNC_DATA:\r
1080         {\r
1081             Ucs_Xrm_SyncCon_t *con = MCalloc(&priv->objList, 1, sizeof(Ucs_Xrm_SyncCon_t));\r
1082             if (NULL == con) RETURN_ASSERT(Parse_MemoryError);\r
1083             if (!AddJob(jobList, con, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
1084             con->resource_type = UCS_XRM_RC_TYPE_SYNC_CON;\r
1085             con->socket_in_obj_ptr = priv->conData.inSocket;\r
1086             con->socket_out_obj_ptr = priv->conData.outSocket;\r
1087             con->mute_mode = priv->conData.muteMode;\r
1088             con->offset = priv->conData.syncOffset;\r
1089             break;\r
1090         }\r
1091         case AV_PACKETIZED:\r
1092         {\r
1093             Ucs_Xrm_AvpCon_t *con = MCalloc(&priv->objList, 1, sizeof(Ucs_Xrm_AvpCon_t));\r
1094             if (NULL == con) RETURN_ASSERT(Parse_MemoryError);\r
1095             if (!AddJob(jobList, con, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
1096             con->resource_type = UCS_XRM_RC_TYPE_AVP_CON;\r
1097             con->socket_in_obj_ptr = priv->conData.inSocket;\r
1098             con->socket_out_obj_ptr = priv->conData.outSocket;\r
1099             con->isoc_packet_size = priv->conData.isocPacketSize;\r
1100             break;\r
1101         }\r
1102         default:\r
1103             UcsXml_CB_OnError("Could not connect sockets, data type not implemented: %d", 1, priv->conData.dataType);\r
1104             RETURN_ASSERT(Parse_XmlError);\r
1105             break;\r
1106         }\r
1107         ep = MCalloc(&priv->objList, 1, sizeof(Ucs_Rm_EndPoint_t));\r
1108         if (NULL == ep) RETURN_ASSERT(Parse_MemoryError);\r
1109 \r
1110         mostIsInput = (UCS_XRM_RC_TYPE_MOST_SOCKET == *((Ucs_Xrm_ResourceType_t *)priv->conData.inSocket));\r
1111         mostIsOutput = (UCS_XRM_RC_TYPE_MOST_SOCKET == *((Ucs_Xrm_ResourceType_t *)priv->conData.outSocket));\r
1112         if (!mostIsInput && !mostIsOutput)\r
1113         {\r
1114             UcsXml_CB_OnError("At least one MOST socket required per connection", 0);\r
1115             RETURN_ASSERT(Parse_XmlError);\r
1116         }\r
1117         ep->endpoint_type = mostIsOutput ? UCS_RM_EP_SOURCE : UCS_RM_EP_SINK;\r
1118         ep->jobs_list_ptr = GetJobList(*jobList, &priv->objList);\r
1119         if(NULL == ep->jobs_list_ptr) RETURN_ASSERT(Parse_MemoryError);\r
1120         ep->node_obj_ptr = priv->nodeData.nod;\r
1121         route = MCalloc(&priv->objList, 1, sizeof(struct UcsXmlRoute));\r
1122         if (NULL == route) RETURN_ASSERT(Parse_MemoryError);\r
1123         route->isSource = mostIsOutput;\r
1124         route->isActive = !priv->conData.isDeactivated;\r
1125         route->routeId = priv->conData.routeId;\r
1126         route->ep = ep;\r
1127         assert(NULL != priv->conData.routeName);\r
1128         strncpy(route->routeName, priv->conData.routeName, sizeof(route->routeName));\r
1129         AddRoute(&priv->pRtLst, route);\r
1130     }\r
1131     return Parse_Success;\r
1132 }\r
1133 \r
1134 static ParseResult_t ParseScript(mxml_node_t *scr, PrivateData_t *priv)\r
1135 {\r
1136     bool found = false;\r
1137     mxml_node_t *act;\r
1138     uint32_t actCnt;\r
1139     uint32_t i = 0;\r
1140     const char *txt;\r
1141     struct UcsXmlScript *scrlist;\r
1142     Ucs_Ns_Script_t *script;\r
1143     assert(NULL != scr && NULL != priv);\r
1144     priv->scriptData.pause = 0;\r
1145     scrlist = priv->pScrLst;\r
1146     if (!GetCountArray(scr->child, ALL_SCRIPTS, &actCnt, false)) RETURN_ASSERT(Parse_XmlError);\r
1147     if (NULL == (script = MCalloc(&priv->objList, actCnt, sizeof(Ucs_Ns_Script_t))))\r
1148         RETURN_ASSERT(Parse_MemoryError);\r
1149     actCnt = 0;\r
1150     /*Iterate all actions*/\r
1151     if (!GetElementArray(scr->child, ALL_SCRIPTS, &txt, &act)) RETURN_ASSERT(Parse_XmlError);\r
1152     while(act)\r
1153     {\r
1154         if (0 == strcmp(txt, SCRIPT_MSG_SEND)) {\r
1155             ParseResult_t result = ParseScriptMsgSend(act, &script[i], priv);\r
1156             if (Parse_Success != result) return result;\r
1157             ++actCnt;\r
1158         } else if (0 == strcmp(txt, SCRIPT_GPIO_PORT_CREATE)) {\r
1159             ParseResult_t result = ParseScriptGpioPortCreate(act, &script[i], priv);\r
1160             if (Parse_Success != result) return result;\r
1161             ++actCnt;\r
1162         } else if (0 == strcmp(txt, SCRIPT_GPIO_PORT_PIN_MODE)) {\r
1163             ParseResult_t result = ParseScriptGpioPinMode(act, &script[i], priv);\r
1164             if (Parse_Success != result) return result;\r
1165             ++actCnt;\r
1166         } else if (0 == strcmp(txt, SCRIPT_GPIO_PIN_STATE)) {\r
1167             ParseResult_t result = ParseScriptGpioPinState(act, &script[i], priv);\r
1168             if (Parse_Success != result) return result;\r
1169             ++actCnt;\r
1170         } else if (0 == strcmp(txt, SCRIPT_I2C_PORT_CREATE)) {\r
1171             ParseResult_t result = ParseScriptPortCreate(act, &script[i], priv);\r
1172             if (Parse_Success != result) return result;\r
1173             ++actCnt;\r
1174         } else if (0 == strcmp(txt, SCRIPT_I2C_PORT_WRITE)) {\r
1175             ParseResult_t result = ParseScriptPortWrite(act, &script[i], priv);\r
1176             if (Parse_Success != result) return result;\r
1177             ++actCnt;\r
1178         } else if (0 == strcmp(txt, SCRIPT_I2C_PORT_READ)) {\r
1179             ParseResult_t result = ParseScriptPortRead(act, &script[i], priv);\r
1180             if (Parse_Success != result) return result;\r
1181             ++actCnt;\r
1182         } else if (0 == strcmp(txt, SCRIPT_PAUSE)) {\r
1183             ParseResult_t result = ParseScriptPause(act, &script[i], priv);\r
1184             if (Parse_Success != result) return result;\r
1185         } else {\r
1186             UcsXml_CB_OnError("Unknown script action:'%s'", 1, txt);\r
1187             RETURN_ASSERT(Parse_XmlError);\r
1188         }\r
1189         if (!GetElementArray(act, ALL_SCRIPTS, &txt, &act))\r
1190             break;\r
1191         ++i;\r
1192     }\r
1193     if (!GetString(scr, NAME, &txt, true))\r
1194         RETURN_ASSERT(Parse_XmlError);\r
1195     while(NULL != scrlist)\r
1196     {\r
1197         if (0 == strcmp(txt, scrlist->scriptName))\r
1198         {\r
1199             Ucs_Rm_Node_t *node = scrlist->node;\r
1200             node->script_list_ptr = script;\r
1201             node->script_list_size = actCnt;\r
1202             scrlist->inUse = true;\r
1203             found = true;\r
1204         }\r
1205         scrlist = scrlist->next;\r
1206     }\r
1207     if(!found)\r
1208     {\r
1209         UcsXml_CB_OnError("Script defined:'%s', which was never referenced", 1, txt);\r
1210         RETURN_ASSERT(Parse_XmlError);\r
1211     }\r
1212     return Parse_Success;\r
1213 }\r
1214 \r
1215 static bool FillScriptInitialValues(Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1216 {\r
1217     assert(NULL != scr && NULL != priv);\r
1218     scr->send_cmd = MCalloc(&priv->objList, 1, sizeof(Ucs_Ns_ConfigMsg_t));\r
1219     scr->exp_result = MCalloc(&priv->objList, 1, sizeof(Ucs_Ns_ConfigMsg_t));\r
1220     assert(scr->send_cmd && scr->exp_result);\r
1221     if (NULL == scr->send_cmd || NULL == scr->exp_result) return false;\r
1222     scr->pause = priv->scriptData.pause;\r
1223     priv->scriptData.pause = 0;\r
1224     return true;\r
1225 }\r
1226 \r
1227 static ParseResult_t ParseScriptMsgSend(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1228 {\r
1229     Ucs_Ns_ConfigMsg_t *req, *res;\r
1230     assert(NULL != act && NULL != scr && NULL != priv);\r
1231     if (!FillScriptInitialValues(scr, priv)) return Parse_MemoryError;\r
1232     req = scr->send_cmd;\r
1233     res = scr->exp_result;\r
1234     req->InstId = res->InstId = 1;\r
1235     if (!GetUInt8(act, FBLOCK_ID, &req->FBlockId, true))\r
1236         RETURN_ASSERT(Parse_XmlError);\r
1237 \r
1238     if (!GetUInt16(act, FUNCTION_ID, &req->FunktId, true))\r
1239         RETURN_ASSERT(Parse_XmlError);\r
1240 \r
1241     if (!GetUInt8(act, OP_TYPE_REQUEST, &req->OpCode, true))\r
1242         RETURN_ASSERT(Parse_XmlError);\r
1243 \r
1244     res->FBlockId = req->FBlockId;\r
1245     res->FunktId = req->FunktId;\r
1246 \r
1247     if (GetUInt8(act, OP_TYPE_RESPONSE, &res->OpCode, false))\r
1248         GetPayload(act, PAYLOAD_RES_HEX, &res->DataPtr, &res->DataLen, 0, &priv->objList, false);\r
1249 \r
1250     if (!GetPayload(act, PAYLOAD_REQ_HEX, &req->DataPtr, &req->DataLen, 0, &priv->objList, true))\r
1251         RETURN_ASSERT(Parse_XmlError);\r
1252     if (0 == req->DataLen || NULL == req->DataPtr)\r
1253         RETURN_ASSERT(Parse_XmlError);\r
1254     return Parse_Success;\r
1255 }\r
1256 \r
1257 static ParseResult_t ParseScriptGpioPortCreate(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1258 {\r
1259     uint16_t debounce;\r
1260     Ucs_Ns_ConfigMsg_t *req, *res;\r
1261     assert(NULL != act && NULL != scr && NULL != priv);\r
1262     if (!FillScriptInitialValues(scr, priv))\r
1263         RETURN_ASSERT(Parse_MemoryError);\r
1264     if (!GetUInt16(act, DEBOUNCE_TIME, &debounce, true))\r
1265         RETURN_ASSERT(Parse_XmlError);\r
1266     req = scr->send_cmd;\r
1267     res = scr->exp_result;\r
1268     req->InstId = res->InstId = 1;\r
1269     req->FunktId = res->FunktId = 0x701;\r
1270     req->OpCode = 0x2;\r
1271     res->OpCode = 0xC;\r
1272     req->DataLen = 3;\r
1273     res->DataLen = 2;\r
1274     req->DataPtr = MCalloc(&priv->objList, req->DataLen, 1);\r
1275     if (NULL == req->DataPtr) return Parse_MemoryError;\r
1276     res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);\r
1277     if (NULL == res->DataPtr) return Parse_MemoryError;\r
1278     req->DataPtr[0] = 0; /*GPIO Port instance, always 0*/\r
1279     req->DataPtr[1] = MISC_HB(debounce);\r
1280     req->DataPtr[2] = MISC_LB(debounce);\r
1281 \r
1282     res->DataPtr[0] = 0x1D;\r
1283     res->DataPtr[1] = 0x00;\r
1284     return Parse_Success;\r
1285 }\r
1286 \r
1287 static ParseResult_t ParseScriptGpioPinMode(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1288 {\r
1289 #define PORT_HANDLE_OFFSET (2)\r
1290     uint8_t *payload;\r
1291     uint8_t payloadLen = 0;\r
1292     Ucs_Ns_ConfigMsg_t *req, *res;\r
1293     assert(NULL != act && NULL != scr && NULL != priv);\r
1294     if (!FillScriptInitialValues(scr, priv))\r
1295         RETURN_ASSERT(Parse_MemoryError);\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 = 0x703;\r
1300     req->OpCode = 0x2;\r
1301     res->OpCode = 0xC;\r
1302     if (!GetPayload(act, PIN_CONFIG, &payload, &payloadLen,\r
1303         PORT_HANDLE_OFFSET, /* First two bytes are reserved for port handle */\r
1304         &priv->objList, true)) RETURN_ASSERT(Parse_XmlError);\r
1305     payload[0] = 0x1D;\r
1306     payload[1] = 0x00;\r
1307     req->DataPtr = payload;\r
1308     res->DataPtr = payload;\r
1309     req->DataLen = payloadLen + PORT_HANDLE_OFFSET;\r
1310     res->DataLen = payloadLen + PORT_HANDLE_OFFSET;\r
1311     return Parse_Success;\r
1312 }\r
1313 \r
1314 static ParseResult_t ParseScriptGpioPinState(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1315 {\r
1316     uint16_t mask, data;\r
1317     Ucs_Ns_ConfigMsg_t *req, *res;\r
1318     assert(NULL != act && NULL != scr && NULL != priv);\r
1319     if (!FillScriptInitialValues(scr, priv))\r
1320         RETURN_ASSERT(Parse_MemoryError);\r
1321     if (!GetUInt16(act, PIN_MASK, &mask, true))\r
1322         RETURN_ASSERT(Parse_XmlError);\r
1323     if (!GetUInt16(act, PIN_DATA, &data, true))\r
1324         RETURN_ASSERT(Parse_XmlError);\r
1325     req = scr->send_cmd;\r
1326     res = scr->exp_result;\r
1327     req->InstId = res->InstId = 1;\r
1328     req->FunktId = res->FunktId = 0x704;\r
1329     req->OpCode = 0x2;\r
1330     res->OpCode = 0xC;\r
1331     req->DataLen = 6;\r
1332     res->DataLen = 8;\r
1333     req->DataPtr = MCalloc(&priv->objList, req->DataLen, 1);\r
1334     if (NULL == req->DataPtr) return Parse_MemoryError;\r
1335     res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);\r
1336     if (NULL == res->DataPtr) return Parse_MemoryError;\r
1337     req->DataPtr[0] = 0x1D;\r
1338     req->DataPtr[1] = 0x00;\r
1339     req->DataPtr[2] = MISC_HB(mask);\r
1340     req->DataPtr[3] = MISC_LB(mask);\r
1341     req->DataPtr[4] = MISC_HB(data);\r
1342     req->DataPtr[5] = MISC_LB(data);\r
1343     memcpy(res->DataPtr, req->DataPtr, req->DataLen);\r
1344     res->DataPtr[6] = 0x00;\r
1345     res->DataPtr[7] = 0x00;\r
1346     return Parse_Success;\r
1347 }\r
1348 \r
1349 static ParseResult_t ParseScriptPortCreate(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1350 {\r
1351     const char *txt;\r
1352     uint8_t speed;\r
1353     Ucs_Ns_ConfigMsg_t *req, *res;\r
1354     assert(NULL != act && NULL != scr && NULL != priv);\r
1355     if (!FillScriptInitialValues(scr, priv))\r
1356         RETURN_ASSERT(Parse_MemoryError);\r
1357     if (!GetString(act, I2C_SPEED, &txt, true))\r
1358         RETURN_ASSERT(Parse_XmlError);\r
1359     if (0 == strcmp(txt, I2C_SPEED_SLOW))\r
1360         speed = 0;\r
1361     else if (0 == strcmp(txt, I2C_SPEED_FAST))\r
1362         speed = 1;\r
1363     else\r
1364     {\r
1365         UcsXml_CB_OnError("Invalid I2C speed:'%s'", 1, txt);\r
1366         RETURN_ASSERT(Parse_XmlError);\r
1367     }\r
1368     req = scr->send_cmd;\r
1369     res = scr->exp_result;\r
1370     req->InstId = res->InstId = 1;\r
1371     req->FunktId = res->FunktId = 0x6C1;\r
1372     req->OpCode = 0x2;\r
1373     res->OpCode = 0xC;\r
1374     req->DataLen = 4;\r
1375     res->DataLen = 2;\r
1376     req->DataPtr = MCalloc(&priv->objList, req->DataLen, 1);\r
1377     if (NULL == req->DataPtr) return Parse_MemoryError;\r
1378     res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);\r
1379     if (NULL == res->DataPtr) return Parse_MemoryError;\r
1380     req->DataPtr[0] = 0x00; /* I2C Port Instance always 0 */\r
1381     req->DataPtr[1] = 0x00; /* I2C slave address, always 0, because we are Master */\r
1382     req->DataPtr[2] = 0x01; /* We are Master */\r
1383     req->DataPtr[3] = speed;\r
1384 \r
1385     res->DataPtr[0] = 0x0F;\r
1386     res->DataPtr[1] = 0x00;\r
1387     return Parse_Success;\r
1388 }\r
1389 \r
1390 static ParseResult_t ParseScriptPortWrite(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1391 {\r
1392 #define HEADER_OFFSET 8\r
1393     const char *txt;\r
1394     uint8_t mode, blockCount, address, length, payloadLength;\r
1395     uint16_t timeout;\r
1396     uint8_t *payload;\r
1397     Ucs_Ns_ConfigMsg_t *req, *res;\r
1398     assert(NULL != act && NULL != scr && NULL != priv);\r
1399     if (GetString(act, I2C_WRITE_MODE, &txt, false))\r
1400     {\r
1401         if (0 == strcmp(txt, I2C_WRITE_MODE_DEFAULT))\r
1402             mode = 0;\r
1403         else if (0 == strcmp(txt, I2C_WRITE_MODE_REPEAT))\r
1404             mode = 1;\r
1405         else if (0 == strcmp(txt, I2C_WRITE_MODE_BURST))\r
1406             mode = 2;\r
1407         else\r
1408         {\r
1409             UcsXml_CB_OnError("Invalid I2C mode:'%s'", 1, txt);\r
1410             RETURN_ASSERT(Parse_XmlError);\r
1411         }\r
1412     } else {\r
1413         mode = 0;\r
1414     }\r
1415     if (!GetUInt8(act, I2C_WRITE_BLOCK_COUNT, &blockCount, false))\r
1416         blockCount = 0;\r
1417     if (!GetUInt8(act, I2C_SLAVE_ADDRESS, &address, true))\r
1418         RETURN_ASSERT(Parse_XmlError);\r
1419     if (!GetUInt8(act, I2C_PAYLOAD_LENGTH, &length, false))\r
1420         length = 0;\r
1421     if (!GetUInt16(act, I2C_TIMEOUT, &timeout, false))\r
1422         timeout = 100;\r
1423     if (!GetPayload(act, I2C_PAYLOAD, &payload, &payloadLength, HEADER_OFFSET, &priv->objList, true))\r
1424         RETURN_ASSERT(Parse_XmlError);\r
1425     if (0 == length)\r
1426         length = payloadLength;\r
1427     if (!FillScriptInitialValues(scr, priv))\r
1428         RETURN_ASSERT(Parse_MemoryError);\r
1429     req = scr->send_cmd;\r
1430     res = scr->exp_result;\r
1431     req->InstId = res->InstId = 1;\r
1432     req->FunktId = res->FunktId = 0x6C4;\r
1433     req->OpCode = 0x2;\r
1434     res->OpCode = 0xC;\r
1435     req->DataLen = payloadLength + HEADER_OFFSET;\r
1436     res->DataLen = 4;\r
1437     req->DataPtr = payload;\r
1438     res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);\r
1439     if (NULL == res->DataPtr) return Parse_MemoryError;\r
1440 \r
1441     req->DataPtr[0] = 0x0F;\r
1442     req->DataPtr[1] = 0x00;\r
1443     req->DataPtr[2] = mode;\r
1444     req->DataPtr[3] = blockCount;\r
1445     req->DataPtr[4] = address;\r
1446     req->DataPtr[5] = length;\r
1447     req->DataPtr[6] = MISC_HB(timeout);\r
1448     req->DataPtr[7] = MISC_LB(timeout);\r
1449 \r
1450     res->DataPtr[0] = 0x0F;\r
1451     res->DataPtr[1] = 0x00;\r
1452     res->DataPtr[2] = address;\r
1453     if (2 == mode)\r
1454         res->DataPtr[3] = blockCount * length;\r
1455     else\r
1456         res->DataPtr[3] = length;\r
1457     return Parse_Success;\r
1458 }\r
1459 \r
1460 static ParseResult_t ParseScriptPortRead(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1461 {\r
1462     uint8_t address, length;\r
1463     uint16_t timeout;\r
1464     Ucs_Ns_ConfigMsg_t *req, *res;\r
1465     assert(NULL != act && NULL != scr && NULL != priv);\r
1466     if (!GetUInt8(act, I2C_SLAVE_ADDRESS, &address, true))\r
1467         RETURN_ASSERT(Parse_XmlError);\r
1468     if (!GetUInt8(act, I2C_PAYLOAD_LENGTH, &length, true))\r
1469         RETURN_ASSERT(Parse_XmlError);\r
1470     if (!GetUInt16(act, I2C_TIMEOUT, &timeout, false))\r
1471         timeout = 100;\r
1472     if (!FillScriptInitialValues(scr, priv))\r
1473         RETURN_ASSERT(Parse_MemoryError);\r
1474     req = scr->send_cmd;\r
1475     res = scr->exp_result;\r
1476     req->InstId = res->InstId = 1;\r
1477     req->FunktId = res->FunktId = 0x6C3;\r
1478     req->OpCode = 0x2;\r
1479     res->OpCode = 0xC;\r
1480     req->DataLen = 6;\r
1481     res->DataLen = 4;\r
1482     req->DataPtr = MCalloc(&priv->objList, req->DataLen, 1);\r
1483     if (NULL == req->DataPtr) return Parse_MemoryError;\r
1484     res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);\r
1485     if (NULL == res->DataPtr) return Parse_MemoryError;\r
1486 \r
1487     req->DataPtr[0] = 0x0F;\r
1488     req->DataPtr[1] = 0x00;\r
1489     req->DataPtr[2] = address;\r
1490     req->DataPtr[3] = length;\r
1491     req->DataPtr[4] = MISC_HB(timeout);\r
1492     req->DataPtr[5] = MISC_LB(timeout);\r
1493 \r
1494     res->DataPtr[0] = 0x0F;\r
1495     res->DataPtr[1] = 0x00;\r
1496     res->DataPtr[2] = address;\r
1497     res->DataPtr[3] = length;\r
1498     return Parse_Success;\r
1499 }\r
1500 \r
1501 static ParseResult_t ParseScriptPause(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)\r
1502 {\r
1503     assert(NULL != act && NULL != priv);\r
1504     if (!GetUInt16(act, PAUSE_MS, &priv->scriptData.pause, true))\r
1505             RETURN_ASSERT(Parse_XmlError);\r
1506     return Parse_Success;\r
1507 }\r
1508 \r
1509 static ParseResult_t ParseRoutes(UcsXmlVal_t *ucs, PrivateData_t *priv)\r
1510 {\r
1511     uint16_t routeAmount = 0;\r
1512     struct UcsXmlRoute *sourceRoute;\r
1513     assert(NULL != ucs && NULL != priv);\r
1514     /*First: Count the amount of routes and allocate the correct amount*/\r
1515     sourceRoute = priv->pRtLst;\r
1516     while (NULL != sourceRoute)\r
1517     {\r
1518         if (!sourceRoute->isSource) /*There can be more sinks than sources, so count them*/\r
1519         {\r
1520             ++routeAmount;\r
1521         }\r
1522         sourceRoute = sourceRoute->next;\r
1523     }\r
1524     if (0 == routeAmount)\r
1525         return Parse_Success; /*Its okay to have no routes at all (e.g. MEP traffic only)*/\r
1526     ucs->pRoutes = MCalloc(&priv->objList, routeAmount, sizeof(Ucs_Rm_Route_t));\r
1527     if (NULL == ucs->pRoutes) RETURN_ASSERT(Parse_MemoryError);\r
1528 \r
1529     /*Second: Fill allocated structure now*/\r
1530     sourceRoute = priv->pRtLst;\r
1531     while (NULL != sourceRoute)\r
1532     {\r
1533         if (sourceRoute->isSource)\r
1534         {\r
1535             struct UcsXmlRoute *sinkRoute = priv->pRtLst;\r
1536             while (NULL != sinkRoute)\r
1537             {\r
1538                 if (sourceRoute != sinkRoute\r
1539                     && !sinkRoute->isSource\r
1540                     && (0 == strncmp(sourceRoute->routeName, sinkRoute->routeName, sizeof(sourceRoute->routeName))))\r
1541                 {\r
1542                     Ucs_Rm_Route_t *route = &ucs->pRoutes[ucs->routesSize++];\r
1543                     route->source_endpoint_ptr = sourceRoute->ep;\r
1544                     route->sink_endpoint_ptr = sinkRoute->ep;\r
1545                     route->active = sinkRoute->isActive;\r
1546                     route->route_id = sinkRoute->routeId;\r
1547                 }\r
1548                 sinkRoute = sinkRoute->next;\r
1549             }\r
1550         }\r
1551         sourceRoute = sourceRoute->next;\r
1552     }\r
1553     if (routeAmount != ucs->routesSize)\r
1554     {\r
1555         UcsXml_CB_OnError("At least one sink (num=%d) is not connected, because of wrong Route name!", 2, (routeAmount - ucs->routesSize));\r
1556         RETURN_ASSERT(Parse_XmlError);\r
1557     }\r
1558 \r
1559 #ifdef DEBUG\r
1560     /* Third perform checks when running in debug mode*/\r
1561     {\r
1562         Ucs_Xrm_ResourceType_t *job;\r
1563         uint16_t i, j;\r
1564         for (i = 0; i < routeAmount; i++)\r
1565         {\r
1566             Ucs_Rm_Route_t *route = &ucs->pRoutes[i];\r
1567             assert(NULL != route->source_endpoint_ptr);\r
1568             assert(NULL != route->sink_endpoint_ptr);\r
1569             assert(NULL != route->source_endpoint_ptr->jobs_list_ptr);\r
1570             assert(UCS_RM_EP_SOURCE == route->source_endpoint_ptr->endpoint_type);\r
1571             assert(UCS_RM_EP_SINK == route->sink_endpoint_ptr->endpoint_type);\r
1572             assert(NULL != route->source_endpoint_ptr->node_obj_ptr);\r
1573             assert(NULL != route->sink_endpoint_ptr->node_obj_ptr);\r
1574             assert(NULL != route->source_endpoint_ptr->node_obj_ptr->signature_ptr);\r
1575             assert(NULL != route->sink_endpoint_ptr->node_obj_ptr->signature_ptr);\r
1576             j = 0;\r
1577             while((job = ((Ucs_Xrm_ResourceType_t *)route->source_endpoint_ptr->jobs_list_ptr[j])))\r
1578             {\r
1579                 assert(UCS_XRM_RC_TYPE_QOS_CON >= *job);\r
1580                 ++j;\r
1581             }\r
1582             j = 0;\r
1583             while((job = ((Ucs_Xrm_ResourceType_t *)route->sink_endpoint_ptr->jobs_list_ptr[j])))\r
1584             {\r
1585                 assert(UCS_XRM_RC_TYPE_QOS_CON >= *job);\r
1586                 ++j;\r
1587             }\r
1588         }\r
1589     }\r
1590 #endif\r
1591     return Parse_Success;\r
1592 }\r