1 /*------------------------------------------------------------------------------------------------*/
2 /* UNICENS XML Parser */
3 /* Copyright 2017, Microchip Technology Inc. and its subsidiaries. */
5 /* Redistribution and use in source and binary forms, with or without */
6 /* modification, are permitted provided that the following conditions are met: */
8 /* 1. Redistributions of source code must retain the above copyright notice, this */
9 /* list of conditions and the following disclaimer. */
11 /* 2. Redistributions in binary form must reproduce the above copyright notice, */
12 /* this list of conditions and the following disclaimer in the documentation */
13 /* and/or other materials provided with the distribution. */
15 /* 3. Neither the name of the copyright holder nor the names of its */
16 /* contributors may be used to endorse or promote products derived from */
17 /* this software without specific prior written permission. */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" */
20 /* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */
21 /* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE */
23 /* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL */
24 /* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR */
25 /* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */
26 /* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, */
27 /* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
28 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /*------------------------------------------------------------------------------------------------*/
32 #include <libxml/tree.h>
33 #include <libxml/parser.h>
34 #include "UcsXml_Private.h"
37 /************************************************************************/
38 /* PRIVATE DECLARATIONS */
39 /************************************************************************/
41 #define COMPILETIME_CHECK(cond) (void)sizeof(int[2 * !!(cond) - 1])
42 #define RETURN_ASSERT(result) { UcsXml_CB_OnError("Assertion in file=%s, line=%d", 2, __FILE__, __LINE__); return result; }
43 #define MISC_HB(value) ((uint8_t)((uint16_t)(value) >> 8))
44 #define MISC_LB(value) ((uint8_t)((uint16_t)(value) & (uint16_t)0xFF))
45 #define ROUTE_AUTO_ID_START (0x8000)
53 Ucs_Rm_EndPoint_t *ep;
54 struct UcsXmlRoute *next;
62 struct UcsXmlScript *next;
67 Ucs_Xrm_ResObject_t *job;
68 struct UcsXmlJobList *next;
91 Ucs_Xrm_UsbPort_t *usbPort;
92 Ucs_Xrm_MlbPort_t *mlbPort;
93 Ucs_Xrm_StrmPort_t *strmPortA;
94 Ucs_Xrm_StrmPort_t *strmPortB;
101 bool syncOffsetNeeded;
105 const char *routeName;
106 Ucs_Xrm_ResObject_t *inSocket;
107 Ucs_Xrm_ResObject_t *outSocket;
108 struct UcsXmlJobList *jobList;
109 Ucs_Xrm_Combiner_t *combiner;
110 xmlNode *pendingCombinerMostSockets;
111 Ucs_Sync_MuteMode_t muteMode;
112 Ucs_Avp_IsocPacketSize_t isocPacketSize;
122 uint16_t autoRouteId;
123 struct UcsXmlObjectList objList;
124 struct UcsXmlRoute *pRtLst;
125 struct UcsXmlScript *pScrLst;
127 ConnectionData_t conData;
128 ScriptData_t scriptData;
131 /************************************************************************/
133 /************************************************************************/
136 static const char* UNICENS = "Unicens";
137 static const char* PACKET_BW = "AsyncBandwidth";
138 static const char* NAME = "Name";
139 static const char* ROUTE = "Route";
140 static const char* ROUTE_ID = "RouteId";
141 static const char* ROUTE_IS_ACTIVE = "IsActive";
142 static const char* ENDPOINT_ADDRESS = "EndpointAddress";
143 static const char* CHANNEL_ADDRESS = "ChannelAddress";
144 static const char* BANDWIDTH = "Bandwidth";
145 static const char* BYTES_PER_FRAME = "BytesPerFrame";
146 static const char* OFFSET = "Offset";
147 static const char* NODE = "Node";
148 static const char* CLOCK_CONFIG = "ClockConfig";
149 static const char* ADDRESS = "Address";
150 static const char* FRAMES_PER_TRANSACTION = "FramesPerTransaction";
151 static const char* MUTE_MODE = "MuteMode";
152 static const char* MUTE_MODE_NO_MUTING = "NoMuting";
153 static const char* MUTE_MODE_MUTE_SIGNAL = "MuteSignal";
154 static const char* AVP_PACKET_SIZE = "IsocPacketSize";
155 #define SYNC_CONNECTION "SyncConnection"
156 #define AVP_CONNECTION "AVPConnection"
157 #define DFP_CONNECTION "DFPhaseConnection"
158 #define QOS_CONNECTION "QoSConnection"
159 #define IPC_CONNECTION "IPCConnection"
161 static const char* ALL_CONNECTIONS[] = { SYNC_CONNECTION, AVP_CONNECTION,
162 DFP_CONNECTION, QOS_CONNECTION, IPC_CONNECTION, NULL };
164 #define MOST_SOCKET "MOSTSocket"
165 #define USB_SOCKET "USBSocket"
166 #define MLB_SOCKET "MediaLBSocket"
167 #define STREAM_SOCKET "StreamSocket"
168 #define SPLITTER "Splitter"
169 #define COMBINER "Combiner"
170 static const char* ALL_SOCKETS[] = { MOST_SOCKET, USB_SOCKET, MLB_SOCKET,
171 STREAM_SOCKET, SPLITTER, COMBINER, NULL };
173 #define MLB_PORT "MediaLBPort"
174 #define USB_PORT "USBPort"
175 #define STRM_PORT "StreamPort"
176 static const char* ALL_PORTS[] = { MLB_PORT, USB_PORT, STRM_PORT, NULL };
178 static const char* PHYSICAL_LAYER = "PhysicalLayer";
179 static const char* DEVICE_INTERFACES = "DeviceInterfaces";
180 static const char* STRM_IN_COUNT = "StreamingIfEpInCount";
181 static const char* STRM_OUT_COUNT = "StreamingIfEpOutCount";
183 static const char* STRM_PIN = "StreamPinID";
184 static const char* STRM_ALIGN = "DataAlignment";
186 static const char* SCRIPT = "Script";
187 static const char* FBLOCK_ID = "FBlockId";
188 static const char* FUNCTION_ID = "FunctionId";
189 static const char* OP_TYPE_REQUEST = "OpTypeRequest";
190 static const char* OP_TYPE_RESPONSE = "OpTypeResponse";
191 static const char* PAYLOAD_REQ_HEX = "PayloadRequest";
192 static const char* PAYLOAD_RES_HEX = "PayloadResponse";
193 static const char* PAUSE_MS = "WaitTime";
194 static const char* DEBOUNCE_TIME = "DebounceTime";
195 static const char* PIN_CONFIG = "PinConfiguration";
196 static const char* PIN_MASK = "Mask";
197 static const char* PIN_DATA = "Data";
198 static const char* I2C_SPEED = "Speed";
199 static const char* I2C_SPEED_SLOW = "SlowMode";
200 static const char* I2C_SPEED_FAST = "FastMode";
201 static const char* I2C_WRITE_MODE = "Mode";
202 static const char* I2C_WRITE_MODE_DEFAULT = "DefaultMode";
203 static const char* I2C_WRITE_MODE_REPEAT = "RepeatedStartMode";
204 static const char* I2C_WRITE_MODE_BURST = "BurstMode";
205 static const char* I2C_WRITE_BLOCK_COUNT = "BlockCount";
206 static const char* I2C_SLAVE_ADDRESS = "Address";
207 static const char* I2C_PAYLOAD_LENGTH = "Length";
208 static const char* I2C_PAYLOAD = "Payload";
209 static const char* I2C_TIMEOUT = "Timeout";
211 #define SCRIPT_MSG_SEND "MsgSend"
212 #define SCRIPT_PAUSE "Pause"
213 #define SCRIPT_GPIO_PORT_CREATE "GPIOPortCreate"
214 #define SCRIPT_GPIO_PORT_PIN_MODE "GPIOPortPinMode"
215 #define SCRIPT_GPIO_PIN_STATE "GPIOPinState"
216 #define SCRIPT_I2C_PORT_CREATE "I2CPortCreate"
217 #define SCRIPT_I2C_PORT_WRITE "I2CPortWrite"
218 #define SCRIPT_I2C_PORT_READ "I2CPortRead"
219 static const char* ALL_SCRIPTS[] = { SCRIPT_MSG_SEND, SCRIPT_PAUSE,
220 SCRIPT_GPIO_PORT_CREATE, SCRIPT_GPIO_PORT_PIN_MODE, SCRIPT_GPIO_PIN_STATE,
221 SCRIPT_I2C_PORT_CREATE, SCRIPT_I2C_PORT_WRITE, SCRIPT_I2C_PORT_READ, NULL };
223 static const char* VALUE_TRUE = "true";
224 static const char* VALUE_FALSE = "false";
225 static const char* VALUE_1 = "1";
226 static const char* VALUE_0 = "0";
228 /************************************************************************/
229 /* Private Function Prototypes */
230 /************************************************************************/
232 static void FreeVal(UcsXmlVal_t *ucs);
233 static bool GetElement(xmlNode *element, const char *name, bool goDeep, xmlNode **out, bool mandatory);
234 static bool GetElementArray(xmlNode *element, const char *array[], const char **foundName, xmlNode **out);
235 static bool GetCount(xmlNode *element, const char *name, uint32_t *out, bool mandatory);
236 static bool GetCountArray(xmlNode *element, const char *array[], uint32_t *out, bool mandatory);
237 static bool GetString(xmlNode *element, const char *key, const char **out, bool mandatory);
238 static bool CheckInteger(const char *val, bool forceHex);
239 static bool GetUInt16(xmlNode *element, const char *key, uint16_t *out, bool mandatory);
240 static bool GetUInt8(xmlNode *element, const char *key, uint8_t *out, bool mandatory);
241 static bool GetSocketType(const char *txt, MSocketType_t *out);
242 static bool GetPayload(xmlNode *element, const char *name, uint8_t **pPayload, uint8_t *len, uint8_t offset,
243 struct UcsXmlObjectList *obj, bool mandatory);
244 static bool AddJob(struct UcsXmlJobList **joblist, Ucs_Xrm_ResObject_t *job, struct UcsXmlObjectList *objList);
245 static Ucs_Xrm_ResObject_t **GetJobList(struct UcsXmlJobList *joblist, struct UcsXmlObjectList *objList);
246 static struct UcsXmlJobList *DeepCopyJobList(struct UcsXmlJobList *jobsIn, struct UcsXmlObjectList *objList);
247 static void AddRoute(struct UcsXmlRoute **pRtLst, struct UcsXmlRoute *route);
248 static void AddScript(struct UcsXmlScript **pScrLst, struct UcsXmlScript *script);
249 static ParseResult_t ParseAll(xmlNode * node, UcsXmlVal_t *ucs, PrivateData_t *priv);
250 static ParseResult_t ParseNode(xmlNode * node, PrivateData_t *priv);
251 static ParseResult_t ParseConnection(xmlNode * node, const char *conType, PrivateData_t *priv);
252 static ParseResult_t ParseSocket(xmlNode *soc, bool isSource, MSocketType_t socketType, struct UcsXmlJobList **jobList, PrivateData_t *priv);
253 static ParseResult_t ParseScript(xmlNode *scr, PrivateData_t *priv);
254 static bool FillScriptInitialValues(Ucs_Ns_Script_t *scr, PrivateData_t *priv);
255 static ParseResult_t ParseScriptMsgSend(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);
256 static ParseResult_t ParseScriptGpioPortCreate(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);
257 static ParseResult_t ParseScriptGpioPinMode(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);
258 static ParseResult_t ParseScriptGpioPinState(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);
259 static ParseResult_t ParseScriptPortCreate(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);
260 static ParseResult_t ParseScriptPortWrite(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);
261 static ParseResult_t ParseScriptPortRead(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);
262 static ParseResult_t ParseScriptPause(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv);
263 static ParseResult_t ParseRoutes(UcsXmlVal_t *ucs, PrivateData_t *priv);
264 static bool IsAutoRouteId(uint16_t id, PrivateData_t *priv);
266 /************************************************************************/
267 /* Public Functions */
268 /************************************************************************/
270 UcsXmlVal_t *UcsXml_Parse(const char *xmlString)
273 UcsXmlVal_t *val = NULL;
274 ParseResult_t result = Parse_MemoryError;
276 if (NULL == (root = xmlReadMemory( xmlString, strlen( xmlString ), "config.xml", NULL, 0 ))) goto ERROR;
277 tree = xmlDocGetRootElement(root);
278 if (0 != strcmp(UNICENS, (const char *)tree->name)) goto ERROR;
279 /*Do not use MCalloc for the root element*/
280 val = calloc(1, sizeof(UcsXmlVal_t));
281 if (!val) goto ERROR;
282 val->pInternal = calloc(1, sizeof(PrivateData_t));
283 if (!val->pInternal) goto ERROR;
284 ((PrivateData_t *)val->pInternal)->root = root;
285 result = ParseAll(tree, val, val->pInternal);
286 if (Parse_Success == result)
289 if (Parse_MemoryError == result)
290 UcsXml_CB_OnError("XML memory error, aborting..", 0);
292 UcsXml_CB_OnError("XML parsing error, aborting..", 0);
301 void UcsXml_FreeVal(UcsXmlVal_t *val)
306 /************************************************************************/
307 /* Private Function Implementations */
308 /************************************************************************/
310 void FreeVal(UcsXmlVal_t *ucs)
313 if (NULL == ucs || NULL == ucs->pInternal)
315 priv = ucs->pInternal;
316 FreeObjList(&priv->objList);
319 xmlFreeDoc(priv->root);
321 free(ucs->pInternal);
325 static bool GetElement(xmlNode *element, const char *name, bool goDeep, xmlNode **out, bool mandatory)
327 xmlNode *n = element;
328 if (NULL == n || NULL == name || NULL == out) return false;
329 if (goDeep && GetElement(n->children, name, goDeep, out, false))
333 while ((n = n->next))
335 if (XML_ELEMENT_NODE != n->type)
337 if (0 == strcmp(name, (const char *)n->name))
342 else if (goDeep && GetElement(n->children, name, goDeep, out, false))
348 UcsXml_CB_OnError("Can not find tag <%s>", 1, name);
352 static bool GetElementArray(xmlNode *element, const char *array[], const char **foundName, xmlNode **out)
354 xmlNode *n = element;
355 if (NULL == n || NULL == array || NULL == foundName || NULL == out) return false;
356 while ((n = n->next))
359 for (i = 0; NULL != array[i]; i++)
361 if (0 == strcmp(array[i], (const char *)n->name))
363 *foundName = array[i];
372 static bool GetCount(xmlNode *element, const char *name, uint32_t *out, bool mandatory)
376 if (NULL == element || NULL == name) return false;
377 if(!GetElement(element, name, true, &n, false))
382 if(!GetElement(n, name, false, &n, false))
385 if (mandatory && 0 == cnt)
387 UcsXml_CB_OnError("element count of <%s> is zero", 1, name);
394 static bool GetCountArray(xmlNode *element, const char *array[], uint32_t *out, bool mandatory)
399 if (NULL == element || NULL == array) return false;
403 if(!GetElementArray(n, array, &tmp, &n))
407 if (mandatory && 0 == cnt)
409 UcsXml_CB_OnError("element count is zero, searched with string array", 0);
416 static bool GetString(xmlNode *element, const char *key, const char **out, bool mandatory)
418 struct _xmlAttr *curAttr;
419 if (NULL == element || NULL == key) return false;
420 curAttr = element->properties;
423 if (XML_ATTRIBUTE_NODE != curAttr->type)
425 if (0 == strcmp(key, (const char *)curAttr->name))
427 struct _xmlNode *valAttr = curAttr->children;
430 if (XML_TEXT_NODE != valAttr->type)
432 *out = (const char *)valAttr->content;
435 while (NULL != (valAttr = valAttr->next));
438 while (NULL != (curAttr = curAttr->next));
440 UcsXml_CB_OnError("Can not find attribute='%s' from element <%s>",
441 2, key, element->name);
445 static bool CheckInteger(const char *value, bool forceHex)
449 if (!value) return false;
451 if (len >= 3 && '0' == value[0] && 'x' == value[1])
459 uint8_t v = value[0];
460 if (v >= '0' && v <= '9') valid = true;
463 if (v >= 'a' && v <= 'f') valid = true;
464 if (v >= 'A' && v <= 'F') valid = true;
466 if (!valid) return false;
472 static bool GetUInt16(xmlNode *element, const char *key, uint16_t *out, bool mandatory)
476 if (!GetString(element, key, &txt, mandatory)) return false;
477 if (!CheckInteger(txt, false))
479 UcsXml_CB_OnError("key='%s' contained invalid integer='%s'", 2, key, txt);
482 value = strtol( txt, NULL, 0 );
485 UcsXml_CB_OnError("key='%s' is out of range='%d'", 2, key, value);
492 static bool GetUInt8(xmlNode *element, const char *key, uint8_t *out, bool mandatory)
496 if (!GetString(element, key, &txt, mandatory)) return false;
497 if (!CheckInteger(txt, false))
499 UcsXml_CB_OnError("key='%s' contained invalid integer='%s'", 2, key, txt);
502 value = strtol( txt, NULL, 0 );
505 UcsXml_CB_OnError("key='%s' is out of range='%d'", 2, key, value);
512 static bool GetDataType(const char *txt, MDataType_t *out)
514 if (NULL == txt || NULL == out) return false;
515 if (0 == strcmp(SYNC_CONNECTION, txt)) {
517 } else if (0 == strcmp(AVP_CONNECTION, txt)) {
518 *out = AV_PACKETIZED;
519 } else if (0 == strcmp(QOS_CONNECTION, txt)) {
521 } else if (0 == strcmp(DFP_CONNECTION, txt)) {
522 *out = DISC_FRAME_PHASE;
523 } else if (0 == strcmp(IPC_CONNECTION, txt)) {
526 UcsXml_CB_OnError("Unknown data type : '%s'", 1, txt);
532 static bool GetSocketType(const char *txt, MSocketType_t *out)
534 if (0 == strcmp(txt, MOST_SOCKET)) {
536 } else if (0 == strcmp(txt, USB_SOCKET)) {
538 } else if (0 == strcmp(txt, MLB_SOCKET)) {
540 } else if (0 == strcmp(txt, STREAM_SOCKET)) {
542 } else if (0 == strcmp(txt, SPLITTER)) {
543 *out = MSocket_SPLITTER;
544 } else if (0 == strcmp(txt, COMBINER)) {
545 *out = MSocket_COMBINER;
547 UcsXml_CB_OnError("Unknown port : '%s'", 1, txt);
553 static bool GetPayload(xmlNode *element, const char *name, uint8_t **pPayload, uint8_t *outLen, uint8_t offset, struct UcsXmlObjectList *obj, bool mandatory)
555 uint32_t tempLen, len = 0;
561 if (!GetString(element, name, &txt, mandatory))
563 tempLen = strlen(txt) + 1;
564 txtCopy = malloc(tempLen);
567 strncpy(txtCopy, txt, tempLen);
568 tempLen = tempLen / 3; /* 2 chars hex value plus space (AA ) */
569 p = MCalloc(obj, offset + tempLen, 1);
576 token = strtok_r( txtCopy, " ,.-", &tkPtr );
577 while( NULL != token )
581 UcsXml_CB_OnError("Script payload values must be stuffed to two characters", 0);
586 if (!CheckInteger(token, true))
588 UcsXml_CB_OnError("Script payload contains non valid hex number='%s'", 1, token);
593 p[offset + len++] = strtol( token, NULL, 16 );
594 token = strtok_r( NULL, " ,.-", &tkPtr );
600 static bool AddJob(struct UcsXmlJobList **joblist, Ucs_Xrm_ResObject_t *job, struct UcsXmlObjectList *objList)
602 struct UcsXmlJobList *tail;
603 if (NULL == joblist || NULL == job)
605 assert(UCS_XRM_RC_TYPE_QOS_CON >= *((Ucs_Xrm_ResourceType_t *)job));
606 if (NULL == joblist[0])
608 joblist[0] = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));
609 if (NULL == joblist[0]) return false;;
610 joblist[0]->job = job;
614 while(tail->next) tail = tail->next;
615 tail->next = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));
616 if (NULL == tail->next) return false;
617 tail->next->job = job;
621 static Ucs_Xrm_ResObject_t **GetJobList(struct UcsXmlJobList *joblist, struct UcsXmlObjectList *objList)
623 Ucs_Xrm_ResObject_t **outJob;
625 struct UcsXmlJobList *tail;
628 /*First: Get amount of stored jobs by enumerate all*/
637 /*Second: Allocate count+1 elements (NULL terminated) and copy pointers*/
638 outJob = MCalloc(objList, (count + 1), sizeof(Ucs_Xrm_ResObject_t *));
645 outJob[count++] = tail->job;
651 static struct UcsXmlJobList *DeepCopyJobList(struct UcsXmlJobList *jobsIn, struct UcsXmlObjectList *objList)
653 struct UcsXmlJobList *jobsOut, *tail;
654 if (NULL == jobsIn || NULL == objList)
656 jobsOut = tail = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));
657 if (NULL == jobsOut) { assert(false); return NULL; }
660 tail->job = jobsIn->job;
663 tail->next = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));
664 if (NULL == tail->next) { assert(false); return NULL; }
667 jobsIn = jobsIn->next;
672 static void AddRoute(struct UcsXmlRoute **pRtLst, struct UcsXmlRoute *route)
674 struct UcsXmlRoute *tail;
675 if (NULL == pRtLst || NULL == route)
680 if (NULL == pRtLst[0])
686 while(tail->next) tail = tail->next;
690 static void AddScript(struct UcsXmlScript **pScrLst, struct UcsXmlScript *script)
692 struct UcsXmlScript *tail;
693 if (NULL == pScrLst || NULL == script)
698 if (NULL == pScrLst[0])
704 while(tail->next) tail = tail->next;
708 static ParseResult_t ParseAll(xmlNode *tree, UcsXmlVal_t *ucs, PrivateData_t *priv)
712 ParseResult_t result;
713 priv->autoRouteId = ROUTE_AUTO_ID_START;
714 if (!GetCount(tree, NODE, &nodeCount, true))
715 RETURN_ASSERT(Parse_XmlError);
717 ucs->pNod = MCalloc(&priv->objList, nodeCount, sizeof(Ucs_Rm_Node_t));
718 if (NULL == ucs->pNod) RETURN_ASSERT(Parse_MemoryError);
720 if (!GetUInt16(tree, PACKET_BW, &ucs->packetBw, true))
721 RETURN_ASSERT(Parse_XmlError);
723 /*Iterate all nodes*/
724 if (!GetElement(tree, NODE, true, &sub, true))
725 RETURN_ASSERT(Parse_XmlError);
730 memset(&priv->nodeData, 0, sizeof(NodeData_t));
731 priv->nodeData.nod = &ucs->pNod[ucs->nodSize];
732 if (Parse_Success != (result = ParseNode(sub, priv)))
734 /*/Iterate all connections. Node without any connection is also valid.*/
735 if (GetElementArray(sub->children, ALL_CONNECTIONS, &conType, &con))
739 const char *socTypeStr;
740 MSocketType_t socType;
742 memset(&priv->conData, 0, sizeof(ConnectionData_t));
743 if (Parse_Success != (result = ParseConnection(con, conType, priv)))
745 /*Iterate all sockets*/
746 if(!GetElementArray(con->children, ALL_SOCKETS, &socTypeStr, &soc)) RETURN_ASSERT(Parse_XmlError);
749 if (!GetSocketType(socTypeStr, &socType)) RETURN_ASSERT(Parse_XmlError);
750 if (Parse_Success != (result = ParseSocket(soc, (0 == priv->conData.sockCnt), socType, &priv->conData.jobList, priv)))
752 ++priv->conData.sockCnt;
753 if(!GetElementArray(soc, ALL_SOCKETS, &socTypeStr, &soc))
756 if(!GetElementArray(con, ALL_CONNECTIONS, &conType, &con))
761 if (!GetElement(sub, NODE, false, &sub, false))
765 /*Fill route structures*/
766 result = ParseRoutes(ucs, priv);
767 if (Parse_MemoryError == result) RETURN_ASSERT(Parse_MemoryError)
768 else if (Parse_XmlError == result) RETURN_ASSERT(Parse_XmlError);
770 /*Iterate all scripts. No scripts at all is allowed*/
771 if(GetElement(tree, SCRIPT, true, &sub, false))
774 struct UcsXmlScript *scrlist = priv->pScrLst;
777 result = ParseScript(sub, priv);
778 if (Parse_MemoryError == result) RETURN_ASSERT(Parse_MemoryError)
779 else if (Parse_XmlError == result) RETURN_ASSERT(Parse_XmlError);
780 if(!GetElement(sub, SCRIPT, false, &sub, false))
783 /* Check if all scripts where referenced */
784 while(NULL != scrlist)
788 UcsXml_CB_OnError("Script not defined:'%s', used by node=0x%X", 1, scrlist->scriptName, scrlist->node->signature_ptr->node_address);
791 scrlist = scrlist->next;
794 RETURN_ASSERT(Parse_XmlError);
799 static ParseResult_t ParseNode(xmlNode *node, PrivateData_t *priv)
803 Ucs_Signature_t *signature;
804 assert(NULL != node && NULL != priv);
805 priv->nodeData.nod->signature_ptr = MCalloc(&priv->objList, 1, sizeof(Ucs_Signature_t));
806 signature = priv->nodeData.nod->signature_ptr;
807 if(NULL == signature) RETURN_ASSERT(Parse_MemoryError);
808 if (!GetUInt16(node, ADDRESS, &signature->node_address, true))
809 RETURN_ASSERT(Parse_XmlError);
810 if (GetString(node, SCRIPT, &txt, false))
812 struct UcsXmlScript *scr = MCalloc(&priv->objList, 1, sizeof(struct UcsXmlScript));
813 if (NULL == scr) RETURN_ASSERT(Parse_MemoryError);
814 scr->node = priv->nodeData.nod;
815 strncpy(scr->scriptName, txt, sizeof(scr->scriptName));
816 AddScript(&priv->pScrLst, scr);
818 /*Iterate all ports*/
819 if(GetElementArray(node->children, ALL_PORTS, &txt, &port))
823 if (0 == (strcmp(txt, MLB_PORT)))
825 struct MlbPortParameters p;
826 p.list = &priv->objList;
827 if (!GetString(port, CLOCK_CONFIG, &p.clockConfig, true)) RETURN_ASSERT(Parse_XmlError);
828 if (!GetMlbPort(&priv->nodeData.mlbPort, &p)) RETURN_ASSERT(Parse_XmlError);
830 else if (0 == (strcmp(txt, USB_PORT)))
832 struct UsbPortParameters p;
833 p.list = &priv->objList;
834 if (!GetString(port, PHYSICAL_LAYER, &p.physicalLayer, true)) RETURN_ASSERT(Parse_XmlError);
835 if (!GetString(port, DEVICE_INTERFACES, &p.deviceInterfaces, true)) RETURN_ASSERT(Parse_XmlError);
836 if (!GetString(port, STRM_IN_COUNT, &p.streamInCount, true)) RETURN_ASSERT(Parse_XmlError);
837 if (!GetString(port, STRM_OUT_COUNT, &p.streamOutCount, true)) RETURN_ASSERT(Parse_XmlError);
838 if (!GetUsbPort(&priv->nodeData.usbPort, &p)) RETURN_ASSERT(Parse_XmlError);
840 else if (0 == (strcmp(txt, STRM_PORT)))
842 struct StrmPortParameters p;
843 p.list = &priv->objList;
845 if (!GetString(port, CLOCK_CONFIG, &p.clockConfig, true)) RETURN_ASSERT(Parse_XmlError);
846 if (!GetString(port, STRM_ALIGN, &p.dataAlignment, true)) RETURN_ASSERT(Parse_XmlError);
847 if (!GetStrmPort(&priv->nodeData.strmPortA, &p)) RETURN_ASSERT(Parse_XmlError);
849 if (!GetStrmPort(&priv->nodeData.strmPortB, &p)) RETURN_ASSERT(Parse_XmlError);
853 UcsXml_CB_OnError("Unknown Port:'%s'", 1, txt);
854 RETURN_ASSERT(Parse_XmlError);
856 if(!GetElementArray(port, ALL_PORTS, &txt, &port))
860 return Parse_Success;;
863 static ParseResult_t ParseConnection(xmlNode * node, const char *conType, PrivateData_t *priv)
865 assert(NULL != node && NULL != priv);
866 if (NULL == conType) RETURN_ASSERT(Parse_XmlError);
867 if (!GetDataType(conType, &priv->conData.dataType)) RETURN_ASSERT(Parse_XmlError);
868 switch (priv->conData.dataType)
873 if (GetString(node, MUTE_MODE, &txt, false))
875 if (0 == strcmp(txt, MUTE_MODE_NO_MUTING))
876 priv->conData.muteMode = UCS_SYNC_MUTE_MODE_NO_MUTING;
877 else if (0 == strcmp(txt, MUTE_MODE_MUTE_SIGNAL))
878 priv->conData.muteMode = UCS_SYNC_MUTE_MODE_MUTE_SIGNAL;
881 UcsXml_CB_OnError("ParseConnection: MuteMode='%s' not implemented", 1, txt);
882 RETURN_ASSERT(Parse_XmlError);
887 /*Be tolerant, this is an optional feature*/
888 priv->conData.muteMode = UCS_SYNC_MUTE_MODE_NO_MUTING;
895 if (GetUInt16(node, AVP_PACKET_SIZE, &size, false))
900 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_188;
903 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_196;
906 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_206;
909 UcsXml_CB_OnError("ParseConnection: %s='%d' not implemented", 2, AVP_PACKET_SIZE, size);
910 RETURN_ASSERT(Parse_XmlError);
915 /*Be tolerant, this is an optional feature*/
916 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_188;
921 UcsXml_CB_OnError("ParseConnection: Datatype='%s' not implemented", 1, conType);
922 RETURN_ASSERT(Parse_XmlError);
925 return Parse_Success;
928 static ParseResult_t ParseSocket(xmlNode *soc, bool isSource, MSocketType_t socketType, struct UcsXmlJobList **jobList, PrivateData_t *priv)
930 Ucs_Xrm_ResObject_t **targetSock;
931 assert(NULL != soc && NULL != priv);
932 targetSock = isSource ? &priv->conData.inSocket : &priv->conData.outSocket;
938 struct MostSocketParameters p;
939 /* If there is an combiner stored, add it now into job list (right before MOST socket) */
940 if (priv->conData.combiner)
941 if (!AddJob(jobList, priv->conData.combiner, &priv->objList)) RETURN_ASSERT(Parse_XmlError);
943 p.list = &priv->objList;
944 p.isSource = isSource;
945 p.dataType = priv->conData.dataType;
946 if (!GetUInt16(soc, BANDWIDTH, &p.bandwidth, true)) RETURN_ASSERT(Parse_XmlError);
947 if (!GetString(soc, ROUTE, &priv->conData.routeName, true)) RETURN_ASSERT(Parse_XmlError);
948 if (GetString(soc, ROUTE_IS_ACTIVE, &txt, false))
950 if (0 == strcmp(txt, VALUE_TRUE) || 0 == strcmp(txt, VALUE_1))
951 priv->conData.isDeactivated = false;
952 else if (0 == strcmp(txt, VALUE_FALSE) || 0 == strcmp(txt, VALUE_0))
953 priv->conData.isDeactivated = true;
954 else RETURN_ASSERT(Parse_XmlError);
956 priv->conData.isDeactivated = false;
958 if (!GetUInt16(soc, ROUTE_ID, &priv->conData.routeId, false))
959 priv->conData.routeId = ++priv->autoRouteId;
960 if (priv->conData.syncOffsetNeeded)
962 if (!GetUInt16(soc, OFFSET, &priv->conData.syncOffset, true)) RETURN_ASSERT(Parse_XmlError);
964 if (!GetMostSocket((Ucs_Xrm_MostSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);
965 if (!AddJob(jobList, *targetSock, &priv->objList)) RETURN_ASSERT(Parse_XmlError);
970 struct UsbSocketParameters p;
971 p.list = &priv->objList;
972 p.isSource = isSource;
973 p.dataType = priv->conData.dataType;
974 if (priv->nodeData.usbPort)
976 p.usbPort = priv->nodeData.usbPort;
978 if (!GetUsbPortDefaultCreated(&p.usbPort, &priv->objList))
979 RETURN_ASSERT(Parse_XmlError);
980 priv->nodeData.usbPort = (Ucs_Xrm_UsbPort_t *)p.usbPort;
982 if(!AddJob(jobList, p.usbPort, &priv->objList)) RETURN_ASSERT(Parse_XmlError);
983 if (!GetString(soc, ENDPOINT_ADDRESS, &p.endpointAddress, true)) RETURN_ASSERT(Parse_XmlError);
984 if (!GetString(soc, FRAMES_PER_TRANSACTION, &p.framesPerTrans, true)) RETURN_ASSERT(Parse_XmlError);
985 if (!GetUsbSocket((Ucs_Xrm_UsbSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);
986 if (!AddJob(jobList, *targetSock, &priv->objList)) RETURN_ASSERT(Parse_XmlError);
991 struct MlbSocketParameters p;
992 p.list = &priv->objList;
993 p.isSource = isSource;
994 p.dataType = priv->conData.dataType;
995 if (priv->nodeData.mlbPort)
997 p.mlbPort = priv->nodeData.mlbPort;
999 if (!GetMlbPortDefaultCreated(&p.mlbPort, &priv->objList))
1000 RETURN_ASSERT(Parse_XmlError);
1001 priv->nodeData.mlbPort = (Ucs_Xrm_MlbPort_t *)p.mlbPort;
1003 if (!AddJob(jobList, p.mlbPort, &priv->objList)) RETURN_ASSERT(Parse_XmlError);
1004 if (!GetUInt16(soc, BANDWIDTH, &p.bandwidth, true)) RETURN_ASSERT(Parse_XmlError);
1005 if (!GetString(soc, CHANNEL_ADDRESS, &p.channelAddress, true)) RETURN_ASSERT(Parse_XmlError);
1006 if (!GetMlbSocket((Ucs_Xrm_MlbSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);
1007 if (!AddJob(jobList, *targetSock, &priv->objList)) RETURN_ASSERT(Parse_XmlError);
1012 struct StrmSocketParameters p;
1013 p.list = &priv->objList;
1014 p.isSource = isSource;
1015 p.dataType = priv->conData.dataType;
1016 p.streamPortA = priv->nodeData.strmPortA;
1017 p.streamPortB = priv->nodeData.strmPortB;
1018 if (!AddJob(jobList, p.streamPortA, &priv->objList)) RETURN_ASSERT(Parse_XmlError);
1019 if (!AddJob(jobList, p.streamPortB, &priv->objList)) RETURN_ASSERT(Parse_XmlError);
1020 if (!GetUInt16(soc, BANDWIDTH, &p.bandwidth, true)) RETURN_ASSERT(Parse_XmlError);
1021 if (!GetString(soc, STRM_PIN, &p.streamPin, true)) RETURN_ASSERT(Parse_XmlError);
1022 if (!GetStrmSocket((Ucs_Xrm_StrmSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);
1023 if (!AddJob(jobList, *targetSock, &priv->objList)) RETURN_ASSERT(Parse_XmlError);
1026 case MSocket_SPLITTER:
1029 struct SplitterParameters p;
1032 UcsXml_CB_OnError("Splitter can not be used as input socket", 0);
1033 RETURN_ASSERT(Parse_XmlError);
1035 p.list = &priv->objList;
1036 if (!GetUInt16(soc, BYTES_PER_FRAME, &p.bytesPerFrame, true)) RETURN_ASSERT(Parse_XmlError);
1037 /* Current input socket will be stored inside splitter
1038 * and splitter will become the new input socket */
1039 if (!(p.inSoc = priv->conData.inSocket)) RETURN_ASSERT(Parse_XmlError);
1040 if (!GetSplitter((Ucs_Xrm_Splitter_t **)&priv->conData.inSocket, &p)) RETURN_ASSERT(Parse_XmlError);
1041 if (!AddJob(jobList, priv->conData.inSocket, &priv->objList)) RETURN_ASSERT(Parse_XmlError);
1042 if (!GetElement(soc->children, MOST_SOCKET, false, &mostSoc, true))
1043 RETURN_ASSERT(Parse_XmlError);
1044 priv->conData.syncOffsetNeeded = true;
1048 struct UcsXmlJobList *jobListCopy = DeepCopyJobList(*jobList, &priv->objList);
1049 if (!ParseSocket(mostSoc, false, MSocket_MOST, &jobListCopy, priv)) RETURN_ASSERT(Parse_XmlError);
1050 if (!GetElement(mostSoc, MOST_SOCKET, false, &mostSoc, false))
1051 return Parse_Success; /* Do not break here, otherwise an additional invalid route will be created */
1055 case MSocket_COMBINER:
1057 struct CombinerParameters p;
1060 UcsXml_CB_OnError("Combiner can not be used as output socket", 0);
1061 RETURN_ASSERT(Parse_XmlError);
1063 p.list = &priv->objList;
1064 if (!GetUInt16(soc, BYTES_PER_FRAME, &p.bytesPerFrame, true)) RETURN_ASSERT(Parse_XmlError);
1065 if (!GetCombiner(&priv->conData.combiner, &p)) RETURN_ASSERT(Parse_XmlError);
1066 priv->conData.syncOffsetNeeded = true;
1067 if (!GetElement(soc->children, MOST_SOCKET, false, &priv->conData.pendingCombinerMostSockets, true))
1068 RETURN_ASSERT(Parse_XmlError);
1072 RETURN_ASSERT(Parse_XmlError);
1074 /*Handle Pending Combiner Tasks*/
1075 if (NULL != priv->conData.outSocket && NULL != priv->conData.combiner &&
1076 NULL != priv->conData.pendingCombinerMostSockets)
1078 xmlNode *tmp = priv->conData.pendingCombinerMostSockets;
1079 priv->conData.pendingCombinerMostSockets = NULL;
1080 /* Current output socket will be stored inside combiner
1081 * and combiner will become the new output socket */
1082 priv->conData.combiner->port_socket_obj_ptr = priv->conData.outSocket;
1083 priv->conData.outSocket = priv->conData.combiner;
1086 struct UcsXmlJobList *jobListCopy = DeepCopyJobList(*jobList, &priv->objList);
1087 if (!ParseSocket(tmp, true, MSocket_MOST, &jobListCopy, priv)) RETURN_ASSERT(Parse_XmlError);
1088 if (!GetElement(tmp, MOST_SOCKET, false, &tmp, false))
1089 return Parse_Success; /* Do not break here, otherwise an additional invalid route will be created */
1092 /*Connect in and out socket once they are created*/
1093 if (priv->conData.inSocket && priv->conData.outSocket)
1097 Ucs_Rm_EndPoint_t *ep;
1098 struct UcsXmlRoute *route;
1099 switch(priv->conData.dataType)
1103 Ucs_Xrm_SyncCon_t *con = MCalloc(&priv->objList, 1, sizeof(Ucs_Xrm_SyncCon_t));
1104 if (NULL == con) RETURN_ASSERT(Parse_MemoryError);
1105 if (!AddJob(jobList, con, &priv->objList)) RETURN_ASSERT(Parse_XmlError);
1106 con->resource_type = UCS_XRM_RC_TYPE_SYNC_CON;
1107 con->socket_in_obj_ptr = priv->conData.inSocket;
1108 con->socket_out_obj_ptr = priv->conData.outSocket;
1109 con->mute_mode = priv->conData.muteMode;
1110 con->offset = priv->conData.syncOffset;
1115 Ucs_Xrm_AvpCon_t *con = MCalloc(&priv->objList, 1, sizeof(Ucs_Xrm_AvpCon_t));
1116 if (NULL == con) RETURN_ASSERT(Parse_MemoryError);
1117 if (!AddJob(jobList, con, &priv->objList)) RETURN_ASSERT(Parse_XmlError);
1118 con->resource_type = UCS_XRM_RC_TYPE_AVP_CON;
1119 con->socket_in_obj_ptr = priv->conData.inSocket;
1120 con->socket_out_obj_ptr = priv->conData.outSocket;
1121 con->isoc_packet_size = priv->conData.isocPacketSize;
1125 UcsXml_CB_OnError("Could not connect sockets, data type not implemented: %d", 1, priv->conData.dataType);
1126 RETURN_ASSERT(Parse_XmlError);
1129 ep = MCalloc(&priv->objList, 1, sizeof(Ucs_Rm_EndPoint_t));
1130 if (NULL == ep) RETURN_ASSERT(Parse_MemoryError);
1132 mostIsInput = (UCS_XRM_RC_TYPE_MOST_SOCKET == *((Ucs_Xrm_ResourceType_t *)priv->conData.inSocket));
1133 mostIsOutput = (UCS_XRM_RC_TYPE_MOST_SOCKET == *((Ucs_Xrm_ResourceType_t *)priv->conData.outSocket));
1134 if (!mostIsInput && !mostIsOutput)
1136 UcsXml_CB_OnError("At least one MOST socket required per connection", 0);
1137 RETURN_ASSERT(Parse_XmlError);
1139 ep->endpoint_type = mostIsOutput ? UCS_RM_EP_SOURCE : UCS_RM_EP_SINK;
1140 ep->jobs_list_ptr = GetJobList(*jobList, &priv->objList);
1141 if(NULL == ep->jobs_list_ptr) RETURN_ASSERT(Parse_MemoryError);
1142 ep->node_obj_ptr = priv->nodeData.nod;
1143 route = MCalloc(&priv->objList, 1, sizeof(struct UcsXmlRoute));
1144 if (NULL == route) RETURN_ASSERT(Parse_MemoryError);
1145 route->isSource = mostIsOutput;
1146 route->isActive = !priv->conData.isDeactivated;
1147 route->routeId = priv->conData.routeId;
1149 assert(NULL != priv->conData.routeName);
1150 strncpy(route->routeName, priv->conData.routeName, sizeof(route->routeName));
1151 AddRoute(&priv->pRtLst, route);
1153 return Parse_Success;
1156 static ParseResult_t ParseScript(xmlNode *scr, PrivateData_t *priv)
1163 struct UcsXmlScript *scrlist;
1164 Ucs_Ns_Script_t *script;
1165 assert(NULL != scr && NULL != priv);
1166 priv->scriptData.pause = 0;
1167 scrlist = priv->pScrLst;
1168 if (!GetCountArray(scr->children, ALL_SCRIPTS, &actCnt, false)) RETURN_ASSERT(Parse_XmlError);
1169 if (NULL == (script = MCalloc(&priv->objList, actCnt, sizeof(Ucs_Ns_Script_t))))
1170 RETURN_ASSERT(Parse_MemoryError);
1172 /*Iterate all actions*/
1173 if (!GetElementArray(scr->children, ALL_SCRIPTS, &txt, &act)) RETURN_ASSERT(Parse_XmlError);
1176 if (0 == strcmp(txt, SCRIPT_MSG_SEND)) {
1177 ParseResult_t result = ParseScriptMsgSend(act, &script[i], priv);
1178 if (Parse_Success != result) return result;
1180 } else if (0 == strcmp(txt, SCRIPT_GPIO_PORT_CREATE)) {
1181 ParseResult_t result = ParseScriptGpioPortCreate(act, &script[i], priv);
1182 if (Parse_Success != result) return result;
1184 } else if (0 == strcmp(txt, SCRIPT_GPIO_PORT_PIN_MODE)) {
1185 ParseResult_t result = ParseScriptGpioPinMode(act, &script[i], priv);
1186 if (Parse_Success != result) return result;
1188 } else if (0 == strcmp(txt, SCRIPT_GPIO_PIN_STATE)) {
1189 ParseResult_t result = ParseScriptGpioPinState(act, &script[i], priv);
1190 if (Parse_Success != result) return result;
1192 } else if (0 == strcmp(txt, SCRIPT_I2C_PORT_CREATE)) {
1193 ParseResult_t result = ParseScriptPortCreate(act, &script[i], priv);
1194 if (Parse_Success != result) return result;
1196 } else if (0 == strcmp(txt, SCRIPT_I2C_PORT_WRITE)) {
1197 ParseResult_t result = ParseScriptPortWrite(act, &script[i], priv);
1198 if (Parse_Success != result) return result;
1200 } else if (0 == strcmp(txt, SCRIPT_I2C_PORT_READ)) {
1201 ParseResult_t result = ParseScriptPortRead(act, &script[i], priv);
1202 if (Parse_Success != result) return result;
1204 } else if (0 == strcmp(txt, SCRIPT_PAUSE)) {
1205 ParseResult_t result = ParseScriptPause(act, &script[i], priv);
1206 if (Parse_Success != result) return result;
1208 UcsXml_CB_OnError("Unknown script action:'%s'", 1, txt);
1209 RETURN_ASSERT(Parse_XmlError);
1211 if (!GetElementArray(act, ALL_SCRIPTS, &txt, &act))
1215 if (!GetString(scr, NAME, &txt, true))
1216 RETURN_ASSERT(Parse_XmlError);
1217 while(NULL != scrlist)
1219 if (0 == strcmp(txt, scrlist->scriptName))
1221 Ucs_Rm_Node_t *node = scrlist->node;
1222 node->script_list_ptr = script;
1223 node->script_list_size = actCnt;
1224 scrlist->inUse = true;
1227 scrlist = scrlist->next;
1231 UcsXml_CB_OnError("Script defined:'%s', which was never referenced", 1, txt);
1232 RETURN_ASSERT(Parse_XmlError);
1234 return Parse_Success;
1237 static bool FillScriptInitialValues(Ucs_Ns_Script_t *scr, PrivateData_t *priv)
1239 assert(NULL != scr && NULL != priv);
1240 scr->send_cmd = MCalloc(&priv->objList, 1, sizeof(Ucs_Ns_ConfigMsg_t));
1241 scr->exp_result = MCalloc(&priv->objList, 1, sizeof(Ucs_Ns_ConfigMsg_t));
1242 assert(scr->send_cmd && scr->exp_result);
1243 if (NULL == scr->send_cmd || NULL == scr->exp_result) return false;
1244 scr->pause = priv->scriptData.pause;
1245 priv->scriptData.pause = 0;
1249 static ParseResult_t ParseScriptMsgSend(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
1251 Ucs_Ns_ConfigMsg_t *req, *res;
1252 assert(NULL != act && NULL != scr && NULL != priv);
1253 if (!FillScriptInitialValues(scr, priv)) return Parse_MemoryError;
1254 req = scr->send_cmd;
1255 res = scr->exp_result;
1256 req->InstId = res->InstId = 1;
1257 if (!GetUInt8(act, FBLOCK_ID, &req->FBlockId, true))
1258 RETURN_ASSERT(Parse_XmlError);
1260 if (!GetUInt16(act, FUNCTION_ID, &req->FunktId, true))
1261 RETURN_ASSERT(Parse_XmlError);
1263 if (!GetUInt8(act, OP_TYPE_REQUEST, &req->OpCode, true))
1264 RETURN_ASSERT(Parse_XmlError);
1266 res->FBlockId = req->FBlockId;
1267 res->FunktId = req->FunktId;
1269 if (GetUInt8(act, OP_TYPE_RESPONSE, &res->OpCode, false))
1270 GetPayload(act, PAYLOAD_RES_HEX, &res->DataPtr, &res->DataLen, 0, &priv->objList, false);
1272 if (!GetPayload(act, PAYLOAD_REQ_HEX, &req->DataPtr, &req->DataLen, 0, &priv->objList, true))
1273 RETURN_ASSERT(Parse_XmlError);
1274 if (0 == req->DataLen || NULL == req->DataPtr)
1275 RETURN_ASSERT(Parse_XmlError);
1276 return Parse_Success;
1279 static ParseResult_t ParseScriptGpioPortCreate(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
1282 Ucs_Ns_ConfigMsg_t *req, *res;
1283 assert(NULL != act && NULL != scr && NULL != priv);
1284 if (!FillScriptInitialValues(scr, priv))
1285 RETURN_ASSERT(Parse_MemoryError);
1286 if (!GetUInt16(act, DEBOUNCE_TIME, &debounce, true))
1287 RETURN_ASSERT(Parse_XmlError);
1288 req = scr->send_cmd;
1289 res = scr->exp_result;
1290 req->InstId = res->InstId = 1;
1291 req->FunktId = res->FunktId = 0x701;
1296 req->DataPtr = MCalloc(&priv->objList, req->DataLen, 1);
1297 if (NULL == req->DataPtr) return Parse_MemoryError;
1298 res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);
1299 if (NULL == res->DataPtr) return Parse_MemoryError;
1300 req->DataPtr[0] = 0; /*GPIO Port instance, always 0*/
1301 req->DataPtr[1] = MISC_HB(debounce);
1302 req->DataPtr[2] = MISC_LB(debounce);
1304 res->DataPtr[0] = 0x1D;
1305 res->DataPtr[1] = 0x00;
1306 return Parse_Success;
1309 static ParseResult_t ParseScriptGpioPinMode(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
1311 #define PORT_HANDLE_OFFSET (2)
1313 uint8_t payloadLen = 0;
1314 Ucs_Ns_ConfigMsg_t *req, *res;
1315 assert(NULL != act && NULL != scr && NULL != priv);
1316 if (!FillScriptInitialValues(scr, priv))
1317 RETURN_ASSERT(Parse_MemoryError);
1318 req = scr->send_cmd;
1319 res = scr->exp_result;
1320 req->InstId = res->InstId = 1;
1321 req->FunktId = res->FunktId = 0x703;
1324 if (!GetPayload(act, PIN_CONFIG, &payload, &payloadLen,
1325 PORT_HANDLE_OFFSET, /* First two bytes are reserved for port handle */
1326 &priv->objList, true)) RETURN_ASSERT(Parse_XmlError);
1329 req->DataPtr = payload;
1330 res->DataPtr = payload;
1331 req->DataLen = payloadLen + PORT_HANDLE_OFFSET;
1332 res->DataLen = payloadLen + PORT_HANDLE_OFFSET;
1333 return Parse_Success;
1336 static ParseResult_t ParseScriptGpioPinState(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
1338 uint16_t mask, data;
1339 Ucs_Ns_ConfigMsg_t *req, *res;
1340 assert(NULL != act && NULL != scr && NULL != priv);
1341 if (!FillScriptInitialValues(scr, priv))
1342 RETURN_ASSERT(Parse_MemoryError);
1343 if (!GetUInt16(act, PIN_MASK, &mask, true))
1344 RETURN_ASSERT(Parse_XmlError);
1345 if (!GetUInt16(act, PIN_DATA, &data, true))
1346 RETURN_ASSERT(Parse_XmlError);
1347 req = scr->send_cmd;
1348 res = scr->exp_result;
1349 req->InstId = res->InstId = 1;
1350 req->FunktId = res->FunktId = 0x704;
1355 req->DataPtr = MCalloc(&priv->objList, req->DataLen, 1);
1356 if (NULL == req->DataPtr) return Parse_MemoryError;
1357 res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);
1358 if (NULL == res->DataPtr) return Parse_MemoryError;
1359 req->DataPtr[0] = 0x1D;
1360 req->DataPtr[1] = 0x00;
1361 req->DataPtr[2] = MISC_HB(mask);
1362 req->DataPtr[3] = MISC_LB(mask);
1363 req->DataPtr[4] = MISC_HB(data);
1364 req->DataPtr[5] = MISC_LB(data);
1365 memcpy(res->DataPtr, req->DataPtr, req->DataLen);
1366 res->DataPtr[6] = 0x00;
1367 res->DataPtr[7] = 0x00;
1368 return Parse_Success;
1371 static ParseResult_t ParseScriptPortCreate(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
1375 Ucs_Ns_ConfigMsg_t *req, *res;
1376 assert(NULL != act && NULL != scr && NULL != priv);
1377 if (!FillScriptInitialValues(scr, priv))
1378 RETURN_ASSERT(Parse_MemoryError);
1379 if (!GetString(act, I2C_SPEED, &txt, true))
1380 RETURN_ASSERT(Parse_XmlError);
1381 if (0 == strcmp(txt, I2C_SPEED_SLOW))
1383 else if (0 == strcmp(txt, I2C_SPEED_FAST))
1387 UcsXml_CB_OnError("Invalid I2C speed:'%s'", 1, txt);
1388 RETURN_ASSERT(Parse_XmlError);
1390 req = scr->send_cmd;
1391 res = scr->exp_result;
1392 req->InstId = res->InstId = 1;
1393 req->FunktId = res->FunktId = 0x6C1;
1398 req->DataPtr = MCalloc(&priv->objList, req->DataLen, 1);
1399 if (NULL == req->DataPtr) return Parse_MemoryError;
1400 res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);
1401 if (NULL == res->DataPtr) return Parse_MemoryError;
1402 req->DataPtr[0] = 0x00; /* I2C Port Instance always 0 */
1403 req->DataPtr[1] = 0x00; /* I2C slave address, always 0, because we are Master */
1404 req->DataPtr[2] = 0x01; /* We are Master */
1405 req->DataPtr[3] = speed;
1407 res->DataPtr[0] = 0x0F;
1408 res->DataPtr[1] = 0x00;
1409 return Parse_Success;
1412 static ParseResult_t ParseScriptPortWrite(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
1414 #define HEADER_OFFSET 8
1416 uint8_t mode, blockCount, address, length, payloadLength;
1419 Ucs_Ns_ConfigMsg_t *req, *res;
1420 assert(NULL != act && NULL != scr && NULL != priv);
1421 if (GetString(act, I2C_WRITE_MODE, &txt, false))
1423 if (0 == strcmp(txt, I2C_WRITE_MODE_DEFAULT))
1425 else if (0 == strcmp(txt, I2C_WRITE_MODE_REPEAT))
1427 else if (0 == strcmp(txt, I2C_WRITE_MODE_BURST))
1431 UcsXml_CB_OnError("Invalid I2C mode:'%s'", 1, txt);
1432 RETURN_ASSERT(Parse_XmlError);
1437 if (!GetUInt8(act, I2C_WRITE_BLOCK_COUNT, &blockCount, false))
1439 if (!GetUInt8(act, I2C_SLAVE_ADDRESS, &address, true))
1440 RETURN_ASSERT(Parse_XmlError);
1441 if (!GetUInt8(act, I2C_PAYLOAD_LENGTH, &length, false))
1443 if (!GetUInt16(act, I2C_TIMEOUT, &timeout, false))
1445 if (!GetPayload(act, I2C_PAYLOAD, &payload, &payloadLength, HEADER_OFFSET, &priv->objList, true))
1446 RETURN_ASSERT(Parse_XmlError);
1448 length = payloadLength;
1449 if (!FillScriptInitialValues(scr, priv))
1450 RETURN_ASSERT(Parse_MemoryError);
1451 req = scr->send_cmd;
1452 res = scr->exp_result;
1453 req->InstId = res->InstId = 1;
1454 req->FunktId = res->FunktId = 0x6C4;
1457 req->DataLen = payloadLength + HEADER_OFFSET;
1459 req->DataPtr = payload;
1460 res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);
1461 if (NULL == res->DataPtr) return Parse_MemoryError;
1463 req->DataPtr[0] = 0x0F;
1464 req->DataPtr[1] = 0x00;
1465 req->DataPtr[2] = mode;
1466 req->DataPtr[3] = blockCount;
1467 req->DataPtr[4] = address;
1468 req->DataPtr[5] = length;
1469 req->DataPtr[6] = MISC_HB(timeout);
1470 req->DataPtr[7] = MISC_LB(timeout);
1472 res->DataPtr[0] = 0x0F;
1473 res->DataPtr[1] = 0x00;
1474 res->DataPtr[2] = address;
1476 res->DataPtr[3] = blockCount * length;
1478 res->DataPtr[3] = length;
1479 return Parse_Success;
1482 static ParseResult_t ParseScriptPortRead(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
1484 uint8_t address, length;
1486 Ucs_Ns_ConfigMsg_t *req, *res;
1487 assert(NULL != act && NULL != scr && NULL != priv);
1488 if (!GetUInt8(act, I2C_SLAVE_ADDRESS, &address, true))
1489 RETURN_ASSERT(Parse_XmlError);
1490 if (!GetUInt8(act, I2C_PAYLOAD_LENGTH, &length, true))
1491 RETURN_ASSERT(Parse_XmlError);
1492 if (!GetUInt16(act, I2C_TIMEOUT, &timeout, false))
1494 if (!FillScriptInitialValues(scr, priv))
1495 RETURN_ASSERT(Parse_MemoryError);
1496 req = scr->send_cmd;
1497 res = scr->exp_result;
1498 req->InstId = res->InstId = 1;
1499 req->FunktId = res->FunktId = 0x6C3;
1504 req->DataPtr = MCalloc(&priv->objList, req->DataLen, 1);
1505 if (NULL == req->DataPtr) return Parse_MemoryError;
1506 res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);
1507 if (NULL == res->DataPtr) return Parse_MemoryError;
1509 req->DataPtr[0] = 0x0F;
1510 req->DataPtr[1] = 0x00;
1511 req->DataPtr[2] = address;
1512 req->DataPtr[3] = length;
1513 req->DataPtr[4] = MISC_HB(timeout);
1514 req->DataPtr[5] = MISC_LB(timeout);
1516 res->DataPtr[0] = 0x0F;
1517 res->DataPtr[1] = 0x00;
1518 res->DataPtr[2] = address;
1519 res->DataPtr[3] = length;
1520 return Parse_Success;
1523 static ParseResult_t ParseScriptPause(xmlNode *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
1525 assert(NULL != act && NULL != priv);
1526 if (!GetUInt16(act, PAUSE_MS, &priv->scriptData.pause, true))
1527 RETURN_ASSERT(Parse_XmlError);
1528 return Parse_Success;
1531 static ParseResult_t ParseRoutes(UcsXmlVal_t *ucs, PrivateData_t *priv)
1533 uint16_t routeAmount = 0;
1534 struct UcsXmlRoute *sourceRoute;
1535 assert(NULL != ucs && NULL != priv);
1536 /*First: Count the amount of routes and allocate the correct amount*/
1537 sourceRoute = priv->pRtLst;
1538 while (NULL != sourceRoute)
1540 if (sourceRoute->isSource)
1542 struct UcsXmlRoute *sinkRoute = priv->pRtLst;
1543 while (NULL != sinkRoute)
1545 if (sourceRoute != sinkRoute
1546 && !sinkRoute->isSource
1547 && (0 == strncmp(sourceRoute->routeName, sinkRoute->routeName, sizeof(sourceRoute->routeName))))
1551 sinkRoute = sinkRoute->next;
1554 sourceRoute = sourceRoute->next;
1556 if (0 == routeAmount)
1557 return Parse_Success; /*Its okay to have no routes at all (e.g. MEP traffic only)*/
1558 ucs->pRoutes = MCalloc(&priv->objList, routeAmount, sizeof(Ucs_Rm_Route_t));
1559 if (NULL == ucs->pRoutes) RETURN_ASSERT(Parse_MemoryError);
1561 /*Second: Fill allocated structure now*/
1562 sourceRoute = priv->pRtLst;
1563 while (NULL != sourceRoute)
1565 if (sourceRoute->isSource)
1567 struct UcsXmlRoute *sinkRoute = priv->pRtLst;
1568 while (NULL != sinkRoute)
1570 if (sourceRoute != sinkRoute
1571 && !sinkRoute->isSource
1572 && (0 == strncmp(sourceRoute->routeName, sinkRoute->routeName, sizeof(sourceRoute->routeName))))
1574 Ucs_Rm_Route_t *route;
1575 if(ucs->routesSize >= routeAmount)
1577 RETURN_ASSERT(Parse_MemoryError);
1579 route = &ucs->pRoutes[ucs->routesSize++];
1580 route->source_endpoint_ptr = sourceRoute->ep;
1581 route->sink_endpoint_ptr = sinkRoute->ep;
1582 if (!IsAutoRouteId(sourceRoute->routeId, priv))
1584 route->active = sourceRoute->isActive;
1585 route->route_id = sourceRoute->routeId;
1589 route->active = sinkRoute->isActive;
1590 route->route_id = sinkRoute->routeId;
1593 sinkRoute = sinkRoute->next;
1596 sourceRoute = sourceRoute->next;
1600 /* Third perform checks when running in debug mode*/
1602 Ucs_Xrm_ResourceType_t *job;
1604 for (i = 0; i < routeAmount; i++)
1606 Ucs_Rm_Route_t *route = &ucs->pRoutes[i];
1607 assert(NULL != route->source_endpoint_ptr);
1608 assert(NULL != route->sink_endpoint_ptr);
1609 assert(NULL != route->source_endpoint_ptr->jobs_list_ptr);
1610 assert(UCS_RM_EP_SOURCE == route->source_endpoint_ptr->endpoint_type);
1611 assert(UCS_RM_EP_SINK == route->sink_endpoint_ptr->endpoint_type);
1612 assert(NULL != route->source_endpoint_ptr->node_obj_ptr);
1613 assert(NULL != route->sink_endpoint_ptr->node_obj_ptr);
1614 assert(NULL != route->source_endpoint_ptr->node_obj_ptr->signature_ptr);
1615 assert(NULL != route->sink_endpoint_ptr->node_obj_ptr->signature_ptr);
1617 while((job = ((Ucs_Xrm_ResourceType_t *)route->source_endpoint_ptr->jobs_list_ptr[j])))
1619 assert(UCS_XRM_RC_TYPE_QOS_CON >= *job);
1623 while((job = ((Ucs_Xrm_ResourceType_t *)route->sink_endpoint_ptr->jobs_list_ptr[j])))
1625 assert(UCS_XRM_RC_TYPE_QOS_CON >= *job);
1631 return Parse_Success;
1634 static bool IsAutoRouteId(uint16_t id, PrivateData_t *priv)
1636 assert(NULL != priv);
1637 return (id >= ROUTE_AUTO_ID_START && id <= priv->autoRouteId);