1 /*------------------------------------------------------------------------------------------------*/
\r
2 /* UNICENS XML Parser */
\r
3 /* Copyright 2017, Microchip Technology Inc. and its subsidiaries. */
\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
8 /* 1. Redistributions of source code must retain the above copyright notice, this */
\r
9 /* list of conditions and the following disclaimer. */
\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
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
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
33 #include "UcsXml_Private.h"
\r
36 /************************************************************************/
\r
37 /* PRIVATE DECLARATIONS */
\r
38 /************************************************************************/
\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
51 Ucs_Rm_EndPoint_t *ep;
\r
52 struct UcsXmlRoute *next;
\r
58 char scriptName[32];
\r
59 Ucs_Rm_Node_t *node;
\r
60 struct UcsXmlScript *next;
\r
63 struct UcsXmlJobList
\r
65 Ucs_Xrm_ResObject_t *job;
\r
66 struct UcsXmlJobList *next;
\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
97 MDataType_t dataType;
\r
99 bool syncOffsetNeeded;
\r
100 bool isDeactivated;
\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
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
128 /************************************************************************/
\r
130 /************************************************************************/
\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
158 static const char* ALL_CONNECTIONS[] = { SYNC_CONNECTION, AVP_CONNECTION,
\r
159 DFP_CONNECTION, QOS_CONNECTION, IPC_CONNECTION, NULL };
\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
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
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
180 static const char* STRM_PIN = "StreamPinID";
\r
181 static const char* STRM_ALIGN = "DataAlignment";
\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
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
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
225 /************************************************************************/
\r
226 /* Private Function Prototypes */
\r
227 /************************************************************************/
\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
262 /************************************************************************/
\r
263 /* Public Functions */
\r
264 /************************************************************************/
\r
266 UcsXmlVal_t *UcsXml_Parse(const char *xmlString)
\r
268 UcsXmlVal_t *val = NULL;
\r
269 ParseResult_t result = Parse_MemoryError;
\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
282 if (Parse_MemoryError == result)
\r
283 UcsXml_CB_OnError("XML memory error, aborting..", 0);
\r
285 UcsXml_CB_OnError("XML parsing error, aborting..", 0);
\r
294 void UcsXml_FreeVal(UcsXmlVal_t *val)
\r
299 /************************************************************************/
\r
300 /* Private Function Implementations */
\r
301 /************************************************************************/
\r
303 void FreeVal(UcsXmlVal_t *ucs)
\r
305 PrivateData_t *priv;
\r
306 if (NULL == ucs || NULL == ucs->pInternal)
\r
308 priv = ucs->pInternal;
\r
309 FreeObjList(&priv->objList);
\r
310 free(ucs->pInternal);
\r
314 static bool GetElement(mxml_node_t *element, const char *name, bool goDeep, mxml_node_t **out, bool mandatory)
\r
316 mxml_node_t *n = element;
\r
317 if (NULL == n || NULL == name || NULL == out) return false;
\r
320 *out = mxmlFindElement(n, n, name, NULL, NULL, MXML_DESCEND);
\r
321 return (NULL != *out);
\r
323 while ((n = n->next))
\r
325 if (MXML_ELEMENT != n->type)
\r
327 if (0 == strcmp(name, n->value.opaque))
\r
334 UcsXml_CB_OnError("Can not find tag <%s>", 1, name);
\r
338 static bool GetElementArray(mxml_node_t *element, const char *array[], const char **foundName, mxml_node_t **out)
\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
345 if (MXML_ELEMENT != n->type)
\r
347 for (i = 0; NULL != array[i]; i++)
\r
349 if (0 == strcmp(array[i], n->value.opaque))
\r
351 *foundName = array[i];
\r
360 static bool GetCount(mxml_node_t *element, const char *name, uint32_t *out, bool mandatory)
\r
364 if (NULL == element || NULL == name) return false;
\r
365 if(!GetElement(element, name, true, &n, false))
\r
370 if(!GetElement(n, name, false, &n, false))
\r
373 if (mandatory && 0 == cnt)
\r
375 UcsXml_CB_OnError("element count of <%s> is zero", 1, name);
\r
382 static bool GetCountArray(mxml_node_t *element, const char *array[], uint32_t *out, bool mandatory)
\r
387 if (NULL == element || NULL == array) return false;
\r
391 if(!GetElementArray(n, array, &tmp, &n))
\r
395 if (mandatory && 0 == cnt)
\r
397 UcsXml_CB_OnError("element count is zero, searched with string array", 0);
\r
404 static bool GetString(mxml_node_t *element, const char *key, const char **out, bool mandatory)
\r
407 if (NULL == element || NULL == key) return false;
\r
408 for (i = 0; i < element->value.element.num_attrs; i++)
\r
410 mxml_attr_t *attr = &element->value.element.attrs[i];
\r
411 if (0 == strcmp(key, attr->name))
\r
413 *out = attr->value;
\r
418 UcsXml_CB_OnError("Can not find attribute='%s' from element <%s>",
\r
419 2, key, element->value.element.name);
\r
423 static bool CheckInteger(const char *value, bool forceHex)
\r
425 bool hex = forceHex;
\r
427 if (!value) return false;
\r
428 len = strlen(value);
\r
429 if (len >= 3 && '0' == value[0] && 'x' == value[1])
\r
436 bool valid = false;
\r
437 uint8_t v = value[0];
\r
438 if (v >= '0' && v <= '9') valid = true;
\r
441 if (v >= 'a' && v <= 'f') valid = true;
\r
442 if (v >= 'A' && v <= 'F') valid = true;
\r
444 if (!valid) return false;
\r
450 static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory)
\r
454 if (!GetString(element, key, &txt, mandatory)) return false;
\r
455 if (!CheckInteger(txt, false))
\r
457 UcsXml_CB_OnError("key='%s' contained invalid integer='%s'", 2, key, txt);
\r
460 value = strtol( txt, NULL, 0 );
\r
461 if (value > 0xFFFF)
\r
463 UcsXml_CB_OnError("key='%s' is out of range='%d'", 2, key, value);
\r
470 static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory)
\r
474 if (!GetString(element, key, &txt, mandatory)) return false;
\r
475 if (!CheckInteger(txt, false))
\r
477 UcsXml_CB_OnError("key='%s' contained invalid integer='%s'", 2, key, txt);
\r
480 value = strtol( txt, NULL, 0 );
\r
483 UcsXml_CB_OnError("key='%s' is out of range='%d'", 2, key, value);
\r
490 static bool GetDataType(const char *txt, MDataType_t *out)
\r
492 if (NULL == txt || NULL == out) return false;
\r
493 if (0 == strcmp(SYNC_CONNECTION, txt)) {
\r
495 } else if (0 == strcmp(AVP_CONNECTION, txt)) {
\r
496 *out = AV_PACKETIZED;
\r
497 } else if (0 == strcmp(QOS_CONNECTION, txt)) {
\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
504 UcsXml_CB_OnError("Unknown data type : '%s'", 1, txt);
\r
510 static bool GetSocketType(const char *txt, MSocketType_t *out)
\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
525 UcsXml_CB_OnError("Unknown port : '%s'", 1, txt);
\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
533 uint32_t tempLen, len = 0;
\r
539 if (!GetString(element, name, &txt, mandatory))
\r
541 tempLen = strlen(txt) + 1;
\r
542 txtCopy = malloc(tempLen);
\r
543 if (NULL == txtCopy)
\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
554 token = strtok_r( txtCopy, " ,.-", &tkPtr );
\r
555 while( NULL != token )
\r
557 if( len >= tempLen )
\r
559 UcsXml_CB_OnError("Script payload values must be stuffed to two characters", 0);
\r
564 if (!CheckInteger(token, true))
\r
566 UcsXml_CB_OnError("Script payload contains non valid hex number='%s'", 1, token);
\r
571 p[offset + len++] = strtol( token, NULL, 16 );
\r
572 token = strtok_r( NULL, " ,.-", &tkPtr );
\r
578 static bool AddJob(struct UcsXmlJobList **joblist, Ucs_Xrm_ResObject_t *job, struct UcsXmlObjectList *objList)
\r
580 struct UcsXmlJobList *tail;
\r
581 if (NULL == joblist || NULL == job)
\r
583 assert(UCS_XRM_RC_TYPE_QOS_CON >= *((Ucs_Xrm_ResourceType_t *)job));
\r
584 if (NULL == joblist[0])
\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
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
599 static Ucs_Xrm_ResObject_t **GetJobList(struct UcsXmlJobList *joblist, struct UcsXmlObjectList *objList)
\r
601 Ucs_Xrm_ResObject_t **outJob;
\r
602 uint32_t count = 0;
\r
603 struct UcsXmlJobList *tail;
\r
604 if (NULL == joblist)
\r
606 /*First: Get amount of stored jobs by enumerate all*/
\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
623 outJob[count++] = tail->job;
\r
629 static struct UcsXmlJobList *DeepCopyJobList(struct UcsXmlJobList *jobsIn, struct UcsXmlObjectList *objList)
\r
631 struct UcsXmlJobList *jobsOut, *tail;
\r
632 if (NULL == jobsIn || NULL == objList)
\r
634 jobsOut = tail = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));
\r
635 if (NULL == jobsOut) { assert(false); return NULL; }
\r
638 tail->job = jobsIn->job;
\r
641 tail->next = MCalloc(objList, 1, sizeof(struct UcsXmlJobList));
\r
642 if (NULL == tail->next) { assert(false); return NULL; }
\r
645 jobsIn = jobsIn->next;
\r
650 static void AddRoute(struct UcsXmlRoute **pRtLst, struct UcsXmlRoute *route)
\r
652 struct UcsXmlRoute *tail;
\r
653 if (NULL == pRtLst || NULL == route)
\r
658 if (NULL == pRtLst[0])
\r
664 while(tail->next) tail = tail->next;
\r
665 tail->next = route;
\r
668 static void AddScript(struct UcsXmlScript **pScrLst, struct UcsXmlScript *script)
\r
670 struct UcsXmlScript *tail;
\r
671 if (NULL == pScrLst || NULL == script)
\r
676 if (NULL == pScrLst[0])
\r
678 pScrLst[0] = script;
\r
682 while(tail->next) tail = tail->next;
\r
683 tail->next = script;
\r
686 static ParseResult_t ParseAll(mxml_node_t *tree, UcsXmlVal_t *ucs, PrivateData_t *priv)
\r
688 uint32_t nodeCount;
\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
695 ucs->pNod = MCalloc(&priv->objList, nodeCount, sizeof(Ucs_Rm_Node_t));
\r
696 if (NULL == ucs->pNod) RETURN_ASSERT(Parse_MemoryError);
\r
698 if (!GetUInt16(tree, PACKET_BW, &ucs->packetBw, true))
\r
699 RETURN_ASSERT(Parse_XmlError);
\r
701 /*Iterate all nodes*/
\r
702 if (!GetElement(tree, NODE, true, &sub, true))
\r
703 RETURN_ASSERT(Parse_XmlError);
\r
706 const char *conType;
\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
712 /*/Iterate all connections. Node without any connection is also valid.*/
\r
713 if (GetElementArray(sub->child, ALL_CONNECTIONS, &conType, &con))
\r
717 const char *socTypeStr;
\r
718 MSocketType_t socType;
\r
720 memset(&priv->conData, 0, sizeof(ConnectionData_t));
\r
721 if (Parse_Success != (result = ParseConnection(con, conType, priv)))
\r
723 /*Iterate all sockets*/
\r
724 if(!GetElementArray(con->child, ALL_SOCKETS, &socTypeStr, &soc)) RETURN_ASSERT(Parse_XmlError);
\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
730 ++priv->conData.sockCnt;
\r
731 if(!GetElementArray(soc, ALL_SOCKETS, &socTypeStr, &soc))
\r
734 if(!GetElementArray(con, ALL_CONNECTIONS, &conType, &con))
\r
739 if (!GetElement(sub, NODE, false, &sub, false))
\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
748 /*Iterate all scripts. No scripts at all is allowed*/
\r
749 if(GetElement(tree, SCRIPT, true, &sub, false))
\r
752 struct UcsXmlScript *scrlist = priv->pScrLst;
\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
761 /* Check if all scripts where referenced */
\r
762 while(NULL != scrlist)
\r
764 if (!scrlist->inUse)
\r
766 UcsXml_CB_OnError("Script not defined:'%s', used by node=0x%X", 1, scrlist->scriptName, scrlist->node->signature_ptr->node_address);
\r
769 scrlist = scrlist->next;
\r
772 RETURN_ASSERT(Parse_XmlError);
\r
777 static ParseResult_t ParseNode(mxml_node_t *node, PrivateData_t *priv)
\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
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
796 /*Iterate all ports*/
\r
797 if(GetElementArray(node->child, ALL_PORTS, &txt, &port))
\r
801 if (0 == (strcmp(txt, MLB_PORT)))
\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
808 else if (0 == (strcmp(txt, USB_PORT)))
\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
818 else if (0 == (strcmp(txt, STRM_PORT)))
\r
820 struct StrmPortParameters p;
\r
821 p.list = &priv->objList;
\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
827 if (!GetStrmPort(&priv->nodeData.strmPortB, &p)) RETURN_ASSERT(Parse_XmlError);
\r
831 UcsXml_CB_OnError("Unknown Port:'%s'", 1, txt);
\r
832 RETURN_ASSERT(Parse_XmlError);
\r
834 if(!GetElementArray(port, ALL_PORTS, &txt, &port))
\r
838 return Parse_Success;;
\r
841 static ParseResult_t ParseConnection(mxml_node_t * node, const char *conType, PrivateData_t *priv)
\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
851 if (GetString(node, MUTE_MODE, &txt, false))
\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
859 UcsXml_CB_OnError("ParseConnection: MuteMode='%s' not implemented", 1, txt);
\r
860 RETURN_ASSERT(Parse_XmlError);
\r
865 /*Be tolerant, this is an optional feature*/
\r
866 priv->conData.muteMode = UCS_SYNC_MUTE_MODE_NO_MUTING;
\r
870 case AV_PACKETIZED:
\r
873 if (GetUInt16(node, AVP_PACKET_SIZE, &size, false))
\r
878 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_188;
\r
881 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_196;
\r
884 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_206;
\r
887 UcsXml_CB_OnError("ParseConnection: %s='%d' not implemented", 2, AVP_PACKET_SIZE, size);
\r
888 RETURN_ASSERT(Parse_XmlError);
\r
893 /*Be tolerant, this is an optional feature*/
\r
894 priv->conData.isocPacketSize = UCS_ISOC_PCKT_SIZE_188;
\r
899 UcsXml_CB_OnError("ParseConnection: Datatype='%s' not implemented", 1, conType);
\r
900 RETURN_ASSERT(Parse_XmlError);
\r
903 return Parse_Success;
\r
906 static ParseResult_t ParseSocket(mxml_node_t *soc, bool isSource, MSocketType_t socketType, struct UcsXmlJobList **jobList, PrivateData_t *priv)
\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
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
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
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
934 priv->conData.isDeactivated = false;
\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
940 if (!GetUInt16(soc, OFFSET, &priv->conData.syncOffset, true)) RETURN_ASSERT(Parse_XmlError);
\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
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
954 p.usbPort = priv->nodeData.usbPort;
\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
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
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
975 p.mlbPort = priv->nodeData.mlbPort;
\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
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
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
1004 case MSocket_SPLITTER:
\r
1006 mxml_node_t *mostSoc;
\r
1007 struct SplitterParameters p;
\r
1010 UcsXml_CB_OnError("Splitter can not be used as input socket", 0);
\r
1011 RETURN_ASSERT(Parse_XmlError);
\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
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
1033 case MSocket_COMBINER:
\r
1035 struct CombinerParameters p;
\r
1038 UcsXml_CB_OnError("Combiner can not be used as output socket", 0);
\r
1039 RETURN_ASSERT(Parse_XmlError);
\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
1050 RETURN_ASSERT(Parse_XmlError);
\r
1052 /*Handle Pending Combiner Tasks*/
\r
1053 if (NULL != priv->conData.outSocket && NULL != priv->conData.combiner &&
\r
1054 NULL != priv->conData.pendingCombinerMostSockets)
\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
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
1070 /*Connect in and out socket once they are created*/
\r
1071 if (priv->conData.inSocket && priv->conData.outSocket)
\r
1074 bool mostIsOutput;
\r
1075 Ucs_Rm_EndPoint_t *ep;
\r
1076 struct UcsXmlRoute *route;
\r
1077 switch(priv->conData.dataType)
\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
1091 case AV_PACKETIZED:
\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
1103 UcsXml_CB_OnError("Could not connect sockets, data type not implemented: %d", 1, priv->conData.dataType);
\r
1104 RETURN_ASSERT(Parse_XmlError);
\r
1107 ep = MCalloc(&priv->objList, 1, sizeof(Ucs_Rm_EndPoint_t));
\r
1108 if (NULL == ep) RETURN_ASSERT(Parse_MemoryError);
\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
1114 UcsXml_CB_OnError("At least one MOST socket required per connection", 0);
\r
1115 RETURN_ASSERT(Parse_XmlError);
\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
1127 assert(NULL != priv->conData.routeName);
\r
1128 strncpy(route->routeName, priv->conData.routeName, sizeof(route->routeName));
\r
1129 AddRoute(&priv->pRtLst, route);
\r
1131 return Parse_Success;
\r
1134 static ParseResult_t ParseScript(mxml_node_t *scr, PrivateData_t *priv)
\r
1136 bool found = false;
\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
1150 /*Iterate all actions*/
\r
1151 if (!GetElementArray(scr->child, ALL_SCRIPTS, &txt, &act)) RETURN_ASSERT(Parse_XmlError);
\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
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
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
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
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
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
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
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
1186 UcsXml_CB_OnError("Unknown script action:'%s'", 1, txt);
\r
1187 RETURN_ASSERT(Parse_XmlError);
\r
1189 if (!GetElementArray(act, ALL_SCRIPTS, &txt, &act))
\r
1193 if (!GetString(scr, NAME, &txt, true))
\r
1194 RETURN_ASSERT(Parse_XmlError);
\r
1195 while(NULL != scrlist)
\r
1197 if (0 == strcmp(txt, scrlist->scriptName))
\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
1205 scrlist = scrlist->next;
\r
1209 UcsXml_CB_OnError("Script defined:'%s', which was never referenced", 1, txt);
\r
1210 RETURN_ASSERT(Parse_XmlError);
\r
1212 return Parse_Success;
\r
1215 static bool FillScriptInitialValues(Ucs_Ns_Script_t *scr, PrivateData_t *priv)
\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
1227 static ParseResult_t ParseScriptMsgSend(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
\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
1238 if (!GetUInt16(act, FUNCTION_ID, &req->FunktId, true))
\r
1239 RETURN_ASSERT(Parse_XmlError);
\r
1241 if (!GetUInt8(act, OP_TYPE_REQUEST, &req->OpCode, true))
\r
1242 RETURN_ASSERT(Parse_XmlError);
\r
1244 res->FBlockId = req->FBlockId;
\r
1245 res->FunktId = req->FunktId;
\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
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
1257 static ParseResult_t ParseScriptGpioPortCreate(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
\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
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
1282 res->DataPtr[0] = 0x1D;
\r
1283 res->DataPtr[1] = 0x00;
\r
1284 return Parse_Success;
\r
1287 static ParseResult_t ParseScriptGpioPinMode(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
\r
1289 #define PORT_HANDLE_OFFSET (2)
\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
1314 static ParseResult_t ParseScriptGpioPinState(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
\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
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
1349 static ParseResult_t ParseScriptPortCreate(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
\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
1361 else if (0 == strcmp(txt, I2C_SPEED_FAST))
\r
1365 UcsXml_CB_OnError("Invalid I2C speed:'%s'", 1, txt);
\r
1366 RETURN_ASSERT(Parse_XmlError);
\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
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
1385 res->DataPtr[0] = 0x0F;
\r
1386 res->DataPtr[1] = 0x00;
\r
1387 return Parse_Success;
\r
1390 static ParseResult_t ParseScriptPortWrite(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
\r
1392 #define HEADER_OFFSET 8
\r
1394 uint8_t mode, blockCount, address, length, payloadLength;
\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
1401 if (0 == strcmp(txt, I2C_WRITE_MODE_DEFAULT))
\r
1403 else if (0 == strcmp(txt, I2C_WRITE_MODE_REPEAT))
\r
1405 else if (0 == strcmp(txt, I2C_WRITE_MODE_BURST))
\r
1409 UcsXml_CB_OnError("Invalid I2C mode:'%s'", 1, txt);
\r
1410 RETURN_ASSERT(Parse_XmlError);
\r
1415 if (!GetUInt8(act, I2C_WRITE_BLOCK_COUNT, &blockCount, false))
\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
1421 if (!GetUInt16(act, I2C_TIMEOUT, &timeout, false))
\r
1423 if (!GetPayload(act, I2C_PAYLOAD, &payload, &payloadLength, HEADER_OFFSET, &priv->objList, true))
\r
1424 RETURN_ASSERT(Parse_XmlError);
\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
1437 req->DataPtr = payload;
\r
1438 res->DataPtr = MCalloc(&priv->objList, res->DataLen, 1);
\r
1439 if (NULL == res->DataPtr) return Parse_MemoryError;
\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
1450 res->DataPtr[0] = 0x0F;
\r
1451 res->DataPtr[1] = 0x00;
\r
1452 res->DataPtr[2] = address;
\r
1454 res->DataPtr[3] = blockCount * length;
\r
1456 res->DataPtr[3] = length;
\r
1457 return Parse_Success;
\r
1460 static ParseResult_t ParseScriptPortRead(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
\r
1462 uint8_t address, length;
\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
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
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
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
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
1501 static ParseResult_t ParseScriptPause(mxml_node_t *act, Ucs_Ns_Script_t *scr, PrivateData_t *priv)
\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
1509 static ParseResult_t ParseRoutes(UcsXmlVal_t *ucs, PrivateData_t *priv)
\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
1518 if (!sourceRoute->isSource) /*There can be more sinks than sources, so count them*/
\r
1522 sourceRoute = sourceRoute->next;
\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
1529 /*Second: Fill allocated structure now*/
\r
1530 sourceRoute = priv->pRtLst;
\r
1531 while (NULL != sourceRoute)
\r
1533 if (sourceRoute->isSource)
\r
1535 struct UcsXmlRoute *sinkRoute = priv->pRtLst;
\r
1536 while (NULL != sinkRoute)
\r
1538 if (sourceRoute != sinkRoute
\r
1539 && !sinkRoute->isSource
\r
1540 && (0 == strncmp(sourceRoute->routeName, sinkRoute->routeName, sizeof(sourceRoute->routeName))))
\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
1548 sinkRoute = sinkRoute->next;
\r
1551 sourceRoute = sourceRoute->next;
\r
1553 if (routeAmount != ucs->routesSize)
\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
1560 /* Third perform checks when running in debug mode*/
\r
1562 Ucs_Xrm_ResourceType_t *job;
\r
1564 for (i = 0; i < routeAmount; i++)
\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
1577 while((job = ((Ucs_Xrm_ResourceType_t *)route->source_endpoint_ptr->jobs_list_ptr[j])))
\r
1579 assert(UCS_XRM_RC_TYPE_QOS_CON >= *job);
\r
1583 while((job = ((Ucs_Xrm_ResourceType_t *)route->sink_endpoint_ptr->jobs_list_ptr[j])))
\r
1585 assert(UCS_XRM_RC_TYPE_QOS_CON >= *job);
\r
1591 return Parse_Success;
\r