/*------------------------------------------------------------------------------------------------*/\r
-/* Unicens XML Parser */\r
+/* UNICENS XML Parser */\r
/* Copyright 2017, Microchip Technology Inc. and its subsidiaries. */\r
/* */\r
/* Redistribution and use in source and binary forms, with or without */\r
/************************************************************************/\r
\r
#define COMPILETIME_CHECK(cond) (void)sizeof(int[2 * !!(cond) - 1])\r
-#define RETURN_ASSERT(result) { assert(false); return result; }\r
+#define RETURN_ASSERT(result) { UcsXml_CB_OnError("Assertion in file=%s, line=%d", 2, __FILE__, __LINE__); return result; }\r
#define MISC_HB(value) ((uint8_t)((uint16_t)(value) >> 8))\r
#define MISC_LB(value) ((uint8_t)((uint16_t)(value) & (uint16_t)0xFF))\r
\r
\r
struct UcsXmlScript\r
{\r
+ bool inUse;\r
char scriptName[32];\r
Ucs_Rm_Node_t *node;\r
struct UcsXmlScript *next;\r
typedef struct\r
{\r
Ucs_Rm_Node_t *nod;\r
- bool usbPortAddedToJobList; /* USB Port must be added only ONCE to connection job lists */\r
Ucs_Xrm_UsbPort_t *usbPort;\r
- bool mlbPortAddedToJobList; /* MLB Port must be added only ONCE to connection job lists */\r
Ucs_Xrm_MlbPort_t *mlbPort;\r
- bool strmPortsAddedToJobList; /* STRM Ports must be added only ONCE to connection job lists */\r
Ucs_Xrm_StrmPort_t *strmPortA;\r
Ucs_Xrm_StrmPort_t *strmPortB;\r
} NodeData_t;\r
#define MLB_PORT "MediaLBPort"\r
#define USB_PORT "USBPort"\r
#define STRM_PORT "StreamPort"\r
-static const char* ALL_PORTS[] = { MLB_PORT, USB_PORT, STRM_PORT };\r
+static const char* ALL_PORTS[] = { MLB_PORT, USB_PORT, STRM_PORT, NULL };\r
\r
static const char* PHYSICAL_LAYER = "PhysicalLayer";\r
static const char* DEVICE_INTERFACES = "DeviceInterfaces";\r
static bool GetCount(mxml_node_t *element, const char *name, uint32_t *out, bool mandatory);\r
static bool GetCountArray(mxml_node_t *element, const char *array[], uint32_t *out, bool mandatory);\r
static bool GetString(mxml_node_t *element, const char *key, const char **out, bool mandatory);\r
+static bool CheckInteger(const char *val, bool forceHex);\r
static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory);\r
static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory);\r
static bool GetSocketType(const char *txt, MSocketType_t *out);\r
return val;\r
ERROR:\r
if (Parse_MemoryError == result)\r
- UcsXml_CB_OnError("XML error, aborting..", 0);\r
+ UcsXml_CB_OnError("XML memory error, aborting..", 0);\r
else\r
- UcsXml_CB_OnError("Allocation error, aborting..", 0);\r
+ UcsXml_CB_OnError("XML parsing error, aborting..", 0);\r
assert(false);\r
if (!tree)\r
mxmlDelete(tree);\r
return false;\r
}\r
\r
+static bool CheckInteger(const char *value, bool forceHex)\r
+{\r
+ bool hex = forceHex;\r
+ int32_t len;\r
+ if (!value) return false;\r
+ len = strlen(value);\r
+ if (len >= 3 && '0' == value[0] && 'x' == value[1])\r
+ {\r
+ hex = true;\r
+ value += 2;\r
+ }\r
+ while(value[0])\r
+ {\r
+ bool valid = false;\r
+ uint8_t v = value[0];\r
+ if (v >= '0' && v <= '9') valid = true;\r
+ if (hex)\r
+ {\r
+ if (v >= 'a' && v <= 'f') valid = true;\r
+ if (v >= 'A' && v <= 'F') valid = true;\r
+ }\r
+ if (!valid) return false;\r
+ ++value;\r
+ }\r
+ return true;\r
+}\r
+\r
static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory)\r
{\r
+ long int value;\r
const char* txt;\r
if (!GetString(element, key, &txt, mandatory)) return false;\r
- *out = strtol( txt, NULL, 0 );\r
+ if (!CheckInteger(txt, false))\r
+ {\r
+ UcsXml_CB_OnError("key='%s' contained invalid integer='%s'", 2, key, txt);\r
+ return false;\r
+ }\r
+ value = strtol( txt, NULL, 0 );\r
+ if (value > 0xFFFF)\r
+ {\r
+ UcsXml_CB_OnError("key='%s' is out of range='%d'", 2, key, value);\r
+ return false;\r
+ }\r
+ *out = value;\r
return true;\r
}\r
\r
static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory)\r
{\r
+ long int value;\r
const char* txt;\r
if (!GetString(element, key, &txt, mandatory)) return false;\r
- *out = strtol( txt, NULL, 0 );\r
+ if (!CheckInteger(txt, false))\r
+ {\r
+ UcsXml_CB_OnError("key='%s' contained invalid integer='%s'", 2, key, txt);\r
+ return false;\r
+ }\r
+ value = strtol( txt, NULL, 0 );\r
+ if (value > 0xFF)\r
+ {\r
+ UcsXml_CB_OnError("key='%s' is out of range='%d'", 2, key, value);\r
+ return false;\r
+ }\r
+ *out = value;\r
return true;\r
}\r
\r
assert(false);\r
return 0;\r
}\r
+ if (!CheckInteger(token, true))\r
+ {\r
+ UcsXml_CB_OnError("Script payload contains non valid hex number='%s'", 1, token);\r
+ free(txtCopy);\r
+ assert(false);\r
+ return 0;\r
+ }\r
p[offset + len++] = strtol( token, NULL, 16 );\r
token = strtok_r( NULL, " ,.-", &tkPtr );\r
}\r
if (Parse_Success != (result = ParseNode(sub, priv)))\r
return result;\r
/*/Iterate all connections. Node without any connection is also valid.*/\r
- if (!GetElementArray(sub->child, ALL_CONNECTIONS, &conType, &con))\r
- continue;\r
- while(con)\r
+ if (GetElementArray(sub->child, ALL_CONNECTIONS, &conType, &con))\r
{\r
- const char *socTypeStr;\r
- MSocketType_t socType;\r
- mxml_node_t *soc;\r
- memset(&priv->conData, 0, sizeof(ConnectionData_t));\r
- if (Parse_Success != (result = ParseConnection(con, conType, priv)))\r
- return result;\r
- /*Iterate all sockets*/\r
- if(!GetElementArray(con->child, ALL_SOCKETS, &socTypeStr, &soc)) RETURN_ASSERT(Parse_XmlError);\r
- while(soc)\r
+ while(con)\r
{\r
- if (!GetSocketType(socTypeStr, &socType)) RETURN_ASSERT(Parse_XmlError);\r
- if (Parse_Success != (result = ParseSocket(soc, (0 == priv->conData.sockCnt), socType, &priv->conData.jobList, priv)))\r
+ const char *socTypeStr;\r
+ MSocketType_t socType;\r
+ mxml_node_t *soc;\r
+ memset(&priv->conData, 0, sizeof(ConnectionData_t));\r
+ if (Parse_Success != (result = ParseConnection(con, conType, priv)))\r
return result;\r
- ++priv->conData.sockCnt;\r
- if(!GetElementArray(soc, ALL_SOCKETS, &socTypeStr, &soc))\r
+ /*Iterate all sockets*/\r
+ if(!GetElementArray(con->child, ALL_SOCKETS, &socTypeStr, &soc)) RETURN_ASSERT(Parse_XmlError);\r
+ while(soc)\r
+ {\r
+ if (!GetSocketType(socTypeStr, &socType)) RETURN_ASSERT(Parse_XmlError);\r
+ if (Parse_Success != (result = ParseSocket(soc, (0 == priv->conData.sockCnt), socType, &priv->conData.jobList, priv)))\r
+ return result;\r
+ ++priv->conData.sockCnt;\r
+ if(!GetElementArray(soc, ALL_SOCKETS, &socTypeStr, &soc))\r
+ break;\r
+ }\r
+ if(!GetElementArray(con, ALL_CONNECTIONS, &conType, &con))\r
break;\r
}\r
- if(!GetElementArray(con, ALL_CONNECTIONS, &conType, &con))\r
- break;\r
}\r
++ucs->nodSize;\r
if (!GetElement(sub, NODE, false, &sub, false))\r
/*Iterate all scripts. No scripts at all is allowed*/\r
if(GetElement(tree, SCRIPT, true, &sub, false))\r
{\r
+ bool found = true;\r
+ struct UcsXmlScript *scrlist = priv->pScrLst;\r
while(sub)\r
{\r
result = ParseScript(sub, priv);\r
if(!GetElement(sub, SCRIPT, false, &sub, false))\r
break;\r
}\r
+ /* Check if all scripts where referenced */\r
+ while(NULL != scrlist)\r
+ {\r
+ if (!scrlist->inUse)\r
+ {\r
+ UcsXml_CB_OnError("Script not defined:'%s', used by node=0x%X", 1, scrlist->scriptName, scrlist->node->signature_ptr->node_address);\r
+ found = false;\r
+ }\r
+ scrlist = scrlist->next;\r
+ }\r
+ if (!found)\r
+ RETURN_ASSERT(Parse_XmlError);\r
}\r
return result;\r
}\r
UcsXml_CB_OnError("Unknown Port:'%s'", 1, txt);\r
RETURN_ASSERT(Parse_XmlError);\r
}\r
- if(!GetElementArray(port, ALL_SOCKETS, &txt, &port))\r
+ if(!GetElementArray(port, ALL_PORTS, &txt, &port))\r
break;\r
}\r
}\r
RETURN_ASSERT(Parse_XmlError);\r
priv->nodeData.usbPort = (Ucs_Xrm_UsbPort_t *)p.usbPort;\r
}\r
- if (!priv->nodeData.usbPortAddedToJobList)\r
- {\r
- priv->nodeData.usbPortAddedToJobList = true;\r
- if(!AddJob(jobList, p.usbPort, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
- }\r
+ if(!AddJob(jobList, p.usbPort, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
if (!GetString(soc, ENDPOINT_ADDRESS, &p.endpointAddress, true)) RETURN_ASSERT(Parse_XmlError);\r
if (!GetString(soc, FRAMES_PER_TRANSACTION, &p.framesPerTrans, true)) RETURN_ASSERT(Parse_XmlError);\r
if (!GetUsbSocket((Ucs_Xrm_UsbSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);\r
RETURN_ASSERT(Parse_XmlError);\r
priv->nodeData.mlbPort = (Ucs_Xrm_MlbPort_t *)p.mlbPort;\r
}\r
- if (!priv->nodeData.mlbPortAddedToJobList)\r
- {\r
- priv->nodeData.mlbPortAddedToJobList = true;\r
- if (!AddJob(jobList, p.mlbPort, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
- }\r
+ if (!AddJob(jobList, p.mlbPort, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
if (!GetUInt16(soc, BANDWIDTH, &p.bandwidth, true)) RETURN_ASSERT(Parse_XmlError);\r
if (!GetString(soc, CHANNEL_ADDRESS, &p.channelAddress, true)) RETURN_ASSERT(Parse_XmlError);\r
if (!GetMlbSocket((Ucs_Xrm_MlbSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);\r
p.dataType = priv->conData.dataType;\r
p.streamPortA = priv->nodeData.strmPortA;\r
p.streamPortB = priv->nodeData.strmPortB;\r
- if (!priv->nodeData.strmPortsAddedToJobList)\r
- {\r
- priv->nodeData.strmPortsAddedToJobList = true;\r
- if (!AddJob(jobList, p.streamPortA, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
- if (!AddJob(jobList, p.streamPortB, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
- }\r
+ if (!AddJob(jobList, p.streamPortA, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
+ if (!AddJob(jobList, p.streamPortB, &priv->objList)) RETURN_ASSERT(Parse_XmlError);\r
if (!GetUInt16(soc, BANDWIDTH, &p.bandwidth, true)) RETURN_ASSERT(Parse_XmlError);\r
if (!GetString(soc, STRM_PIN, &p.streamPin, true)) RETURN_ASSERT(Parse_XmlError);\r
if (!GetStrmSocket((Ucs_Xrm_StrmSocket_t **)targetSock, &p)) RETURN_ASSERT(Parse_XmlError);\r
/*Connect in and out socket once they are created*/\r
if (priv->conData.inSocket && priv->conData.outSocket)\r
{\r
+ bool mostIsInput;\r
bool mostIsOutput;\r
Ucs_Rm_EndPoint_t *ep;\r
struct UcsXmlRoute *route;\r
ep = MCalloc(&priv->objList, 1, sizeof(Ucs_Rm_EndPoint_t));\r
if (NULL == ep) RETURN_ASSERT(Parse_MemoryError);\r
\r
+ mostIsInput = (UCS_XRM_RC_TYPE_MOST_SOCKET == *((Ucs_Xrm_ResourceType_t *)priv->conData.inSocket));\r
mostIsOutput = (UCS_XRM_RC_TYPE_MOST_SOCKET == *((Ucs_Xrm_ResourceType_t *)priv->conData.outSocket));\r
+ if (!mostIsInput && !mostIsOutput)\r
+ {\r
+ UcsXml_CB_OnError("At least one MOST socket required per connection", 0);\r
+ RETURN_ASSERT(Parse_XmlError);\r
+ }\r
ep->endpoint_type = mostIsOutput ? UCS_RM_EP_SOURCE : UCS_RM_EP_SINK;\r
ep->jobs_list_ptr = GetJobList(*jobList, &priv->objList);\r
if(NULL == ep->jobs_list_ptr) RETURN_ASSERT(Parse_MemoryError);\r
if (Parse_Success != result) return result;\r
} else {\r
UcsXml_CB_OnError("Unknown script action:'%s'", 1, txt);\r
- /*RETURN_ASSERT(Parse_XmlError);*/\r
+ RETURN_ASSERT(Parse_XmlError);\r
}\r
if (!GetElementArray(act, ALL_SCRIPTS, &txt, &act))\r
break;\r
Ucs_Rm_Node_t *node = scrlist->node;\r
node->script_list_ptr = script;\r
node->script_list_size = actCnt;\r
+ scrlist->inUse = true;\r
found = true;\r
}\r
scrlist = scrlist->next;\r
if (!GetUInt8(act, OP_TYPE_REQUEST, &req->OpCode, true))\r
RETURN_ASSERT(Parse_XmlError);\r
\r
- if (!GetUInt8(act, OP_TYPE_RESPONSE, &res->OpCode, true))\r
- RETURN_ASSERT(Parse_XmlError);\r
-\r
res->FBlockId = req->FBlockId;\r
res->FunktId = req->FunktId;\r
- GetPayload(act, PAYLOAD_RES_HEX, &res->DataPtr, &res->DataLen, 0, &priv->objList, false);\r
+\r
+ if (GetUInt8(act, OP_TYPE_RESPONSE, &res->OpCode, false))\r
+ GetPayload(act, PAYLOAD_RES_HEX, &res->DataPtr, &res->DataLen, 0, &priv->objList, false);\r
\r
if (!GetPayload(act, PAYLOAD_REQ_HEX, &req->DataPtr, &req->DataLen, 0, &priv->objList, true))\r
RETURN_ASSERT(Parse_XmlError);\r
speed = 0;\r
else if (0 == strcmp(txt, I2C_SPEED_FAST))\r
speed = 1;\r
- else RETURN_ASSERT(Parse_XmlError);\r
+ else\r
+ {\r
+ UcsXml_CB_OnError("Invalid I2C speed:'%s'", 1, txt);\r
+ RETURN_ASSERT(Parse_XmlError);\r
+ }\r
req = scr->send_cmd;\r
res = scr->exp_result;\r
req->InstId = res->InstId = 1;\r
mode = 1;\r
else if (0 == strcmp(txt, I2C_WRITE_MODE_BURST))\r
mode = 2;\r
+ else\r
+ {\r
+ UcsXml_CB_OnError("Invalid I2C mode:'%s'", 1, txt);\r
+ RETURN_ASSERT(Parse_XmlError);\r
+ }\r
} else {\r
mode = 0;\r
}\r
}\r
sourceRoute = sourceRoute->next;\r
}\r
- assert(routeAmount == ucs->routesSize);\r
+ if (routeAmount != ucs->routesSize)\r
+ {\r
+ UcsXml_CB_OnError("At least one sink (num=%d) is not connected, because of wrong Route name!", 2, (routeAmount - ucs->routesSize));\r
+ RETURN_ASSERT(Parse_XmlError);\r
+ }\r
\r
#ifdef DEBUG\r
/* Third perform checks when running in debug mode*/\r