aboutsummaryrefslogtreecommitdiffstats
path: root/ucs2-interface
diff options
context:
space:
mode:
Diffstat (limited to 'ucs2-interface')
-rw-r--r--ucs2-interface/CMakeLists.txt36
-rw-r--r--ucs2-interface/ucs-xml/UcsXml.c1174
-rw-r--r--ucs2-interface/ucs-xml/UcsXml.h94
-rw-r--r--ucs2-interface/ucs_config.h145
-rw-r--r--ucs2-interface/ucs_interface.h197
-rw-r--r--ucs2-interface/ucs_lib_interf.c647
-rw-r--r--ucs2-interface/ucs_vol_interf.c59
7 files changed, 2352 insertions, 0 deletions
diff --git a/ucs2-interface/CMakeLists.txt b/ucs2-interface/CMakeLists.txt
new file mode 100644
index 0000000..e4db96b
--- /dev/null
+++ b/ucs2-interface/CMakeLists.txt
@@ -0,0 +1,36 @@
+###########################################################################
+# Copyright 2015, 2016, 2017 IoT.bzh
+#
+# author: Fulup Ar Foll <fulup@iot.bzh>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+###########################################################################
+
+# Add target to project dependency list
+PROJECT_TARGET_ADD(ucs2-inter)
+
+ # Define targets
+ ADD_LIBRARY(ucs2-inter STATIC ucs_lib_interf.c ucs_vol_interf.c ucs-xml/UcsXml.c)
+
+ # Library properties
+ SET_TARGET_PROPERTIES(ucs2-inter PROPERTIES OUTPUT_NAME ucs2interface)
+
+ # Depends on Unicens2 lib
+ TARGET_LINK_LIBRARIES(ucs2-inter ucs2-lib ucs2-vol)
+
+ # Define includes
+ TARGET_INCLUDE_DIRECTORIES(ucs2-inter
+ PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+
+
diff --git a/ucs2-interface/ucs-xml/UcsXml.c b/ucs2-interface/ucs-xml/UcsXml.c
new file mode 100644
index 0000000..cd7c477
--- /dev/null
+++ b/ucs2-interface/ucs-xml/UcsXml.c
@@ -0,0 +1,1174 @@
+/*
+ * Unicens XML Parser
+ *
+ * Copyright (C) 2017 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+#include <assert.h>
+#include <string.h>
+#include "mxml.h"
+#include "UcsXml.h"
+
+/************************************************************************/
+/* USER ADJUSTABLE CONSTANTS */
+/************************************************************************/
+
+#define MAX_JOB_LIST_LEN 6
+
+/************************************************************************/
+/* PRIVATE DECLARATIONS */
+/************************************************************************/
+
+#define COMPILETIME_CHECK(cond) (void)sizeof(int[!!(cond) - 1])
+
+struct UcsXmlObjectList
+{
+ void *obj;
+ struct UcsXmlObjectList *next;
+};
+
+struct UcsXmlRouteInfo
+{
+ bool isSource;
+ char routeName[32];
+ Ucs_Rm_EndPoint_t *ep;
+ struct UcsXmlRouteInfo *next;
+};
+
+struct UcsXmlScriptInfo
+{
+ char scriptName[32];
+ Ucs_Rm_Node_t *node;
+ struct UcsXmlScriptInfo *next;
+};
+
+typedef enum
+{
+ SYNC_DATA = 0, /*!< \brief Specifies the synchronous streaming data type */
+ CONTROL_DATA = 2, /*!< \brief Specifies the control data type */
+ AV_PACKETIZED = 3, /*!< \brief Specifies the A/V Packetized Isochronous
+ streaming data type */
+ QOS_IP = 4, /*!< \brief Specifies the Quality of Service IP
+ streaming data type*/
+ DISC_FRAME_PHASE = 5, /*!< \brief Specifies the DiscreteFrame Isochronous
+ streaming phase data type */
+ IPC_PACKET = 7, /*!< \brief Specifies the IPC packet data type */
+ INVALID = 0xFF /*!< \brief Defined invalid value */
+} MData_t;
+
+typedef enum
+{
+ MPORT_MOST,
+ MPORT_USB,
+ MPORT_MLB,
+ MPORT_I2S,
+ MPORT_INVALID = 0xFF
+} MPort_t;
+
+typedef enum
+{
+ Parse_Success = 10,
+ Parse_MemoryError,
+ Parse_XmlError
+} ParseResult_t;
+
+typedef struct {
+ struct UcsXmlObjectList objList;
+ struct UcsXmlRouteInfo *pRtLst;
+ struct UcsXmlScriptInfo *pScrLst;
+ Ucs_Rm_Node_t *nod;
+ Ucs_Xrm_ResObject_t *inSocket;
+ Ucs_Xrm_ResObject_t *outSocket;
+ Ucs_Xrm_ResObject_t **jobList;
+ MData_t dataType;
+ uint16_t blockWidth;
+ const char* chName;
+ uint16_t pause;
+} PrivateData_t;
+
+/************************************************************************/
+/* Constants */
+/************************************************************************/
+
+//Key section
+static const char* UNICENS = "unicens";
+static const char* ASYNC_BANDWIDTH = "async_bandwidth";
+static const char* CHANNEL = "channel";
+static const char* CHANNEL_NAME = "channel_name";
+static const char* ADDRESS = "channel_addr";
+static const char* BANDWIDTH = "bandwidth";
+static const char* OFFSET = "offset";
+static const char* DATA_TYPE = "data_type";
+static const char* DEVICE = "device";
+static const char* DEVICE_MLB_SPEED = "mlb_port_speed";
+static const char* NODE_ADDR = "node_address";
+static const char* DIR = "dir";
+static const char* I2S_PIN = "i2s_pin";
+static const char* PACKETS_XACT = "packets_per_xact";
+static const char* PORT = "port";
+static const char* SOCKET = "socket";
+
+static const char* I2S_FS_SPEED = "i2s_fs_speed";
+static const char* I2S_ALIGN = "i2s_align";
+
+//value section
+static const char* PORT_MOST = "MOST";
+static const char* PORT_USB = "USB";
+static const char* PORT_MLB = "MLB";
+static const char* PORT_I2S = "I2S";
+
+static const char* DATATYPE_SYNC = "SYNC";
+static const char* DATATYPE_AVP = "AVP";
+static const char* DATATYPE_CTRL = "CTRL";
+static const char* DATATYPE_QOS = "QOS";
+static const char* DATATYPE_DFP = "DFP";
+static const char* DATATYPE_IPC = "IPC";
+
+static const char* DIR_IN = "IN";
+static const char* DIR_OUT = "OUT";
+
+static const char* I2S_PIN_SRXA0 = "SRXA0";
+static const char* I2S_PIN_SRXA1 = "SRXA1";
+static const char* I2S_PIN_SRXB0 = "SRXB0";
+static const char* I2S_PIN_SRXB1 = "SRXB1";
+
+static const char* I2S_ALIGN_L16 = "Left16";
+static const char* I2S_ALIGN_L24 = "Left24";
+static const char* I2S_ALIGN_R16 = "Right16";
+static const char* I2S_ALIGN_R24 = "Right24";
+static const char* I2S_ALIGN_SEQUENTIAL = "Seq";
+
+static const char* SCRIPT = "script";
+static const char* ACTION = "action";
+static const char* NAME = "name";
+static const char* TYPE = "type";
+static const char* FBLOCK_ID = "fblock_id";
+static const char* FUNCTION_ID = "function_id";
+static const char* OP_TYPE_REQUEST = "op_request";
+static const char* OP_TYPE_RESPONSE = "op_response";
+static const char* PAYLOAD_REQ_HEX = "load_req_hex";
+static const char* PAYLOAD_RES_HEX = "load_res_hex";
+static const char* PAUSE_MS = "pause_ms";
+
+static const char* SEND_MSG = "SEND_MSG";
+static const char* PAUSE = "PAUSE";
+
+/************************************************************************/
+/* Private Function Prototypes */
+/************************************************************************/
+
+static void *MCalloc(struct UcsXmlObjectList *list, uint32_t nElem, uint32_t elemSize);
+static void FreeObjList(struct UcsXmlObjectList *cur);
+static void FreeVal(UcsXmlVal_t *v);
+static bool GetElement(mxml_node_t *element, const char *name, bool goDeep, mxml_node_t **out, bool mandatory);
+static bool GetCount(mxml_node_t *element, const char *name, uint32_t *out, bool mandatory);
+static bool GetString(mxml_node_t *element, const char *key, const char **out, bool mandatory);
+static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory);
+static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory);
+static bool GetMlbSpeed(mxml_node_t *element, const char *key, Ucs_Mlb_ClockConfig_t *clock, bool mandatory);
+static bool GetI2SSpeed(mxml_node_t *element, const char *key, Ucs_Stream_PortClockConfig_t *clock, bool mandatory);
+static bool GetI2SPin(mxml_node_t *element, Ucs_Stream_PortPinId_t *pin, uint8_t *portIndex, bool mandatory);
+static bool GetI2SAlignment(mxml_node_t *element, Ucs_Stream_PortDataAlign_t *align, bool mandatory);
+static bool GetDirection(mxml_node_t *element, Ucs_SocketDirection_t *out);
+static bool GetDataType(mxml_node_t *element, MData_t *out);
+static bool GetPort(mxml_node_t *element, MPort_t *out);
+static bool GetPayload(mxml_node_t *element, const char *name, uint8_t **pPayload, uint8_t *len,
+ struct UcsXmlObjectList *obj, bool mandatory);
+static bool AddJob(Ucs_Xrm_ResObject_t **joblist, Ucs_Xrm_ResObject_t *job);
+static void AddRoute(struct UcsXmlRouteInfo **pRtLst, struct UcsXmlRouteInfo *route);
+static void AddScript(struct UcsXmlScriptInfo **pScrLst, struct UcsXmlScriptInfo *script);
+static ParseResult_t ParseAll(mxml_node_t *tree, UcsXmlVal_t *v, PrivateData_t *vp);
+static ParseResult_t ParseDevice(mxml_node_t * dev, PrivateData_t *vp);
+static ParseResult_t ParseChannel(mxml_node_t * ch, PrivateData_t *vp);
+static ParseResult_t ParseSocket(mxml_node_t *soc, PrivateData_t *vp);
+static ParseResult_t ParseMostSoc(Ucs_Xrm_MostSocket_t *mostSoc, mxml_node_t *soc, PrivateData_t *vp);
+static ParseResult_t ParseUsbSoc(Ucs_Xrm_UsbSocket_t *usbSoc, mxml_node_t *soc, PrivateData_t *vp);
+static ParseResult_t ParseMlbSoc(Ucs_Xrm_MlbSocket_t *mlbSoc, mxml_node_t *soc, PrivateData_t *vp);
+static ParseResult_t ParseStreamSoc(Ucs_Xrm_StrmSocket_t *strmSoc, mxml_node_t *soc, PrivateData_t *vp);
+static ParseResult_t ParseScript(mxml_node_t *scr, PrivateData_t *vp);
+static ParseResult_t ParseScriptAction(mxml_node_t *act, Ucs_Rm_Node_t *n, uint32_t index, PrivateData_t *vp);
+static ParseResult_t ParseRoutes(UcsXmlVal_t *v, PrivateData_t *vp);
+
+/************************************************************************/
+/* Public Functions */
+/************************************************************************/
+
+UcsXmlVal_t *UcsXml_Parse(const char *xmlString)
+{
+ UcsXmlVal_t *v;
+ ParseResult_t result = Parse_Success;
+ mxml_node_t *tree = mxmlLoadString(NULL, xmlString, MXML_NO_CALLBACK);
+ if (!tree)
+ {
+ result = Parse_XmlError;
+ }
+ if (Parse_Success == result)
+ {
+ if (!GetElement(tree, UNICENS, true, &tree, true))
+ result = Parse_XmlError;
+ }
+ if (Parse_Success == result)
+ {
+ //Do not use MCalloc for the root element
+ v = calloc(1, sizeof(UcsXmlVal_t));
+ if (NULL == v) result = Parse_MemoryError;
+ }
+ if (Parse_Success == result)
+ {
+ //Do not use MCalloc for the private data
+ v->pInternal = calloc(1, sizeof(PrivateData_t));
+ if (NULL == v->pInternal) result = Parse_MemoryError;
+ }
+ if (Parse_Success == result)
+ {
+ result = ParseAll(tree, v, v->pInternal);
+ }
+ if (!tree)
+ {
+ mxmlDelete(tree);
+ }
+ if (Parse_Success == result)
+ {
+ return v;
+ }
+ if (Parse_MemoryError == result)
+ {
+ UcsXml_CB_OnError("XML error, aborting..", 0);
+ }
+ else
+ {
+ UcsXml_CB_OnError("Alloc error, aborting..", 0);
+ }
+ assert(false);
+ FreeVal(v);
+ return NULL;
+}
+
+void UcsXml_FreeVal(UcsXmlVal_t *val)
+{
+ FreeVal(val);
+}
+
+/************************************************************************/
+/* Private Function Implementations */
+/************************************************************************/
+
+static void *MCalloc(struct UcsXmlObjectList *list, uint32_t nElem, uint32_t elemSize)
+{
+ void *obj;
+ struct UcsXmlObjectList *tail = list;
+ if (NULL == list || 0 == nElem || 0 == elemSize) return NULL;
+
+ obj = calloc(nElem, elemSize);
+ if (NULL == obj)
+ {
+ assert(false);
+ return NULL;
+ }
+ if (NULL == list->obj)
+ {
+ list->obj = obj;
+ return obj;
+ }
+ while(tail->next) tail = tail->next;
+ tail->next = calloc(1, sizeof(struct UcsXmlObjectList));
+ if (NULL == tail->next)
+ {
+ assert(false);
+ free(obj);
+ return NULL;
+ }
+ tail->next->obj = obj;
+ return obj;
+}
+
+static void FreeObjList(struct UcsXmlObjectList *cur)
+{
+ struct UcsXmlObjectList *root = cur;
+ while(cur)
+ {
+ struct UcsXmlObjectList *next = cur->next;
+ assert(NULL != cur->obj);
+ if (cur->obj)
+ free(cur->obj);
+ if (cur != root)
+ free(cur);
+ cur = next;
+ }
+}
+
+static void FreeVal(UcsXmlVal_t *v)
+{
+ PrivateData_t *vp;
+ if (NULL == v || NULL == v->pInternal)
+ return;
+ vp = v->pInternal;
+ FreeObjList(&vp->objList);
+ free(v->pInternal);
+ free(v);
+}
+
+static bool GetElement(mxml_node_t *element, const char *name, bool goDeep, mxml_node_t **out, bool mandatory)
+{
+ mxml_node_t *n = element;
+ if (NULL == n || NULL == name || NULL == out) return false;
+ if (goDeep)
+ {
+ *out = mxmlFindElement(n, n, name, NULL, NULL, MXML_DESCEND);
+ return (NULL != *out);
+ }
+ while ((n = n->next))
+ {
+ if (MXML_ELEMENT != n->type)
+ continue;
+ if (0 == strcmp(name, n->value.opaque))
+ {
+ *out = n;
+ return true;
+ }
+ }
+ if (mandatory)
+ UcsXml_CB_OnError("Can not find tag <%s>", 1, name);
+ return false;
+}
+
+static bool GetCount(mxml_node_t *element, const char *name, uint32_t *out, bool mandatory)
+{
+ uint32_t cnt = 0;
+ mxml_node_t *n;
+ if (NULL == element || NULL == name) return false;
+ if(!GetElement(element, name, true, &n, false))
+ return false;
+ while(NULL != n)
+ {
+ ++cnt;
+ if(!GetElement(n, name, false, &n, false))
+ break;
+ }
+ if (mandatory && 0 == cnt)
+ {
+ UcsXml_CB_OnError("element count of <%s> is zero", 1, name);
+ return false;
+ }
+ *out = cnt;
+ return true;
+}
+
+static bool GetString(mxml_node_t *element, const char *key, const char **out, bool mandatory)
+{
+ uint32_t i;
+ if (NULL == element || NULL == key) return false;
+ for (i = 0; i < element->value.element.num_attrs; i++)
+ {
+ mxml_attr_t *attr = &element->value.element.attrs[i];
+ if (0 == strcmp(key, attr->name))
+ {
+ *out = attr->value;
+ return true;
+ }
+ }
+ if (mandatory)
+ UcsXml_CB_OnError("Can not find attribute='%s' from element <%s>",
+ 2, key, element->value.element.name);
+ return false;
+}
+
+static bool GetUInt16(mxml_node_t *element, const char *key, uint16_t *out, bool mandatory)
+{
+ const char* txt;
+ if (!GetString(element, key, &txt, mandatory)) return false;
+ *out = strtol( txt, NULL, 0 );
+ return true;
+}
+
+static bool GetUInt8(mxml_node_t *element, const char *key, uint8_t *out, bool mandatory)
+{
+ const char* txt;
+ if (!GetString(element, key, &txt, mandatory)) return false;
+ *out = strtol( txt, NULL, 0 );
+ return true;
+}
+
+static bool GetMlbSpeed(mxml_node_t *element, const char *key, Ucs_Mlb_ClockConfig_t *clock, bool mandatory)
+{
+ uint16_t speed;
+ if (!GetUInt16(element, DEVICE_MLB_SPEED, &speed, false))
+ return false;
+ switch(speed)
+ {
+ case 256: *clock = UCS_MLB_CLK_CFG_256_FS; break;
+ case 512: *clock = UCS_MLB_CLK_CFG_512_FS; break;
+ case 1024: *clock = UCS_MLB_CLK_CFG_1024_FS; break;
+ case 2048: *clock = UCS_MLB_CLK_CFG_2048_FS; break;
+ case 3072: *clock = UCS_MLB_CLK_CFG_3072_FS; break;
+ case 4096: *clock = UCS_MLB_CLK_CFG_4096_FS; break;
+ case 6144: *clock = UCS_MLB_CLK_CFG_6144_FS; break;
+ case 8192: *clock = UCS_MLB_CLK_CFG_8192_FS; break;
+ case 0: *clock = UCS_MLB_CLK_CFG_WILDCARD; break;
+ default:
+ UcsXml_CB_OnError("Invalid MLB clock val:'%d'", 1, clock);
+ return false;
+ }
+ return true;
+}
+
+static bool GetI2SSpeed(mxml_node_t *element, const char *key, Ucs_Stream_PortClockConfig_t *clock, bool mandatory)
+{
+ uint16_t speed;
+ if (!GetUInt16(element, I2S_FS_SPEED, &speed, false))
+ return false;
+ switch(speed)
+ {
+ case 8: *clock = UCS_STREAM_PORT_CLK_CFG_8FS; break;
+ case 16: *clock = UCS_STREAM_PORT_CLK_CFG_16FS; break;
+ case 32: *clock = UCS_STREAM_PORT_CLK_CFG_32FS; break;
+ case 64: *clock = UCS_STREAM_PORT_CLK_CFG_64FS; break;
+ case 128: *clock = UCS_STREAM_PORT_CLK_CFG_128FS; break;
+ case 256: *clock = UCS_STREAM_PORT_CLK_CFG_256FS; break;
+ case 512: *clock = UCS_STREAM_PORT_CLK_CFG_512FS; break;
+ case 0: *clock = UCS_MLB_CLK_CFG_WILDCARD; break;
+ default:
+ UcsXml_CB_OnError("Invalid I2S clock val:'%d'", 1, clock);
+ return false;
+ }
+ return true;
+}
+
+static bool GetI2SPin(mxml_node_t *element, Ucs_Stream_PortPinId_t *pin, uint8_t *portIndex, bool mandatory)
+{
+ const char *txt;
+ if (!GetString(element, I2S_PIN, &txt, true))
+ return false;
+ if (0 == strcmp(I2S_PIN_SRXA0, txt))
+ {
+ *pin = UCS_STREAM_PORT_PIN_ID_SRXA0;
+ *portIndex = 0;
+ return true;
+ }
+ else if (0 == strcmp(I2S_PIN_SRXA1, txt))
+ {
+ *pin = UCS_STREAM_PORT_PIN_ID_SRXA1;
+ *portIndex = 0;
+ return true;
+ }
+ else if (0 == strcmp(I2S_PIN_SRXB0, txt))
+ {
+ *pin = UCS_STREAM_PORT_PIN_ID_SRXB0;
+ *portIndex = 1;
+ return true;
+ }
+ else if (0 == strcmp(I2S_PIN_SRXB1, txt))
+ {
+ *pin = UCS_STREAM_PORT_PIN_ID_SRXB1;
+ *portIndex = 1;
+ return true;
+ }
+ UcsXml_CB_OnError("Invalid I2S pin val:'%s'", 1, txt);
+ return false;
+}
+
+static bool GetI2SAlignment(mxml_node_t *element, Ucs_Stream_PortDataAlign_t *align, bool mandatory)
+{
+ const char *txt;
+ if (!GetString(element, I2S_ALIGN, &txt, true))
+ return false;
+ if (0 == strcmp(I2S_ALIGN_L16, txt))
+ *align = UCS_STREAM_PORT_ALGN_LEFT16BIT;
+ else if (0 == strcmp(I2S_ALIGN_L24, txt))
+ *align = UCS_STREAM_PORT_ALGN_LEFT24BIT;
+ else if (0 == strcmp(I2S_ALIGN_R16, txt))
+ *align = UCS_STREAM_PORT_ALGN_RIGHT16BIT;
+ else if (0 == strcmp(I2S_ALIGN_R24, txt))
+ *align = UCS_STREAM_PORT_ALGN_RIGHT24BIT;
+ else if (0 == strcmp(I2S_ALIGN_SEQUENTIAL, txt))
+ *align = UCS_STREAM_PORT_ALGN_SEQ;
+ else
+ {
+ UcsXml_CB_OnError("Invalid I2S alignment:'%s'", 1, txt);
+ return false;
+ }
+ return true;
+}
+
+static bool GetDirection(mxml_node_t *element, Ucs_SocketDirection_t *out)
+{
+ const char *txt;
+ if (!GetString(element, DIR, &txt, true)) return false;
+ if (0 == strcmp(DIR_IN, txt))
+ *out = UCS_SOCKET_DIR_INPUT;
+ else if (0 == strcmp(DIR_OUT, txt))
+ *out = UCS_SOCKET_DIR_OUTPUT;
+ else
+ return false;
+ return true;
+}
+
+static bool GetDataType(mxml_node_t *element, MData_t *out)
+{
+ const char *txt;
+ if (!GetString(element, DATA_TYPE, &txt, true)) return false;
+ if (0 == strcmp(DATATYPE_SYNC, txt)) {
+ *out = SYNC_DATA;
+ } else if (0 == strcmp(DATATYPE_CTRL, txt)) {
+ *out = CONTROL_DATA;
+ } else if (0 == strcmp(DATATYPE_AVP, txt)) {
+ *out = AV_PACKETIZED;
+ } else if (0 == strcmp(DATATYPE_QOS, txt)) {
+ *out = QOS_IP;
+ } else if (0 == strcmp(DATATYPE_DFP, txt)) {
+ *out = DISC_FRAME_PHASE;
+ } else if (0 == strcmp(DATATYPE_IPC, txt)) {
+ *out = IPC_PACKET;
+ } else {
+ UcsXml_CB_OnError("Unknown data type : '%s'", 1, txt);
+ return false;
+ }
+ return true;
+}
+
+static bool GetPort(mxml_node_t *element, MPort_t *out)
+{
+ const char *txt;
+ if (!GetString(element, PORT, &txt, true)) return false;
+ if (0 == strcmp(txt, PORT_MOST)) {
+ *out = MPORT_MOST;
+ } else if (0 == strcmp(txt, PORT_USB)) {
+ *out = MPORT_USB;
+ } else if (0 == strcmp(txt, PORT_MLB)) {
+ *out = MPORT_MLB;
+ } else if (0 == strcmp(txt, PORT_I2S)) {
+ *out = MPORT_I2S;
+ } else {
+ UcsXml_CB_OnError("Unknown port : '%s'", 1, txt);
+ return false;
+ }
+ return true;
+}
+
+static bool GetPayload(mxml_node_t *element, const char *name, uint8_t **pPayload, uint8_t *outLen, struct UcsXmlObjectList *obj, bool mandatory)
+{
+ uint32_t tempLen, len = 0;
+ uint8_t *p;
+ const char *txt;
+ char *txtCopy;
+ char *tkPtr;
+ char *token;
+ if (!GetString(element, name, &txt, mandatory))
+ return false;
+ tempLen = strlen(txt) + 1;
+ txtCopy = malloc(tempLen);
+ if (NULL == txtCopy)
+ return false;
+ strncpy(txtCopy, txt, tempLen);
+ tempLen = tempLen / 3; /* 2 chars hex value plus space (AA ) */
+ p = MCalloc(obj, tempLen, 1);
+ if (NULL == p)
+ {
+ free(txtCopy);
+ return false;
+ }
+ *pPayload = p;
+ token = strtok_r( txtCopy, " ,.-", &tkPtr );
+ while( NULL != token )
+ {
+ if( len >= tempLen )
+ {
+ UcsXml_CB_OnError("Script payload values must be stuffed to two characters", 0);
+ free(txtCopy);
+ assert(false);
+ return 0;
+ }
+ p[len++] = strtol( token, NULL, 16 );
+ token = strtok_r( NULL, " ,.-", &tkPtr );
+ }
+ *outLen = len;
+ return true;
+}
+
+static bool AddJob(Ucs_Xrm_ResObject_t **joblist, Ucs_Xrm_ResObject_t *job)
+{
+ uint32_t i;
+ if (NULL == joblist || NULL == job)
+ {
+ assert(false);
+ return false;
+ }
+ for (i = 0; i < MAX_JOB_LIST_LEN; i++)
+ {
+ if (NULL == joblist[i])
+ {
+ joblist[i] = job;
+ return true;
+ }
+ }
+ assert(false);
+ return false;
+}
+
+static void AddRoute(struct UcsXmlRouteInfo **pRtLst, struct UcsXmlRouteInfo *route)
+{
+ struct UcsXmlRouteInfo *tail;
+ if (NULL == pRtLst || NULL == route) return;
+ if (NULL == pRtLst[0])
+ {
+ pRtLst[0] = route;
+ return;
+ }
+ tail = pRtLst[0];
+ while(tail->next) tail = tail->next;
+ tail->next = route;
+}
+
+static void AddScript(struct UcsXmlScriptInfo **pScrLst, struct UcsXmlScriptInfo *script)
+{
+ struct UcsXmlScriptInfo *tail;
+ if (NULL == pScrLst || NULL == script) return;
+ if (NULL == pScrLst[0])
+ {
+ pScrLst[0] = script;
+ return;
+ }
+ tail = pScrLst[0];
+ while(tail->next) tail = tail->next;
+ tail->next = script;
+}
+
+static ParseResult_t ParseAll(mxml_node_t *tree, UcsXmlVal_t *v, PrivateData_t *vp)
+{
+ uint32_t devCount;
+ mxml_node_t *sub;
+ ParseResult_t result;
+ if (!GetCount(tree, DEVICE, &devCount, true))
+ return Parse_XmlError;
+
+ v->pNod = MCalloc(&vp->objList, devCount, sizeof(Ucs_Rm_Node_t));
+ if (NULL == v->pNod) return Parse_MemoryError;
+
+ if (!GetUInt16(tree, ASYNC_BANDWIDTH, &v->packetBw, true))
+ return Parse_XmlError;
+
+ ///Iterate all devices
+ if (!GetElement(tree, DEVICE, true, &sub, true))
+ return Parse_XmlError;
+ while(sub)
+ {
+ mxml_node_t *ch;
+ vp->nod = &v->pNod[v->nodSize];
+ if (Parse_Success != (result = ParseDevice(sub, vp)))
+ return result;
+ ///Iterate all channels. Device without any channel is also valid.
+ if (GetElement(sub->child, CHANNEL, false, &ch, false))
+ {
+ while(ch)
+ {
+ mxml_node_t *soc;
+ uint8_t sockCnt = 0;
+ if (Parse_Success != (result = ParseChannel(ch, vp)))
+ return result;
+ ///Iterate all sockets
+ if(!GetElement(ch->child, SOCKET, false, &soc, true))
+ return Parse_XmlError;
+ while(soc)
+ {
+ ParseResult_t result;
+ if (Parse_Success != (result = ParseSocket(soc, vp)))
+ return result;
+ ++sockCnt;
+ if (!GetElement(soc, SOCKET, false, &soc, false))
+ break;
+ }
+ if (2 != sockCnt)
+ {
+ UcsXml_CB_OnError("%d sockets per channel found, must be 2", 1, sockCnt);
+ return Parse_XmlError;
+ }
+ if (!GetElement(ch, CHANNEL, false, &ch, false))
+ break;
+ }
+ }
+ ++v->nodSize;
+ if (!GetElement(sub, DEVICE, false, &sub, false))
+ break;
+ }
+
+ ///Fill route structures
+ result = ParseRoutes(v, vp);
+ if (Parse_MemoryError == result) return Parse_MemoryError;
+ else if (Parse_XmlError == result) return Parse_XmlError;
+
+ ///Iterate all scripts. No scripts at all is allowed
+ if(GetElement(tree, SCRIPT, true, &sub, false))
+ {
+ while(sub)
+ {
+ ParseResult_t result = ParseScript(sub, vp);
+ if (Parse_MemoryError == result) return Parse_MemoryError;
+ else if (Parse_XmlError == result) return Parse_XmlError;
+ if(!GetElement(sub, SCRIPT, false, &sub, false))
+ break;
+ }
+ }
+ return result;
+}
+
+static ParseResult_t ParseDevice(mxml_node_t * dev, PrivateData_t *vp)
+{
+ const char *txt;
+ assert(NULL != dev && NULL != vp);
+ vp->nod->signature_ptr = MCalloc(&vp->objList, 1, sizeof(Ucs_Signature_t));
+ if(NULL == vp->nod->signature_ptr) return Parse_MemoryError;
+ if (!GetUInt16(dev, NODE_ADDR, &vp->nod->signature_ptr->node_address, true))
+ return Parse_XmlError;
+ if (GetString(dev, SCRIPT, &txt, false))
+ {
+ struct UcsXmlScriptInfo *scr = MCalloc(&vp->objList, 1, sizeof(struct UcsXmlScriptInfo));
+ if (NULL == scr) return Parse_MemoryError;
+ scr->node = vp->nod;
+ strncpy(scr->scriptName, txt, sizeof(scr->scriptName));
+ AddScript(&vp->pScrLst, scr);
+ }
+ return Parse_Success;;
+}
+
+static ParseResult_t ParseChannel(mxml_node_t *ch, PrivateData_t *vp)
+{
+ vp->inSocket = NULL;
+ vp->outSocket = NULL;
+ vp->jobList = NULL;
+ vp->dataType = 0xFF;
+ vp->blockWidth = 0;
+ vp->chName = NULL;
+ assert(NULL != ch && NULL != vp);
+ if (!GetString(ch, CHANNEL_NAME, &vp->chName, true))
+ return Parse_XmlError;
+ if (!GetDataType(ch, &vp->dataType))
+ return Parse_XmlError;
+ if (!GetUInt16(ch, BANDWIDTH, &vp->blockWidth, true))
+ return Parse_XmlError;
+ vp->jobList = MCalloc(&vp->objList, MAX_JOB_LIST_LEN, sizeof(Ucs_Xrm_ResObject_t *));
+ if (NULL == vp->jobList) return Parse_MemoryError;
+ return Parse_Success;
+}
+
+static ParseResult_t ParseSocket(mxml_node_t *soc, PrivateData_t *vp)
+{
+ MPort_t port;
+ bool isIn = false;
+ bool isSource = false;
+ uint16_t offset = 0;
+ assert(NULL != soc && NULL != vp);
+ Ucs_SocketDirection_t direction;
+ if (!GetDirection(soc, &direction))
+ return Parse_XmlError;
+ isIn = (UCS_SOCKET_DIR_INPUT == direction);
+ if (!GetPort(soc, &port))
+ return Parse_XmlError;
+ switch(port)
+ {
+ case MPORT_MOST:
+ {
+ Ucs_Xrm_MostSocket_t *sock = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_MostSocket_t));
+ if (NULL == sock) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, sock)) return Parse_XmlError;
+ sock->data_type = vp->dataType;
+ sock->bandwidth = vp->blockWidth;
+ if (Parse_Success != ParseMostSoc(sock, soc, vp))
+ return Parse_XmlError;
+ isSource = (UCS_SOCKET_DIR_OUTPUT == direction);
+ if (isIn) vp->inSocket = sock; else vp->outSocket = sock;
+ break;
+ }
+ case MPORT_USB:
+ {
+ Ucs_Xrm_UsbSocket_t *sock = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_UsbSocket_t));
+ if (NULL == sock) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, sock)) return Parse_XmlError;
+ sock->data_type = vp->dataType;
+ if (Parse_Success != ParseUsbSoc(sock, soc, vp))
+ return Parse_XmlError;
+ if (isIn) vp->inSocket = sock; else vp->outSocket = sock;
+ break;
+ }
+ case MPORT_MLB:
+ {
+ Ucs_Xrm_MlbSocket_t *sock = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_MlbSocket_t));
+ if (NULL == sock) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, sock)) return Parse_XmlError;
+ sock->data_type = vp->dataType;
+ sock->bandwidth = vp->blockWidth;
+ if (Parse_Success != ParseMlbSoc(sock, soc, vp))
+ return Parse_XmlError;
+ if (isIn) vp->inSocket = sock; else vp->outSocket = sock;
+ break;
+ }
+ case MPORT_I2S:
+ {
+ Ucs_Xrm_StrmSocket_t *sock = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_StrmSocket_t));
+ if (NULL == sock) return Parse_MemoryError;
+ sock->data_type = vp->dataType;
+ sock->bandwidth = vp->blockWidth;
+ if (Parse_Success != ParseStreamSoc(sock, soc, vp))
+ return Parse_XmlError;
+ if (isIn) vp->inSocket = sock; else vp->outSocket = sock;
+ break;
+ }
+ default:
+ assert(false);
+ return Parse_XmlError;
+ }
+ if (GetUInt16(soc, OFFSET, &offset, false))
+ {
+ //TODO: If offset is non zero allocate Splitter / Combiner
+ }
+ //Connect in and out socket once they are created
+ if (vp->inSocket && vp->outSocket)
+ {
+ switch(vp->dataType)
+ {
+ case AV_PACKETIZED:
+ {
+ Ucs_Xrm_AvpCon_t *con = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_AvpCon_t));
+ if (NULL == con) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, con))
+ return Parse_XmlError;
+ con->resource_type = UCS_XRM_RC_TYPE_AVP_CON;
+ con->socket_in_obj_ptr = vp->inSocket;
+ con->socket_out_obj_ptr = vp->outSocket;
+ con->isoc_packet_size = UCS_ISOC_PCKT_SIZE_188; //TODO:Read from XML
+ break;
+ }
+ case SYNC_DATA:
+ {
+ Ucs_Xrm_SyncCon_t *con = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_SyncCon_t));
+ if (NULL == con) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, con))
+ return Parse_XmlError;
+ con->resource_type = UCS_XRM_RC_TYPE_SYNC_CON;
+ con->socket_in_obj_ptr = vp->inSocket;
+ con->socket_out_obj_ptr = vp->outSocket;
+ con->mute_mode = UCS_SYNC_MUTE_MODE_NO_MUTING; //TODO:Read from XML
+ con->offset = offset;
+ break;
+ }
+ default:
+ UcsXml_CB_OnError("Could not connect sockets, data type not implemented: %d", 1, vp->dataType);
+ return Parse_XmlError;
+ break;
+ }
+ Ucs_Rm_EndPoint_t *ep = MCalloc(&vp->objList, 1, sizeof(Ucs_Rm_EndPoint_t));
+ if (NULL == ep) return Parse_MemoryError;
+ ep->endpoint_type = isSource ? UCS_RM_EP_SOURCE : UCS_RM_EP_SINK;
+ ep->jobs_list_ptr = vp->jobList;
+ ep->node_obj_ptr = vp->nod;
+
+ struct UcsXmlRouteInfo *route = MCalloc(&vp->objList, 1, sizeof(struct UcsXmlRouteInfo));
+ if (NULL == route) return Parse_MemoryError;
+ route->isSource = isSource;
+ route->ep = ep;
+ strncpy(route->routeName, vp->chName, sizeof(route->routeName));
+ AddRoute(&vp->pRtLst, route);
+ }
+ return Parse_Success;
+}
+
+static ParseResult_t ParseMostSoc(Ucs_Xrm_MostSocket_t *mostSoc, mxml_node_t *soc, PrivateData_t *vp)
+{
+ assert(NULL != mostSoc && NULL != soc && NULL != vp);
+ COMPILETIME_CHECK(SYNC_DATA == (MData_t)UCS_MOST_SCKT_SYNC_DATA);
+ COMPILETIME_CHECK(AV_PACKETIZED == (MData_t)UCS_MOST_SCKT_AV_PACKETIZED);
+ COMPILETIME_CHECK(QOS_IP == (MData_t)UCS_MOST_SCKT_QOS_IP);
+ COMPILETIME_CHECK(DISC_FRAME_PHASE == (MData_t)UCS_MOST_SCKT_DISC_FRAME_PHASE);
+ switch((MData_t)mostSoc->data_type)
+ {
+ case SYNC_DATA:
+ case AV_PACKETIZED:
+ case QOS_IP:
+ case DISC_FRAME_PHASE:
+ break; //Nothing to do, valid values.
+ default:
+ UcsXml_CB_OnError("Invalid DataType=%d for MOST socket", 1, mostSoc->data_type);
+ return Parse_XmlError;
+ }
+ mostSoc->resource_type = UCS_XRM_RC_TYPE_MOST_SOCKET;
+ mostSoc->most_port_handle = 0x0D00;
+ if (!GetDirection(soc, &mostSoc->direction))
+ return Parse_XmlError;
+ return Parse_Success;
+}
+
+static ParseResult_t ParseUsbSoc(Ucs_Xrm_UsbSocket_t *usbSoc, mxml_node_t *soc, PrivateData_t *vp)
+{
+ Ucs_Xrm_DefaultCreatedPort_t *p;
+ assert(NULL != usbSoc && NULL != soc && NULL != vp);
+ COMPILETIME_CHECK(SYNC_DATA == (MData_t)UCS_USB_SCKT_SYNC_DATA);
+ COMPILETIME_CHECK(CONTROL_DATA == (MData_t)UCS_USB_SCKT_CONTROL_DATA);
+ COMPILETIME_CHECK(AV_PACKETIZED == (MData_t)UCS_USB_SCKT_AV_PACKETIZED);
+ switch((MData_t)usbSoc->data_type)
+ {
+ case SYNC_DATA:
+ case CONTROL_DATA:
+ case AV_PACKETIZED:
+ break; //Nothing to do, valid values.
+ default:
+ UcsXml_CB_OnError("Invalid DataType=%d for USB socket", 1, usbSoc->data_type);
+ return Parse_XmlError;
+ }
+ usbSoc->resource_type = UCS_XRM_RC_TYPE_USB_SOCKET;
+ if (!GetDirection(soc, &usbSoc->direction))
+ return Parse_XmlError;
+ if (!GetUInt8(soc, ADDRESS, &usbSoc->end_point_addr, true))
+ return Parse_XmlError;
+
+ if (!GetUInt16(soc, PACKETS_XACT, &usbSoc->frames_per_transfer, true))
+ return Parse_XmlError;
+
+ //XML provides currently no way to open USB port, so use ConfigString default
+ p = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_DefaultCreatedPort_t));
+ if (NULL == p) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, p)) return Parse_MemoryError;
+ p->resource_type = UCS_XRM_RC_TYPE_DC_PORT;
+ p->port_type = UCS_XRM_PORT_TYPE_USB;
+ p->index = 0;
+ usbSoc->usb_port_obj_ptr = p;
+ return Parse_Success;
+}
+
+static ParseResult_t ParseMlbSoc(Ucs_Xrm_MlbSocket_t *mlbSoc, mxml_node_t *soc, PrivateData_t *vp)
+{
+ Ucs_Mlb_ClockConfig_t clock;
+ assert(NULL != mlbSoc && NULL != soc && NULL != vp);
+ COMPILETIME_CHECK(SYNC_DATA == (MData_t)UCS_MLB_SCKT_SYNC_DATA);
+ COMPILETIME_CHECK(CONTROL_DATA == (MData_t)UCS_MLB_SCKT_CONTROL_DATA);
+ COMPILETIME_CHECK(AV_PACKETIZED == (MData_t)UCS_USB_SCKT_AV_PACKETIZED);
+ COMPILETIME_CHECK(QOS_IP == (MData_t)UCS_MLB_SCKT_QOS_IP);
+ COMPILETIME_CHECK(DISC_FRAME_PHASE == (MData_t)UCS_MLB_SCKT_DISC_FRAME_PHASE);
+ COMPILETIME_CHECK(IPC_PACKET == (MData_t)UCS_MLB_SCKT_IPC_PACKET);
+ switch((MData_t)mlbSoc->data_type)
+ {
+ case SYNC_DATA:
+ case CONTROL_DATA:
+ case AV_PACKETIZED:
+ case QOS_IP:
+ case DISC_FRAME_PHASE:
+ case IPC_PACKET:
+ break; //Nothing to do, valid values.
+ default:
+ UcsXml_CB_OnError("Invalid DataType=%d for MLB socket", 1, mlbSoc->data_type);
+ return Parse_XmlError;
+ }
+ mlbSoc->resource_type = UCS_XRM_RC_TYPE_MLB_SOCKET;
+ if (!GetDirection(soc, &mlbSoc->direction))
+ return Parse_XmlError;
+ if (!GetUInt16(soc, ADDRESS, &mlbSoc->channel_address, true))
+ return Parse_XmlError;
+
+ //Create MLB port when DEVICE_MLB_SPEED is defined, otherwise use ConfigString default
+ if (GetMlbSpeed(soc, DEVICE_MLB_SPEED, &clock, false))
+ {
+ Ucs_Xrm_MlbPort_t *p = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_MlbPort_t));
+ if (NULL == p) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, p)) return Parse_MemoryError;
+ p->resource_type = UCS_XRM_RC_TYPE_MLB_PORT;
+ p->index = 0;
+ p->clock_config = clock;
+ mlbSoc->mlb_port_obj_ptr = p;
+ } else {
+ Ucs_Xrm_DefaultCreatedPort_t *p = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_DefaultCreatedPort_t));
+ if (NULL == p) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, p)) return Parse_MemoryError;
+ p->resource_type = UCS_XRM_RC_TYPE_DC_PORT;
+ p->port_type = UCS_XRM_PORT_TYPE_MLB;
+ p->index = 0;
+ mlbSoc->mlb_port_obj_ptr = p;
+ }
+ return Parse_Success;
+}
+
+static ParseResult_t ParseStreamSoc(Ucs_Xrm_StrmSocket_t *strmSoc, mxml_node_t *soc, PrivateData_t *vp)
+{
+ const char *txt;
+ Ucs_Xrm_StrmPort_t *strPort;
+ assert(NULL != strmSoc && NULL != soc && NULL != vp);
+ COMPILETIME_CHECK(SYNC_DATA == (MData_t)UCS_STREAM_PORT_SCKT_SYNC_DATA);
+ if (SYNC_DATA != (MData_t)strmSoc->data_type)
+ {
+ UcsXml_CB_OnError("Invalid DataType=%d for I2S socket", 1, strmSoc->data_type);
+ return Parse_XmlError;
+ }
+ strPort = MCalloc(&vp->objList, 1, sizeof(Ucs_Xrm_StrmPort_t));
+ if (NULL == strPort) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, strPort)) return Parse_MemoryError;
+ if (!AddJob(vp->jobList, strmSoc)) return Parse_MemoryError;
+ strmSoc->resource_type = UCS_XRM_RC_TYPE_STRM_SOCKET;
+ strmSoc->stream_port_obj_ptr = strPort;
+
+ strPort->resource_type = UCS_XRM_RC_TYPE_STRM_PORT;
+ if (!GetDirection(soc, &strmSoc->direction))
+ return Parse_XmlError;
+ if (!GetI2SPin(soc, &strmSoc->stream_pin_id, &strPort->index, true))
+ return Parse_XmlError;
+ if (!GetI2SSpeed(soc, I2S_FS_SPEED, &strPort->clock_config, true))
+ return Parse_XmlError;
+ if (!GetString(soc, I2S_ALIGN, &txt, true))
+ return Parse_XmlError;
+ if (!GetI2SAlignment(soc, &strPort->data_alignment, true))
+ return Parse_XmlError;
+ return Parse_Success;
+}
+
+static ParseResult_t ParseScript(mxml_node_t *scr, PrivateData_t *vp)
+{
+ mxml_node_t *act;
+ uint32_t actCnt;
+ uint32_t i = 0;
+ const char *txt;
+ assert(NULL != scr && NULL != vp);
+ vp->pause = 0;
+ if (!GetString(scr, NAME, &txt, true))
+ return Parse_XmlError;
+ Ucs_Rm_Node_t *n = NULL;
+ struct UcsXmlScriptInfo *scrlist = vp->pScrLst;
+ while(NULL != scrlist)
+ {
+ if (0 == strcmp(txt, scrlist->scriptName))
+ {
+ n = scrlist->node;
+ break;
+ }
+ scrlist = scrlist->next;
+ }
+ if (NULL == n)
+ {
+ UcsXml_CB_OnError("Script defined:'%s', which was never referenced", 1, txt);
+ return Parse_XmlError;
+ }
+ if (!GetCount(scr, ACTION, &actCnt, true)) return Parse_XmlError;
+ if (NULL == (n->script_list_ptr = MCalloc(&vp->objList, actCnt, sizeof(Ucs_Ns_Script_t))))
+ return Parse_MemoryError;
+ n->script_list_size = actCnt;
+ ///Iterate all actions
+ if (!GetElement(scr, ACTION, true, &act, true)) return false;
+ while(act)
+ {
+ ParseResult_t result = ParseScriptAction(act, n, i, vp);
+ if (Parse_Success != result) return result;
+ if (!GetElement(act, ACTION, false, &act, false))
+ break;
+ ++i;
+ }
+ return Parse_Success;
+}
+
+static ParseResult_t ParseScriptAction(mxml_node_t *act, Ucs_Rm_Node_t *n, uint32_t index, PrivateData_t *vp)
+{
+ const char *txt;
+ uint8_t opResult;
+ assert(NULL != act && NULL != vp);
+ Ucs_Ns_Script_t *scr = &n->script_list_ptr[index];
+ if (!GetString(act, TYPE, &txt, true))
+ return Parse_XmlError;
+ if (0 == strcmp(txt, SEND_MSG))
+ {
+ Ucs_Ns_ConfigMsg_t *req;
+ scr->send_cmd = MCalloc(&vp->objList, 1, sizeof(Ucs_Ns_ConfigMsg_t));
+ req = scr->send_cmd;
+ if (NULL == req) return Parse_MemoryError;
+ scr->pause = vp->pause;
+ if (vp->pause) vp->pause = 0;
+ req->InstId = 1;
+ if (!GetUInt8(act, FBLOCK_ID, &req->FBlockId, true))
+ return Parse_XmlError;
+
+ if (!GetUInt16(act, FUNCTION_ID, &req->FunktId, true))
+ return Parse_XmlError;
+
+ if (!GetUInt8(act, OP_TYPE_REQUEST, &req->OpCode, true))
+ return Parse_XmlError;
+
+ if (GetUInt8(act, OP_TYPE_RESPONSE, &opResult, false))
+ {
+ //Waiting for response is optional
+ Ucs_Ns_ConfigMsg_t *res;
+ scr->exp_result = MCalloc(&vp->objList, 1, sizeof(Ucs_Ns_ConfigMsg_t));
+ res = scr->exp_result;
+ res->FBlockId = req->FBlockId;
+ res->InstId = req->InstId;
+ res->FunktId = req->FunktId;
+ res->OpCode = opResult;
+ //Not interested in result:
+ GetPayload(act, PAYLOAD_RES_HEX, &res->DataPtr, &res->DataLen, &vp->objList, false);
+ }
+ if (!GetPayload(act, PAYLOAD_REQ_HEX, &req->DataPtr, &req->DataLen, &vp->objList, true))
+ return Parse_XmlError;
+ if (0 == req->DataLen || NULL == req->DataPtr)
+ return Parse_XmlError;
+ }
+ else if (0 == strcmp(txt, PAUSE))
+ {
+ if (!GetUInt16(act, PAUSE_MS, &vp->pause, true))
+ return Parse_XmlError;
+ }
+ return Parse_Success;
+}
+
+static ParseResult_t ParseRoutes(UcsXmlVal_t *v, PrivateData_t *vp)
+{
+ uint16_t routeAmount = 0;
+ struct UcsXmlRouteInfo *sourceRoute;
+ assert(NULL != v && NULL != vp);
+ //First: Count the amount of routes and allocate the correct amount
+ sourceRoute = vp->pRtLst;
+ while (NULL != sourceRoute)
+ {
+ if (!sourceRoute->isSource) //There can be more sinks than sources, so count them
+ {
+ ++routeAmount;
+ }
+ sourceRoute = sourceRoute->next;
+ }
+ if (0 == routeAmount)
+ return Parse_Success; //Its okay to have no routes at all (e.g. MEP traffic only)
+ v->pRoutes = MCalloc(&vp->objList, routeAmount, sizeof(Ucs_Rm_Route_t));
+ if (NULL == v->pRoutes) return Parse_MemoryError;
+
+ //Second: Fill allocated structure now
+ sourceRoute = vp->pRtLst;
+ while (NULL != sourceRoute)
+ {
+ if (sourceRoute->isSource)
+ {
+ struct UcsXmlRouteInfo *sinkRoute = vp->pRtLst;
+ while (NULL != sinkRoute)
+ {
+ if (sourceRoute != sinkRoute
+ && !sinkRoute->isSource
+ && (0 == strncmp(sourceRoute->routeName, sinkRoute->routeName, sizeof(sourceRoute->routeName))))
+ {
+ Ucs_Rm_Route_t *route = &v->pRoutes[v->routesSize++];
+ route->source_endpoint_ptr = sourceRoute->ep;
+ route->sink_endpoint_ptr = sinkRoute->ep;
+ route->active = 1;
+ }
+ sinkRoute = sinkRoute->next;
+ }
+ }
+ sourceRoute = sourceRoute->next;
+ }
+ return Parse_Success;
+}
diff --git a/ucs2-interface/ucs-xml/UcsXml.h b/ucs2-interface/ucs-xml/UcsXml.h
new file mode 100644
index 0000000..883a9ff
--- /dev/null
+++ b/ucs2-interface/ucs-xml/UcsXml.h
@@ -0,0 +1,94 @@
+/*
+ * Unicens XML Parser
+ *
+ * Copyright (C) 2017 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+#ifndef UCSXML_H_
+#define UCSXML_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "ucs_api.h"
+
+/** Structure holding informations to startup Unicens (UCS).
+ * Pass all these variables to the UCS manager structure, but not pInternal.
+ * */
+typedef struct
+{
+ /** The amount of bytes assigned to the async channel*/
+ uint16_t packetBw;
+ /** Array of routes */
+ Ucs_Rm_Route_t *pRoutes;
+ /** Route array size */
+ uint16_t routesSize;
+ /** Array of nodes */
+ Ucs_Rm_Node_t *pNod;
+ /** Node array size */
+ uint16_t nodSize;
+ /** Internal data, to be ignored */
+ void *pInternal;
+} UcsXmlVal_t;
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+/* Public API */
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+/**
+ * \brief Initializes Unicens XML parser module, parses the given string and
+ * generate the data needed to run Unicens (UCS) library.
+ *
+ * \note In case of errors the callback UcsXml_CB_OnError will be raised.
+ * \param xmlString - Zero terminated XML string. The string will not be used
+ * after this function call.
+ * \return Structure holding the needed data for UCS. NULL, if there was an error.
+ * The structure will be created dynamically, to free the data call UcsXml_FreeVal.
+ */
+UcsXmlVal_t *UcsXml_Parse(const char *xmlString);
+
+/**
+ * \brief Frees the given structure, generated by UcsXml_Parse.
+ *
+ * \note In case of errors the callback UcsXml_CB_OnError will be raised.
+ * \param val - The structure to be freed.
+ */
+void UcsXml_FreeVal(UcsXmlVal_t *val);
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+/* CALLBACK SECTION */
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+/**
+ * \brief Callback whenever a parser error occurs. The message is human readable.
+ * \note This function must be implemented by the integrator.
+ *
+ * \param format - Zero terminated format string (following printf rules)
+ * \param vargsCnt - Amount of parameters stored in "..."
+ */
+extern void UcsXml_CB_OnError(const char format[], uint16_t vargsCnt, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UCSXML_H_ */ \ No newline at end of file
diff --git a/ucs2-interface/ucs_config.h b/ucs2-interface/ucs_config.h
new file mode 100644
index 0000000..fdca515
--- /dev/null
+++ b/ucs2-interface/ucs_config.h
@@ -0,0 +1,145 @@
+/*
+ * Unicens Integration Helper Component
+ *
+ * Copyright (C) 2017 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+#ifndef UNICENSINTEGRATION_H_
+#define UNICENSINTEGRATION_H_
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+/* USER ADJUSTABLE VALUES */
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+#define ENABLE_INIC_WATCHDOG (false)
+#define ENABLE_AMS_LIB (true)
+#define DEBUG_XRM
+#define BOARD_PMS_TX_SIZE (72)
+#define CMD_QUEUE_LEN (4)
+
+#include <string.h>
+#include <stdarg.h>
+
+#include "ucs_cfg.h"
+#include "ucs_api.h"
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+/* PRIVATE SECTION */
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+/**
+ * \brief Internal enum for Unicens Integration
+ */
+typedef enum
+{
+ ///Result is OK and the processing is finished. Safe to dequeue this command.
+ UniCmdResult_OK_ProcessFinished,
+ ///Result is OK but the processing is ongoing. Must wait for callback.
+ UniCmdResult_OK_NeedToWaitForCB,
+ ///Result is error and the processing is finished. Safe to dequeue this command.
+ UniCmdResult_ERROR_ProcessFinished
+} UnicensCmdResult_t;
+
+/**
+ * \brief Internal enum for Unicens Integration
+ */
+typedef enum
+{
+ UnicensCmd_Unknown,
+ UnicensCmd_Init,
+ UnicensCmd_Stop,
+ UnicensCmd_RmSetRoute,
+ UnicensCmd_NsRun
+} UnicensCmd_t;
+
+/**
+ * \brief Internal struct for Unicens Integration
+ */
+typedef struct
+{
+ const Ucs_InitData_t *init_ptr;
+} UnicensCmdInit_t;
+
+/**
+ * \brief Internal struct for Unicens Integration
+ */
+typedef struct
+{
+ Ucs_Rm_Route_t *routePtr;
+ bool isActive;
+} UnicensCmdRmSetRoute_t;
+
+/**
+ * \brief Internal struct for Unicens Integration
+ */
+typedef struct
+{
+ Ucs_Rm_Node_t * node_ptr;
+} UnicensCmdNsRun_t;
+
+/**
+ * \brief Internal struct for Unicens Integration
+ */
+typedef struct
+{
+ UnicensCmd_t cmd;
+ union
+ {
+ UnicensCmdInit_t Init;
+ UnicensCmdRmSetRoute_t RmSetRoute;
+ UnicensCmdNsRun_t NsRun;
+ } val;
+} UnicensCmdEntry_t;
+
+/**
+ * \brief Internal variables for one instance of Unicens Integration
+ * \note Never touch any of this fields!
+ */
+typedef struct {
+ volatile uint8_t *dataQueue;
+ volatile uint8_t *pRx;
+ volatile uint8_t *pTx;
+ volatile uint32_t amountOfEntries;
+ volatile uint32_t sizeOfEntry;
+ volatile uint32_t rxPos;
+ volatile uint32_t txPos;
+} RB_t;
+
+/**
+ * \brief Internal variables for one instance of Unicens Integration
+ * \note Allocate this structure for each instance (static or malloc)
+ * and pass it to UCSI_Init()
+ * \note Never touch any of this fields!
+ */
+typedef struct
+{
+ uint32_t magic;
+ void *tag;
+ bool initialized;
+ RB_t rb;
+ uint8_t rbBuf[(CMD_QUEUE_LEN * sizeof(UnicensCmdEntry_t))];
+ Ucs_Inst_t *unicens;
+ Ucs_InitData_t uniInitData;
+ bool triggerService;
+ Ucs_Lld_Api_t *uniLld;
+ void *uniLldHPtr;
+ UnicensCmdEntry_t *currentCmd;
+} UCSI_Data_t;
+
+#endif /* UNICENSINTEGRATION_H_ */ \ No newline at end of file
diff --git a/ucs2-interface/ucs_interface.h b/ucs2-interface/ucs_interface.h
new file mode 100644
index 0000000..39ecdf7
--- /dev/null
+++ b/ucs2-interface/ucs_interface.h
@@ -0,0 +1,197 @@
+/*
+ * Unicens Integration Helper Component
+ *
+ * Copyright (C) 2017 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+#ifndef UCSI_H_
+#define UCSI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ucs_config.h"
+#include "ucs-xml/UcsXml.h"
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+/* Public API */
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+// Fulup interface added to support ucs2vol
+typedef const struct {
+ char* name;
+ int numid;
+} UCSI_channelsT;
+
+typedef void (*UCSI_VolumeServiceCB_t)(uint16_t timeout);
+UCSI_channelsT *UCSI_Vol_Init (UCSI_Data_t *pPriv, UCSI_VolumeServiceCB_t serviceCB);
+uint8_t UCSI_Vol_Set (UCSI_Data_t *pPriv, int numId, uint8_t volume);
+void UCSI_Vol_Service (UCSI_Data_t *pPriv);
+
+
+/**
+ * \brief Initializes Unicens Integration module.
+ * \note Must be called before any other function of this component
+ *
+ * \param pPriv - External allocated memory area for this particular
+ * instance (static allocated or allocated with malloc)
+ * \param pTag - Pointer given by the integrator. This pointer will be
+ * returned by any callback function of this component
+ */
+void UCSI_Init(UCSI_Data_t *pPriv, void *pTag);
+
+
+/**
+ * \brief Executes the given configuration. If already started, all
+ * existing local and remote INIC resources will be destroyed
+ * \note All given pointers must stay valid until this callback is
+ * raised: "UCSI_CB_OnStop"
+ *
+ * \param pPriv - private data section of this instance
+ * \param ucsConfig - UCS config handle
+ * \return true, configuration successfully enqueued, false otherwise
+ */
+bool UCSI_NewConfig(UCSI_Data_t *pPriv, UcsXmlVal_t *ucsConfig);
+
+/**
+ * \brief Offer the received control data from LLD to Unicens
+ * \note Call this function only from single context (not from ISR)
+ * \note This function can be called repeated until it return false
+ *
+ * \param pPriv - private data section of this instance
+ * \param pBuffer - Received bytes from MOST control channel
+ * \param len - Length of the received data array
+ * \return true, if the data could be enqueued for processing, remove
+ * the data from LLD queue in this case.
+ * false, data could not be processed due to lag of resources.
+ * In this case do not discard the data. Offer the same
+ * data again after UCSI_CB_OnServiceRequired was
+ * raised or any time later.
+ */
+bool UCSI_ProcessRxData(UCSI_Data_t *pPriv, const uint8_t *pBuffer, uint16_t len);
+
+/**
+ * \brief Gives Unicens Integration module time to do its job
+ * \note Call this function only from single context (not from ISR)
+ *
+ * \param pPriv - private data section of this instance
+ */
+void UCSI_Service(UCSI_Data_t *pPriv);
+
+
+/**
+ * \brief Call after timer set by UCSI_CB_OnSetServiceTimer
+ * expired.
+ * \note Call this function only from single context (not from ISR)
+ *
+ * \param pPriv - private data section of this instance
+ */
+void UCSI_Timeout(UCSI_Data_t *pPriv);
+
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+/* CALLBACK SECTION */
+/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
+
+/**
+ * \brief Callback when ever a timestamp is needed
+ * \note This function must be implemented by the integrator
+ * \param pTag - Pointer given by the integrator by UCSI_Init
+ * \return timestamp in milliseconds
+ */
+extern uint16_t UCSI_CB_OnGetTime(void *pTag);
+
+
+/**
+ * \brief Callback when the implementer needs to arm a timer.
+ * \note This function must be implemented by the integrator
+ * \note After timer expired, call the UCSI_Timeout from service
+ * Thread. (Not from callback!)
+ * \param pTag - Pointer given by the integrator by UCSI_Init
+ * \param timeout - milliseconds from now on to call back. (0=disable)
+ */
+extern void UCSI_CB_OnSetServiceTimer(void *pTag, uint16_t timeout);
+
+
+/**
+ * \brief Callback when ever an Unicens forms a human readable message.
+ * This can be error events or when enabled also debug messages.
+ * \note This function must be implemented by the integrator
+ * \param pTag - Pointer given by the integrator by UCSI_Init
+ * \param format - Zero terminated format string (following printf rules)
+ * \param vargsCnt - Amount of parameters stored in "..."
+ */
+extern void UCSI_CB_OnUserMessage(void *pTag, const char format[],
+ uint16_t vargsCnt, ...);
+
+
+/**
+ * \brief Callback when ever this instance needs to be serviced.
+ * \note Call UCSI_Service by your scheduler at the next run
+ * \note This function must be implemented by the integrator
+ * \param pTag - Pointer given by the integrator by UCSI_Init
+ */
+extern void UCSI_CB_OnServiceRequired(void *pTag);
+
+
+/**
+ * \brief Callback when ever a MOST error message was received.
+ * \note This function must be implemented by the integrator
+ * \param pTag - Pointer given by the integrator by UCSI_Init
+ * \note All following parameters belong to the usual MOST message
+ */
+extern void UCSI_CB_OnMostError(void *pTag, uint16_t sourceAddr,
+ uint8_t fblock, uint8_t inst, uint16_t function, uint8_t op,
+ const uint8_t *pPayload, uint32_t payloadLen);
+
+
+/**
+ * \brief Callback when ever this instance wants to send a message to INIC.
+ * \note This function must be implemented by the integrator
+ * \param pTag - Pointer given by the integrator by UCSI_Init
+ * \param pPayload - Byte array to be sent on the INIC control channel
+ * \param payloadLen - Length of pPayload in Byte
+ */
+extern void UCSI_CB_SendMostMessage(void *pTag,
+ const uint8_t *pPayload, uint32_t payloadLen);
+
+/**
+ * \brief Callback when Unicens instance has been stopped.
+ * \note This event can be used to free memory holding the resources
+ * passed with UCSI_NewConfig
+ * \note This function must be implemented by the integrator
+ * \param pTag - Pointer given by the integrator by UCSI_Init
+ */
+extern void UCSI_CB_OnStop(void *pTag);
+
+/**
+ * \brief Callback on Unicens management results.
+ * \note This function must be implemented by the integrator
+ * \param pTag - Pointer given by the integrator by UCSI_Init
+ * \param code - Result code
+ * \param nodeAddress - Node address of the device causing this event
+ * \param pNode - Pointer to node structure holding details of changed node
+ */
+extern void UCSI_CB_OnMgrReport(void *pTag, Ucs_MgrReport_t code, uint16_t nodeAddress, Ucs_Rm_Node_t *pNode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UCSI_H_ */ \ No newline at end of file
diff --git a/ucs2-interface/ucs_lib_interf.c b/ucs2-interface/ucs_lib_interf.c
new file mode 100644
index 0000000..842ba5a
--- /dev/null
+++ b/ucs2-interface/ucs_lib_interf.c
@@ -0,0 +1,647 @@
+/*
+ * Unicens Integration Helper Component
+ *
+ * Copyright (C) 2017 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+#include <assert.h>
+#include "ucs_interface.h"
+
+/************************************************************************/
+/* Private Definitions and variables */
+/************************************************************************/
+#define MAGIC (0xA144BEAF)
+
+/************************************************************************/
+/* Private Function Prototypes */
+/************************************************************************/
+static bool EnqueueCommand(UCSI_Data_t *my, UnicensCmdEntry_t *cmd);
+static void OnCommandExecuted(UCSI_Data_t *my, UnicensCmd_t cmd);
+static void RB_Init(RB_t *rb, uint16_t amountOfEntries, uint32_t sizeOfEntry, uint8_t *workingBuffer);
+static void *RB_GetReadPtr(RB_t *rb);
+static void RB_PopReadPtr(RB_t *rb);
+static void *RB_GetWritePtr(RB_t *rb);
+static void RB_PopWritePtr(RB_t *rb);
+static uint16_t OnUnicensGetTime(void *user_ptr);
+static void OnUnicensService( void *user_ptr );
+static void OnUnicensError( Ucs_Error_t error_code, void *user_ptr );
+static void OnUnicensAppTimer( uint16_t timeout, void *user_ptr );
+static void OnUnicensDebugErrorMsg(Msg_MostTel_t *m, void *user_ptr);
+static void OnLldCtrlStart( Ucs_Lld_Api_t* api_ptr, void *inst_ptr, void *lld_user_ptr );
+static void OnLldCtrlStop( void *lld_user_ptr );
+static void OnLldCtrlRxMsgAvailable( void *lld_user_ptr );
+static void OnLldCtrlTxTransmitC( Ucs_Lld_TxMsg_t *msg_ptr, void *lld_user_ptr );
+static void OnUnicensRoutingResult(Ucs_Rm_Route_t* route_ptr, Ucs_Rm_RouteInfos_t route_infos, void *user_ptr);
+static void OnUnicensMostPortStatus(uint16_t most_port_handle,
+ Ucs_Most_PortAvail_t availability, Ucs_Most_PortAvailInfo_t avail_info,
+ uint16_t free_streaming_bw, void* user_ptr);
+static void OnUnicensDebugXrmResources(Ucs_Xrm_ResourceType_t resource_type,
+ Ucs_Xrm_ResObject_t *resource_ptr, Ucs_Xrm_ResourceInfos_t resource_infos,
+ Ucs_Rm_EndPoint_t *endpoint_inst_ptr, void *user_ptr);
+static void OnUcsInitResult(Ucs_InitResult_t result, void *user_ptr);
+static void OnUcsStopResult(Ucs_StdResult_t result, void *user_ptr);
+static void OnUcsMgrReport(Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr, void *user_ptr);
+static void OnUcsNsRun(Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCode_t result, void *ucs_user_ptr);
+
+/************************************************************************/
+/* Public Function Implementations */
+/************************************************************************/
+void UCSI_Init(UCSI_Data_t *my, void *pTag)
+{
+ Ucs_Return_t result;
+ assert(NULL != my);
+ memset(my, 0, sizeof(UCSI_Data_t));
+ my->magic = MAGIC;
+ my->tag = pTag;
+ my->unicens = Ucs_CreateInstance();
+ if (NULL == my->unicens)
+ {
+ UCSI_CB_OnUserMessage(my->tag, "Can not instance a new version of UNICENS, "\
+ "increase UCS_NUM_INSTANCES define", 0);
+ assert(false);
+ return;
+ }
+ result = Ucs_SetDefaultConfig(&my->uniInitData);
+ if(UCS_RET_SUCCESS != result)
+ {
+ UCSI_CB_OnUserMessage(my->tag, "Can not set default values to Unicens config (result=0x%X)", 1, result);
+ assert(false);
+ return;
+ }
+ my->uniInitData.user_ptr = my;
+ my->uniInitData.mgr.report_fptr = OnUcsMgrReport;
+
+ my->uniInitData.general.inic_watchdog_enabled = ENABLE_INIC_WATCHDOG;
+ my->uniInitData.general.get_tick_count_fptr = &OnUnicensGetTime;
+ my->uniInitData.general.request_service_fptr = &OnUnicensService;
+ my->uniInitData.general.error_fptr = &OnUnicensError;
+ my->uniInitData.general.set_application_timer_fptr = &OnUnicensAppTimer;
+ my->uniInitData.general.debug_error_msg_fptr = &OnUnicensDebugErrorMsg;
+ my->uniInitData.ams.enabled = ENABLE_AMS_LIB;
+
+ my->uniInitData.lld.lld_user_ptr = my;
+ my->uniInitData.lld.start_fptr = &OnLldCtrlStart;
+ my->uniInitData.lld.stop_fptr = &OnLldCtrlStop;
+ my->uniInitData.lld.rx_available_fptr = &OnLldCtrlRxMsgAvailable;
+ my->uniInitData.lld.tx_transmit_fptr = &OnLldCtrlTxTransmitC;
+
+ my->uniInitData.rm.report_fptr = &OnUnicensRoutingResult;
+ my->uniInitData.rm.xrm.most_port_status_fptr = &OnUnicensMostPortStatus;
+ my->uniInitData.rm.debug_resource_status_fptr = &OnUnicensDebugXrmResources;
+
+ RB_Init(&my->rb, CMD_QUEUE_LEN, sizeof(UnicensCmdEntry_t), my->rbBuf);
+}
+
+bool UCSI_NewConfig(UCSI_Data_t *my, UcsXmlVal_t *ucsConfig) {
+
+ UnicensCmdEntry_t *e;
+ assert(MAGIC == my->magic);
+ if (my->initialized)
+ {
+ e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
+ if (NULL == e) return false;
+ e->cmd = UnicensCmd_Stop;
+ RB_PopWritePtr(&my->rb);
+ }
+ my->uniInitData.mgr.packet_bw = ucsConfig->packetBw;
+ my->uniInitData.mgr.routes_list_ptr = ucsConfig->pRoutes;
+ my->uniInitData.mgr.routes_list_size = ucsConfig->routesSize;
+ my->uniInitData.mgr.nodes_list_ptr = ucsConfig->pNod;
+ my->uniInitData.mgr.nodes_list_size = ucsConfig->nodSize;
+ my->uniInitData.mgr.enabled = true;
+ e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
+ if (NULL == e) return false;
+ e->cmd = UnicensCmd_Init;
+ e->val.Init.init_ptr = &my->uniInitData;
+ RB_PopWritePtr(&my->rb);
+ UCSI_CB_OnServiceRequired(my->tag);
+ return true;
+}
+
+bool UCSI_ProcessRxData(UCSI_Data_t *my, const uint8_t *pBuffer, uint16_t len)
+{
+ assert(MAGIC == my->magic);
+ if (NULL == my->uniLld || NULL == my->uniLldHPtr) return false;
+ Ucs_Lld_RxMsg_t *msg = NULL;
+ msg = my->uniLld->rx_allocate_fptr(my->uniLldHPtr, len);
+ if (NULL == msg)
+ {
+ //This may happen by definition, OnLldCtrlRxMsgAvailable()
+ //will be called, once buffers are available again
+ return false;
+ }
+ msg->data_size = len;
+ memcpy(msg->data_ptr, pBuffer, len);
+ my->uniLld->rx_receive_fptr(my->uniLldHPtr, msg);
+ return true;
+}
+
+
+void UCSI_Service(UCSI_Data_t *my) {
+ UnicensCmdEntry_t *e;
+ bool popEntry = true; //Set to false in specific case, where function will callback asynchrony.
+ assert(MAGIC == my->magic);
+ if (NULL != my->unicens && my->triggerService) {
+ my->triggerService = false;
+ Ucs_Service(my->unicens);
+ }
+ if (NULL != my->currentCmd) return;
+ my->currentCmd = e = (UnicensCmdEntry_t *)RB_GetReadPtr(&my->rb);
+ if (NULL == e) return;
+ switch (e->cmd) {
+ case UnicensCmd_Init:
+ if (UCS_RET_SUCCESS == Ucs_Init(my->unicens, e->val.Init.init_ptr, OnUcsInitResult))
+ popEntry = false;
+ else
+ UCSI_CB_OnUserMessage(my->tag, "Ucs_Init failed", 0);
+ break;
+ case UnicensCmd_Stop:
+ if (UCS_RET_SUCCESS == Ucs_Stop(my->unicens, OnUcsStopResult))
+ popEntry = false;
+ else
+ UCSI_CB_OnUserMessage(my->tag, "Ucs_Stop failed", 0);
+ break;
+ case UnicensCmd_RmSetRoute:
+ if (UCS_RET_SUCCESS != Ucs_Rm_SetRouteActive(my->unicens, e->val.RmSetRoute.routePtr, e->val.RmSetRoute.isActive))
+ UCSI_CB_OnUserMessage(my->tag, "Ucs_Rm_SetRouteActive failed", 0);
+ break;
+ case UnicensCmd_NsRun:
+ if (UCS_RET_SUCCESS != Ucs_Ns_Run(my->unicens, e->val.NsRun.node_ptr, OnUcsNsRun))
+ UCSI_CB_OnUserMessage(my->tag, "Ucs_Ns_Run failed", 0);
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ if (popEntry)
+ {
+ my->currentCmd = NULL;
+ RB_PopReadPtr(&my->rb);
+ }
+}
+
+void UCSI_Timeout(UCSI_Data_t *my)
+{
+ assert(MAGIC == my->magic);
+ if (NULL == my->unicens) return;
+ Ucs_ReportTimeout(my->unicens);
+}
+
+/************************************************************************/
+/* Private Functions */
+/************************************************************************/
+static bool EnqueueCommand(UCSI_Data_t *my, UnicensCmdEntry_t *cmd)
+{
+ UnicensCmdEntry_t *e;
+ if (NULL == my || NULL == cmd)
+ {
+ assert(false);
+ return false;
+ }
+ e = RB_GetWritePtr(&my->rb);
+ if (NULL == e)
+ {
+ UCSI_CB_OnUserMessage(my->tag, "Could not enqueue command. Increase CMD_QUEUE_LEN define", 0);
+ return false;
+ }
+ memcpy(e, cmd, sizeof(UnicensCmdEntry_t));
+ RB_PopWritePtr(&my->rb);
+ UCSI_CB_OnServiceRequired(my->tag);
+ return true;
+}
+
+static void OnCommandExecuted(UCSI_Data_t *my, UnicensCmd_t cmd)
+{
+ if (NULL == my)
+ {
+ assert(false);
+ return;
+ }
+ if (NULL == my->currentCmd)
+ {
+ UCSI_CB_OnUserMessage(my->tag, "OnUniCommandExecuted was called, but no "\
+ "command is in queue", 0);
+ assert(false);
+ return;
+ }
+ if (my->currentCmd->cmd != cmd)
+ {
+ UCSI_CB_OnUserMessage(my->tag, "OnUniCommandExecuted was called with "\
+ "wrong command (Expected=0x%X, Got=0x%X", 2, my->currentCmd->cmd, cmd);
+ assert(false);
+ return;
+ }
+ my->currentCmd = NULL;
+ RB_PopReadPtr(&my->rb);
+}
+
+static void RB_Init(RB_t *rb, uint16_t amountOfEntries, uint32_t sizeOfEntry, uint8_t *workingBuffer)
+{
+ assert(NULL != rb);
+ assert(NULL != workingBuffer);
+ rb->dataQueue = workingBuffer;
+ rb->pRx = rb->dataQueue;
+ rb->pTx = rb->dataQueue;
+ rb->amountOfEntries = amountOfEntries;
+ rb->sizeOfEntry = sizeOfEntry;
+ rb->rxPos = 0;
+ rb->txPos = 0;
+}
+
+static void *RB_GetReadPtr(RB_t *rb)
+{
+ assert(NULL != rb);
+ assert(0 != rb->dataQueue);
+ if (rb->txPos - rb->rxPos > 0)
+ return (void *)rb->pRx;
+ return NULL;
+}
+
+static void RB_PopReadPtr(RB_t *rb)
+{
+ assert(NULL != rb);
+ assert(0 != rb->dataQueue);
+
+ rb->pRx += rb->sizeOfEntry;
+ if (rb->pRx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
+ rb->pRx = rb->dataQueue;
+ ++rb->rxPos;
+ assert(rb->txPos >= rb->rxPos);
+}
+
+static void *RB_GetWritePtr(RB_t *rb)
+{
+ assert(NULL != rb);
+ assert(0 != rb->dataQueue);
+ if (rb->txPos - rb->rxPos < rb->amountOfEntries)
+ return (void *)rb->pTx;
+ return NULL;
+}
+
+static void RB_PopWritePtr(RB_t *rb)
+{
+ assert(NULL != rb);
+ assert(0 != rb->dataQueue);
+ rb->pTx += rb->sizeOfEntry;
+ if (rb->pTx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
+ rb->pTx = rb->dataQueue;
+ ++rb->txPos;
+ assert(rb->txPos >= rb->rxPos);
+}
+
+static uint16_t OnUnicensGetTime(void *user_ptr)
+{
+ UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
+ assert(MAGIC == my->magic);
+ return UCSI_CB_OnGetTime(my->tag);
+}
+
+static void OnUnicensService( void *user_ptr )
+{
+ UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
+ assert(MAGIC == my->magic);
+ my->triggerService = true;
+ UCSI_CB_OnServiceRequired(my->tag);
+}
+
+static void OnUnicensError( Ucs_Error_t error_code, void *user_ptr )
+{
+ error_code = error_code;
+ UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
+ assert(MAGIC == my->magic);
+ UCSI_CB_OnUserMessage(my->tag, "Unicens general error, code=0x%X", 1, error_code);
+}
+
+static void OnUnicensAppTimer( uint16_t timeout, void *user_ptr )
+{
+ UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
+ assert(MAGIC == my->magic);
+ UCSI_CB_OnSetServiceTimer(my->tag, timeout);
+}
+
+static void OnUnicensDebugErrorMsg(Msg_MostTel_t *m, void *user_ptr)
+{
+ UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
+ assert(MAGIC == my->magic);
+ UCSI_CB_OnMostError(my->tag, m->source_addr, m->id.fblock_id, m->id.instance_id,
+ m->id.function_id, m->id.op_type, m->tel.tel_data_ptr, m->tel.tel_len);
+}
+
+static void OnLldCtrlStart( Ucs_Lld_Api_t* api_ptr, void *inst_ptr, void *lld_user_ptr )
+{
+ UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
+ assert(MAGIC == my->magic);
+ my->uniLld = api_ptr;
+ my->uniLldHPtr = inst_ptr;
+}
+
+static void OnLldCtrlStop( void *lld_user_ptr )
+{
+ UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
+ assert(MAGIC == my->magic);
+ my->uniLld = NULL;
+ my->uniLldHPtr = NULL;
+}
+
+static void OnLldCtrlRxMsgAvailable( void *lld_user_ptr )
+{
+ UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
+ assert(MAGIC == my->magic);
+ UCSI_CB_OnServiceRequired(my->tag);
+}
+
+static void OnLldCtrlTxTransmitC( Ucs_Lld_TxMsg_t *msg_ptr, void *lld_user_ptr )
+{
+ UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
+ assert(MAGIC == my->magic);
+ uint8_t buffer[BOARD_PMS_TX_SIZE];
+ uint32_t bufferPos = 0;
+ Ucs_Mem_Buffer_t * buf_ptr;
+ if (NULL == msg_ptr || NULL == my || NULL == my->uniLld || NULL == my->uniLldHPtr)
+ {
+ assert(false);
+ return;
+ }
+ for (buf_ptr = msg_ptr->memory_ptr; buf_ptr != NULL; buf_ptr = buf_ptr->next_buffer_ptr)
+ {
+ if (buf_ptr->data_size + bufferPos > sizeof(buffer))
+ {
+ UCSI_CB_OnUserMessage(my->tag, "TX buffer is too small, increase " \
+ "BOARD_PMS_TX_SIZE define (%lu > %lu)", 2, buf_ptr->data_size + bufferPos, sizeof(buffer));
+ my->uniLld->tx_release_fptr(my->uniLldHPtr, msg_ptr);
+ return;
+ }
+ memcpy(&buffer[bufferPos], buf_ptr->data_ptr, buf_ptr->data_size);
+ bufferPos += buf_ptr->data_size;
+ }
+ assert(bufferPos == msg_ptr->memory_ptr->total_size);
+ my->uniLld->tx_release_fptr(my->uniLldHPtr, msg_ptr);
+ UCSI_CB_SendMostMessage(my->tag, buffer, bufferPos);
+}
+
+static void OnUnicensRoutingResult(Ucs_Rm_Route_t* route_ptr, Ucs_Rm_RouteInfos_t route_infos, void *user_ptr)
+{
+ //TODO: implement
+ route_ptr = route_ptr;
+ route_infos = route_infos;
+ user_ptr = user_ptr;
+}
+
+static void OnUnicensMostPortStatus(uint16_t most_port_handle,
+ Ucs_Most_PortAvail_t availability, Ucs_Most_PortAvailInfo_t avail_info,
+ uint16_t free_streaming_bw, void* user_ptr)
+{
+ //TODO: implement
+ most_port_handle = most_port_handle;
+ availability = availability;
+ avail_info = avail_info;
+ free_streaming_bw = free_streaming_bw;
+ user_ptr = user_ptr;
+}
+
+static void OnUnicensDebugXrmResources(Ucs_Xrm_ResourceType_t resource_type,
+ Ucs_Xrm_ResObject_t *resource_ptr, Ucs_Xrm_ResourceInfos_t resource_infos,
+ Ucs_Rm_EndPoint_t *endpoint_inst_ptr, void *user_ptr)
+{
+#ifndef DEBUG_XRM
+ resource_type = resource_type;
+ resource_ptr = resource_ptr;
+ resource_infos = resource_infos;
+ endpoint_inst_ptr = endpoint_inst_ptr;
+ user_ptr = user_ptr;
+#else
+ endpoint_inst_ptr = endpoint_inst_ptr;
+ UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
+ assert(MAGIC == my->magic);
+ if (NULL == resource_ptr) return;
+ char *msg = NULL;
+ uint16_t adr = 0xFFFF;
+ if (endpoint_inst_ptr && endpoint_inst_ptr->node_obj_ptr &&
+ endpoint_inst_ptr->node_obj_ptr->signature_ptr)
+ adr = endpoint_inst_ptr->node_obj_ptr->signature_ptr->node_address;
+ switch (resource_infos)
+ {
+ case UCS_XRM_INFOS_BUILT:
+ msg = (char *)"has been built";
+ break;
+ case UCS_XRM_INFOS_DESTROYED:
+ msg = (char *)"has been destroyed";
+ break;
+ case UCS_XRM_INFOS_ERR_BUILT:
+ msg = (char *)"cannot be built";
+ break;
+ default:
+ msg = (char *)"cannot be destroyed";
+ break;
+ }
+ switch(resource_type)
+ {
+ case UCS_XRM_RC_TYPE_MOST_SOCKET:
+ {
+ Ucs_Xrm_MostSocket_t *ms = (Ucs_Xrm_MostSocket_t *)resource_ptr;
+ assert(ms->resource_type == resource_type);
+ UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): MOST socket %s, handle=%04X, "\
+ "direction=%d, type=%d, bandwidth=%d", 6, adr, msg, ms->most_port_handle,
+ ms->direction, ms->data_type, ms->bandwidth);
+ break;
+ }
+ case UCS_XRM_RC_TYPE_MLB_PORT:
+ {
+ Ucs_Xrm_MlbPort_t *m = (Ucs_Xrm_MlbPort_t *)resource_ptr;
+ assert(m->resource_type == resource_type);
+ UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): MLB port %s, index=%d, clock=%d", 4,
+ adr, msg, m->index, m->clock_config);
+ break;
+ }
+ case UCS_XRM_RC_TYPE_MLB_SOCKET:
+ {
+ Ucs_Xrm_MlbSocket_t *m = (Ucs_Xrm_MlbSocket_t *)resource_ptr;
+ assert(m->resource_type == resource_type);
+ UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): MLB socket %s, direction=%d, type=%d,"\
+ " bandwidth=%d, channel=%d", 6, adr, msg, m->direction, m->data_type,
+ m->bandwidth, m->channel_address);
+ break;
+ }
+ case UCS_XRM_RC_TYPE_USB_PORT:
+ {
+ Ucs_Xrm_UsbPort_t *m = (Ucs_Xrm_UsbPort_t *)resource_ptr;
+ assert(m->resource_type == resource_type);
+ UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): USB port %s, in-cnt=%d, out-cnt=%d", 4,
+ adr, msg, m->streaming_if_ep_in_count, m->streaming_if_ep_out_count);
+ break;
+ }
+ case UCS_XRM_RC_TYPE_USB_SOCKET:
+ {
+ Ucs_Xrm_UsbSocket_t *m = (Ucs_Xrm_UsbSocket_t *)resource_ptr;
+ assert(m->resource_type == resource_type);
+ UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): USB socket %s, direction=%d, type=%d," \
+ " ep-addr=%02X, frames=%d", 6, adr, msg, m->direction, m->data_type,
+ m->end_point_addr, m->frames_per_transfer);
+ break;
+ }
+ case UCS_XRM_RC_TYPE_STRM_PORT:
+ {
+ Ucs_Xrm_StrmPort_t *m = (Ucs_Xrm_StrmPort_t *)resource_ptr;
+ assert(m->resource_type == resource_type);
+ UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): I2S port %s, index=%d, clock=%d, "\
+ "align=%d", 5, adr, msg, m->index, m->clock_config, m->data_alignment);
+ break;
+ }
+ case UCS_XRM_RC_TYPE_STRM_SOCKET:
+ {
+ Ucs_Xrm_StrmSocket_t *m = (Ucs_Xrm_StrmSocket_t *)resource_ptr;
+ assert(m->resource_type == resource_type);
+ UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): I2S socket %s, direction=%d, type=%d"\
+ ", bandwidth=%d, pin=%d", 6, adr, msg, m->direction, m->data_type,
+ m->bandwidth, m->stream_pin_id);
+ break;
+ }
+ case UCS_XRM_RC_TYPE_SYNC_CON:
+ {
+ Ucs_Xrm_SyncCon_t *m = (Ucs_Xrm_SyncCon_t *)resource_ptr;
+ assert(m->resource_type == resource_type);
+ UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): Sync connection %s, mute=%d, "\
+ "offset=%d", 4, adr, msg, m->mute_mode, m->offset);
+ break;
+ }
+ case UCS_XRM_RC_TYPE_COMBINER:
+ {
+ Ucs_Xrm_Combiner_t *m = (Ucs_Xrm_Combiner_t *)resource_ptr;
+ assert(m->resource_type == resource_type);
+ UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): Combiner %s, bytes per frame=%d",
+ 3, adr, msg, m->bytes_per_frame);
+ break;
+ }
+ case UCS_XRM_RC_TYPE_SPLITTER:
+ {
+ Ucs_Xrm_Splitter_t *m = (Ucs_Xrm_Splitter_t *)resource_ptr;
+ assert(m->resource_type == resource_type);
+ UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): Splitter %s, bytes per frame=%d",
+ 3, adr, msg, m->bytes_per_frame);
+ break;
+ }
+ case UCS_XRM_RC_TYPE_AVP_CON:
+ {
+ Ucs_Xrm_AvpCon_t *m = (Ucs_Xrm_AvpCon_t *)resource_ptr;
+ assert(m->resource_type == resource_type);
+ UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): Isoc-AVP connection %s, packetSize=%d",
+ 3, adr, msg, m->isoc_packet_size);
+ break;
+ }
+ default:
+ UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): Unknown type=%d %s", 3 , adr, resource_type, msg);
+ }
+#endif
+}
+
+static void OnUcsInitResult(Ucs_InitResult_t result, void *user_ptr)
+{
+ UnicensCmdEntry_t e;
+ UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
+ assert(MAGIC == my->magic);
+ my->initialized = (UCS_INIT_RES_SUCCESS == result);
+ OnCommandExecuted(my, UnicensCmd_Init);
+ if (!my->initialized)
+ {
+ UCSI_CB_OnUserMessage(my->tag, "UcsInitResult reported error (0x%X), restarting...", 1, result);
+ e.cmd = UnicensCmd_Init;
+ e.val.Init.init_ptr = &my->uniInitData;
+ EnqueueCommand(my, &e);
+ }
+}
+
+static void OnUcsStopResult(Ucs_StdResult_t result, void *user_ptr)
+{
+ result = result; //TODO: check error case
+ UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
+ assert(MAGIC == my->magic);
+ my->initialized = false;
+ OnCommandExecuted(my, UnicensCmd_Stop);
+ UCSI_CB_OnStop(my->tag);
+}
+
+static void OnUcsMgrReport(Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr, void *user_ptr)
+{
+ UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
+ assert(MAGIC == my->magic);
+ if (node_ptr && node_ptr->script_list_ptr && node_ptr->script_list_size)
+ {
+ UnicensCmdEntry_t e;
+ e.cmd = UnicensCmd_NsRun;
+ e.val.NsRun.node_ptr = node_ptr;
+ EnqueueCommand(my, &e);
+ }
+ UCSI_CB_OnMgrReport(my->tag, code, node_address, node_ptr);
+}
+
+static void OnUcsNsRun(Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCode_t result, void *ucs_user_ptr)
+{
+#ifndef DEBUG_XRM
+ node_ptr = node_ptr;
+ result = result;
+ ucs_user_ptr;
+#else
+ UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
+ assert(MAGIC == my->magic);
+ UCSI_CB_OnUserMessage(my->tag, "OnUcsNsRun (%03X): script executed %s",
+ 2, node_ptr->signature_ptr->node_address,
+ (UCS_NS_RES_SUCCESS == result ? "succeeded" : "false"));
+#endif
+}
+
+/*----------------------------------------
+ * Debug Message output from Unicens stack:
+ *----------------------------------------
+ */
+#if defined(UCS_TR_ERROR) || defined(UCS_TR_INFO)
+#include <stdio.h>
+#define TRACE_BUFFER_SZ 200
+void App_TraceError(void *ucs_user_ptr, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
+{
+ void *tag;
+ UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
+ if (my)
+ {
+ assert(MAGIC == my->magic);
+ tag = my->tag;
+ }
+ char outbuf[TRACE_BUFFER_SZ];
+ va_list argptr;
+ va_start(argptr, vargs_cnt);
+ vsprintf(outbuf, entry_str, argptr);
+ va_end(argptr);
+ UCSI_CB_OnUserMessage(tag, "Error | %s | %s", 2, module_str, outbuf);
+}
+void App_TraceInfo(void *ucs_user_ptr, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
+{
+ void *tag;
+ UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
+ if (my)
+ {
+ assert(MAGIC == my->magic);
+ tag = my->tag;
+ }
+ char outbuf[TRACE_BUFFER_SZ];
+ va_list argptr;
+ va_start(argptr, vargs_cnt);
+ vsprintf(outbuf, entry_str, argptr);
+ va_end(argptr);
+ UCSI_CB_OnUserMessage(tag, "Info | %s | %s", 2, module_str, outbuf);
+}
+#endif \ No newline at end of file
diff --git a/ucs2-interface/ucs_vol_interf.c b/ucs2-interface/ucs_vol_interf.c
new file mode 100644
index 0000000..fc2952e
--- /dev/null
+++ b/ucs2-interface/ucs_vol_interf.c
@@ -0,0 +1,59 @@
+/*
+ * Unicens Integration Helper Component
+ *
+ * Copyright (C) 2017 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+#include <assert.h>
+#include "ucs_interface.h"
+#include "libmostvolume.h"
+
+
+
+static UCSI_channelsT ucsiChannels[] = {
+ {.name= "FRONT_LEFT" , .numid= (int)LIB_MOST_VOLUME_CH_FRONT_LEFT},
+ {.name= "FRONT_RIGHT", .numid= (int)LIB_MOST_VOLUME_CH_FRONT_RIGHT},
+ {.name= "REAR_LEFT" , .numid= (int)LIB_MOST_VOLUME_CH_REAR_LEFT},
+ {.name= "REAR_LEFT" , .numid= (int)LIB_MOST_VOLUME_CH_REAR_RIGHT},
+ {.name= "CENTER" , .numid= (int)LIB_MOST_VOLUME_CH_CENTER},
+ {.name= "SUB" , .numid= (int)LIB_MOST_VOLUME_CH_SUB},
+ {.name= "MASTER" , .numid= (int)LIB_MOST_VOLUME_MASTER},
+
+ {.name= NULL}
+};
+
+// Small wrapper as UCSI and UCSVOL do not use the same handle
+void UCSI_Vol_Service (UCSI_Data_t *pPriv) {
+ (void)lib_most_volume_service();
+
+}
+
+UCSI_channelsT *UCSI_Vol_Init (UCSI_Data_t *pPriv, UCSI_VolumeServiceCB_t serviceCB) {
+ int err;
+ err = lib_most_volume_init(pPriv->unicens, (lib_most_volume_service_cb_t) serviceCB);
+ if (err) return (NULL);
+ else return (ucsiChannels);
+}
+
+uint8_t UCSI_Vol_Set(UCSI_Data_t *pPriv, int numid, uint8_t volume) {
+
+ return (lib_most_volume_set((enum lib_most_volume_channel_t)numid, volume));
+}
+
+