Fixed crash of TX CDEV write, when there was many traffic
[apps/agl-service-unicens.git] / ucs2-interface / ucs_lib_interf.c
1 /*
2  * Unicens Integration Helper Component
3  *
4  * Copyright (C) 2017 Microchip Technology Germany II GmbH & Co. KG
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * You may also obtain this software under a propriety license from Microchip.
20  * Please contact Microchip for further information.
21  *
22  */
23 #include <assert.h>
24 #include "ucs_interface.h"
25
26 /************************************************************************/
27 /* Private Definitions and variables                                    */
28 /************************************************************************/
29 #define MAGIC (0xA144BEAF)
30
31 /************************************************************************/
32 /* Private Function Prototypes                                          */
33 /************************************************************************/
34 static bool EnqueueCommand(UCSI_Data_t *my, UnicensCmdEntry_t *cmd);
35 static void OnCommandExecuted(UCSI_Data_t *my, UnicensCmd_t cmd);
36 static void RB_Init(RB_t *rb, uint16_t amountOfEntries, uint32_t sizeOfEntry, uint8_t *workingBuffer);
37 static void *RB_GetReadPtr(RB_t *rb);
38 static void RB_PopReadPtr(RB_t *rb);
39 static void *RB_GetWritePtr(RB_t *rb);
40 static void RB_PopWritePtr(RB_t *rb);
41 static uint16_t OnUnicensGetTime(void *user_ptr);
42 static void OnUnicensService( void *user_ptr );
43 static void OnUnicensError( Ucs_Error_t error_code, void *user_ptr );
44 static void OnUnicensAppTimer( uint16_t timeout, void *user_ptr );
45 static void OnUnicensDebugErrorMsg(Msg_MostTel_t *m, void *user_ptr);
46 static void OnLldCtrlStart( Ucs_Lld_Api_t* api_ptr, void *inst_ptr, void *lld_user_ptr );
47 static void OnLldCtrlStop( void *lld_user_ptr );
48 static void OnLldCtrlRxMsgAvailable( void *lld_user_ptr );
49 static void OnLldCtrlTxTransmitC( Ucs_Lld_TxMsg_t *msg_ptr, void *lld_user_ptr );
50 static void OnUnicensRoutingResult(Ucs_Rm_Route_t* route_ptr, Ucs_Rm_RouteInfos_t route_infos, void *user_ptr);
51 static void OnUnicensMostPortStatus(uint16_t most_port_handle,
52     Ucs_Most_PortAvail_t availability, Ucs_Most_PortAvailInfo_t avail_info,
53     uint16_t free_streaming_bw, void* user_ptr);
54 static void OnUnicensDebugXrmResources(Ucs_Xrm_ResourceType_t resource_type,
55     Ucs_Xrm_ResObject_t *resource_ptr, Ucs_Xrm_ResourceInfos_t resource_infos,
56     Ucs_Rm_EndPoint_t *endpoint_inst_ptr, void *user_ptr);
57 static void OnUcsInitResult(Ucs_InitResult_t result, void *user_ptr);
58 static void OnUcsStopResult(Ucs_StdResult_t result, void *user_ptr);
59 static void OnUcsMgrReport(Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr, void *user_ptr);
60 static void OnUcsNsRun(Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCode_t result, void *ucs_user_ptr);
61
62 /************************************************************************/
63 /* Public Function Implementations                                      */
64 /************************************************************************/
65 void UCSI_Init(UCSI_Data_t *my, void *pTag)
66 {
67     Ucs_Return_t result;
68     assert(NULL != my);
69     memset(my, 0, sizeof(UCSI_Data_t));
70     my->magic = MAGIC;
71     my->tag = pTag;
72     my->UNICENS = Ucs_CreateInstance();
73     if (NULL == my->UNICENS)
74     {
75         UCSI_CB_OnUserMessage(my->tag, "Can not instance a new version of UNICENS, "\
76             "increase UCS_NUM_INSTANCES define", 0);
77         assert(false);
78         return;
79     }
80     result = Ucs_SetDefaultConfig(&my->uniInitData);
81     if(UCS_RET_SUCCESS != result)
82     {
83         UCSI_CB_OnUserMessage(my->tag, "Can not set default values to Unicens config (result=0x%X)", 1, result);
84         assert(false);
85         return;
86     }
87     my->uniInitData.user_ptr = my;
88     my->uniInitData.mgr.report_fptr = OnUcsMgrReport;
89
90     my->uniInitData.general.inic_watchdog_enabled = ENABLE_INIC_WATCHDOG;
91     my->uniInitData.general.get_tick_count_fptr = &OnUnicensGetTime;
92     my->uniInitData.general.request_service_fptr = &OnUnicensService;
93     my->uniInitData.general.error_fptr = &OnUnicensError;
94     my->uniInitData.general.set_application_timer_fptr = &OnUnicensAppTimer;
95     my->uniInitData.general.debug_error_msg_fptr = &OnUnicensDebugErrorMsg;
96     my->uniInitData.ams.enabled = ENABLE_AMS_LIB;
97
98     my->uniInitData.lld.lld_user_ptr = my;
99     my->uniInitData.lld.start_fptr =  &OnLldCtrlStart;
100     my->uniInitData.lld.stop_fptr = &OnLldCtrlStop;
101     my->uniInitData.lld.rx_available_fptr = &OnLldCtrlRxMsgAvailable;
102     my->uniInitData.lld.tx_transmit_fptr = &OnLldCtrlTxTransmitC;
103
104     my->uniInitData.rm.report_fptr = &OnUnicensRoutingResult;
105     my->uniInitData.rm.xrm.most_port_status_fptr = &OnUnicensMostPortStatus;
106     my->uniInitData.rm.debug_resource_status_fptr = &OnUnicensDebugXrmResources;
107
108     RB_Init(&my->rb, CMD_QUEUE_LEN, sizeof(UnicensCmdEntry_t), my->rbBuf);
109 }
110
111 bool UCSI_NewConfig(UCSI_Data_t *my, UcsXmlVal_t *ucsConfig) {
112
113     UnicensCmdEntry_t *e;
114     assert(MAGIC == my->magic);
115     if (my->initialized)
116     {
117         e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
118         if (NULL == e) return false;
119         e->cmd = UnicensCmd_Stop;
120         RB_PopWritePtr(&my->rb);
121     }
122     my->uniInitData.mgr.packet_bw = ucsConfig->packetBw;
123     my->uniInitData.mgr.routes_list_ptr = ucsConfig->pRoutes;
124     my->uniInitData.mgr.routes_list_size = ucsConfig->routesSize;
125     my->uniInitData.mgr.nodes_list_ptr = ucsConfig->pNod;
126     my->uniInitData.mgr.nodes_list_size = ucsConfig->nodSize;
127     my->uniInitData.mgr.enabled = true;
128     e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
129     if (NULL == e) return false;
130     e->cmd =  UnicensCmd_Init;
131     e->val.Init.init_ptr = &my->uniInitData;
132     RB_PopWritePtr(&my->rb);
133     UCSI_CB_OnServiceRequired(my->tag);
134     return true;
135 }
136
137 bool UCSI_ProcessRxData(UCSI_Data_t *my, const uint8_t *pBuffer, uint16_t len)
138 {
139     assert(MAGIC == my->magic);
140     if (NULL == my->uniLld || NULL == my->uniLldHPtr) return false;
141     Ucs_Lld_RxMsg_t *msg = NULL;
142     msg = my->uniLld->rx_allocate_fptr(my->uniLldHPtr, len);
143     if (NULL == msg)
144     {
145         //This may happen by definition, OnLldCtrlRxMsgAvailable()
146         //will be called, once buffers are available again
147         return false;
148     }
149     msg->data_size = len;
150     memcpy(msg->data_ptr, pBuffer, len);
151     my->uniLld->rx_receive_fptr(my->uniLldHPtr, msg);
152     return true;
153 }
154
155
156 void UCSI_Service(UCSI_Data_t *my) {
157     UnicensCmdEntry_t *e;
158     bool popEntry = true; //Set to false in specific case, where function will callback asynchrony.
159     assert(MAGIC == my->magic);
160     if (NULL != my->UNICENS && my->triggerService) {
161         my->triggerService = false;
162         Ucs_Service(my->UNICENS);
163     }
164     if (NULL != my->currentCmd) return;
165     my->currentCmd = e = (UnicensCmdEntry_t *)RB_GetReadPtr(&my->rb);
166     if (NULL == e) return;
167     switch (e->cmd) {
168         case UnicensCmd_Init:
169             if (UCS_RET_SUCCESS == Ucs_Init(my->UNICENS, e->val.Init.init_ptr, OnUcsInitResult))
170                 popEntry = false;
171             else
172                 UCSI_CB_OnUserMessage(my->tag, "Ucs_Init failed", 0);
173             break;
174         case UnicensCmd_Stop:
175             if (UCS_RET_SUCCESS == Ucs_Stop(my->UNICENS, OnUcsStopResult))
176                 popEntry = false;
177             else
178                 UCSI_CB_OnUserMessage(my->tag, "Ucs_Stop failed", 0);
179             break;
180         case UnicensCmd_RmSetRoute:
181             if (UCS_RET_SUCCESS != Ucs_Rm_SetRouteActive(my->UNICENS, e->val.RmSetRoute.routePtr, e->val.RmSetRoute.isActive))
182                 UCSI_CB_OnUserMessage(my->tag, "Ucs_Rm_SetRouteActive failed", 0);
183             break;
184         case UnicensCmd_NsRun:
185             if (UCS_RET_SUCCESS != Ucs_Ns_Run(my->UNICENS, e->val.NsRun.node_ptr, OnUcsNsRun))
186                 UCSI_CB_OnUserMessage(my->tag, "Ucs_Ns_Run failed", 0);
187             break;
188         default:
189             assert(false);
190             break;
191     }
192     if (popEntry)
193     {
194         my->currentCmd = NULL;
195         RB_PopReadPtr(&my->rb);
196     }
197 }
198
199 void UCSI_Timeout(UCSI_Data_t *my)
200 {
201     assert(MAGIC == my->magic);
202     if (NULL == my->UNICENS) return;
203     Ucs_ReportTimeout(my->UNICENS);
204 }
205
206 /************************************************************************/
207 /* Private Functions                                                    */
208 /************************************************************************/
209 static bool EnqueueCommand(UCSI_Data_t *my, UnicensCmdEntry_t *cmd)
210 {
211     UnicensCmdEntry_t *e;
212     if (NULL == my || NULL == cmd)
213     {
214         assert(false);
215         return false;
216     }
217     e = RB_GetWritePtr(&my->rb);
218     if (NULL == e)
219     {
220         UCSI_CB_OnUserMessage(my->tag, "Could not enqueue command. Increase CMD_QUEUE_LEN define", 0);
221         return false;
222     }
223     memcpy(e, cmd, sizeof(UnicensCmdEntry_t));
224     RB_PopWritePtr(&my->rb);
225     UCSI_CB_OnServiceRequired(my->tag);
226     return true;
227 }
228
229 static void OnCommandExecuted(UCSI_Data_t *my, UnicensCmd_t cmd)
230 {
231     if (NULL == my)
232     {
233         assert(false);
234         return;
235     }
236     if (NULL == my->currentCmd)
237     {
238         UCSI_CB_OnUserMessage(my->tag, "OnUniCommandExecuted was called, but no "\
239             "command is in queue", 0);
240         assert(false);
241         return;
242     }
243     if (my->currentCmd->cmd != cmd)
244     {
245         UCSI_CB_OnUserMessage(my->tag, "OnUniCommandExecuted was called with "\
246             "wrong command (Expected=0x%X, Got=0x%X", 2, my->currentCmd->cmd, cmd);
247         assert(false);
248         return;
249     }
250     my->currentCmd = NULL;
251     RB_PopReadPtr(&my->rb);
252 }
253
254 static void RB_Init(RB_t *rb, uint16_t amountOfEntries, uint32_t sizeOfEntry, uint8_t *workingBuffer)
255 {
256     assert(NULL != rb);
257     assert(NULL != workingBuffer);
258     rb->dataQueue = workingBuffer;
259     rb->pRx = rb->dataQueue;
260     rb->pTx = rb->dataQueue;
261     rb->amountOfEntries = amountOfEntries;
262     rb->sizeOfEntry = sizeOfEntry;
263     rb->rxPos = 0;
264     rb->txPos = 0;
265 }
266
267 static void *RB_GetReadPtr(RB_t *rb)
268 {
269     assert(NULL != rb);
270     assert(0 != rb->dataQueue);
271     if (rb->txPos - rb->rxPos > 0)
272     return (void *)rb->pRx;
273     return NULL;
274 }
275
276 static void RB_PopReadPtr(RB_t *rb)
277 {
278     assert(NULL != rb);
279     assert(0 != rb->dataQueue);
280
281     rb->pRx += rb->sizeOfEntry;
282     if (rb->pRx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
283     rb->pRx = rb->dataQueue;
284     ++rb->rxPos;
285     assert(rb->txPos >= rb->rxPos);
286 }
287
288 static void *RB_GetWritePtr(RB_t *rb)
289 {
290     assert(NULL != rb);
291     assert(0 != rb->dataQueue);
292     if (rb->txPos - rb->rxPos < rb->amountOfEntries)
293     return (void *)rb->pTx;
294     return NULL;
295 }
296
297 static void RB_PopWritePtr(RB_t *rb)
298 {
299     assert(NULL != rb);
300     assert(0 != rb->dataQueue);
301     rb->pTx += rb->sizeOfEntry;
302     if (rb->pTx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
303     rb->pTx = rb->dataQueue;
304     ++rb->txPos;
305     assert(rb->txPos >= rb->rxPos);
306 }
307
308 static uint16_t OnUnicensGetTime(void *user_ptr)
309 {
310     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
311     assert(MAGIC == my->magic);
312     return UCSI_CB_OnGetTime(my->tag);
313 }
314
315 static void OnUnicensService( void *user_ptr )
316 {
317     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
318     assert(MAGIC == my->magic);
319     my->triggerService = true;
320     UCSI_CB_OnServiceRequired(my->tag);
321 }
322
323 static void OnUnicensError( Ucs_Error_t error_code, void *user_ptr )
324 {
325     error_code = error_code;
326     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
327     assert(MAGIC == my->magic);
328     UCSI_CB_OnUserMessage(my->tag, "Unicens general error, code=0x%X", 1, error_code);
329 }
330
331 static void OnUnicensAppTimer( uint16_t timeout, void *user_ptr )
332 {
333     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
334     assert(MAGIC == my->magic);
335     UCSI_CB_OnSetServiceTimer(my->tag, timeout);
336 }
337
338 static void OnUnicensDebugErrorMsg(Msg_MostTel_t *m, void *user_ptr)
339 {
340     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
341     assert(MAGIC == my->magic);
342     UCSI_CB_OnMostError(my->tag, m->source_addr, m->id.fblock_id, m->id.instance_id,
343         m->id.function_id, m->id.op_type, m->tel.tel_data_ptr, m->tel.tel_len);
344 }
345
346 static void OnLldCtrlStart( Ucs_Lld_Api_t* api_ptr, void *inst_ptr, void *lld_user_ptr )
347 {
348     UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
349     assert(MAGIC == my->magic);
350     my->uniLld = api_ptr;
351     my->uniLldHPtr = inst_ptr;
352 }
353
354 static void OnLldCtrlStop( void *lld_user_ptr )
355 {
356     UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
357     assert(MAGIC == my->magic);
358     my->uniLld = NULL;
359     my->uniLldHPtr = NULL;
360 }
361
362 static void OnLldCtrlRxMsgAvailable( void *lld_user_ptr )
363 {
364     UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
365     assert(MAGIC == my->magic);
366     UCSI_CB_OnServiceRequired(my->tag);
367 }
368
369 static void OnLldCtrlTxTransmitC( Ucs_Lld_TxMsg_t *msg_ptr, void *lld_user_ptr )
370 {
371     UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
372     assert(MAGIC == my->magic);
373     uint8_t buffer[BOARD_PMS_TX_SIZE];
374     uint32_t bufferPos = 0;
375     Ucs_Mem_Buffer_t * buf_ptr;
376     if (NULL == msg_ptr || NULL == my || NULL == my->uniLld || NULL == my->uniLldHPtr)
377     {
378         assert(false);
379         return;
380     }
381     for (buf_ptr = msg_ptr->memory_ptr; buf_ptr != NULL; buf_ptr = buf_ptr->next_buffer_ptr)
382     {
383         if (buf_ptr->data_size + bufferPos > sizeof(buffer))
384         {
385             UCSI_CB_OnUserMessage(my->tag, "TX buffer is too small, increase " \
386                 "BOARD_PMS_TX_SIZE define (%lu > %lu)", 2, buf_ptr->data_size + bufferPos, sizeof(buffer));
387             my->uniLld->tx_release_fptr(my->uniLldHPtr, msg_ptr);
388             return;
389         }
390         memcpy(&buffer[bufferPos], buf_ptr->data_ptr, buf_ptr->data_size);
391         bufferPos += buf_ptr->data_size;
392     }
393     assert(bufferPos == msg_ptr->memory_ptr->total_size);
394     my->uniLld->tx_release_fptr(my->uniLldHPtr, msg_ptr);
395     UCSI_CB_SendMostMessage(my->tag, buffer, bufferPos);
396 }
397
398 static void OnUnicensRoutingResult(Ucs_Rm_Route_t* route_ptr, Ucs_Rm_RouteInfos_t route_infos, void *user_ptr)
399 {
400     //TODO: implement
401     route_ptr = route_ptr;
402     route_infos = route_infos;
403     user_ptr = user_ptr;
404 }
405
406 static void OnUnicensMostPortStatus(uint16_t most_port_handle,
407     Ucs_Most_PortAvail_t availability, Ucs_Most_PortAvailInfo_t avail_info,
408     uint16_t free_streaming_bw, void* user_ptr)
409 {
410     //TODO: implement
411     most_port_handle = most_port_handle;
412     availability = availability;
413     avail_info = avail_info;
414     free_streaming_bw = free_streaming_bw;
415     user_ptr = user_ptr;
416 }
417
418 static void OnUnicensDebugXrmResources(Ucs_Xrm_ResourceType_t resource_type,
419     Ucs_Xrm_ResObject_t *resource_ptr, Ucs_Xrm_ResourceInfos_t resource_infos,
420     Ucs_Rm_EndPoint_t *endpoint_inst_ptr, void *user_ptr)
421 {
422 #ifndef DEBUG_XRM
423     resource_type = resource_type;
424     resource_ptr = resource_ptr;
425     resource_infos = resource_infos;
426     endpoint_inst_ptr = endpoint_inst_ptr;
427     user_ptr = user_ptr;
428 #else
429     endpoint_inst_ptr = endpoint_inst_ptr;
430     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
431     assert(MAGIC == my->magic);
432     if (NULL == resource_ptr) return;
433     char *msg = NULL;
434     uint16_t adr = 0xFFFF;
435     if (endpoint_inst_ptr && endpoint_inst_ptr->node_obj_ptr &&
436             endpoint_inst_ptr->node_obj_ptr->signature_ptr)
437         adr = endpoint_inst_ptr->node_obj_ptr->signature_ptr->node_address;
438     switch (resource_infos)
439     {
440         case UCS_XRM_INFOS_BUILT:
441         msg = (char *)"has been built";
442         break;
443         case UCS_XRM_INFOS_DESTROYED:
444         msg = (char *)"has been destroyed";
445         break;
446         case UCS_XRM_INFOS_ERR_BUILT:
447         msg = (char *)"cannot be built";
448         break;
449         default:
450         msg = (char *)"cannot be destroyed";
451         break;
452     }
453     switch(resource_type)
454     {
455         case UCS_XRM_RC_TYPE_MOST_SOCKET:
456         {
457             Ucs_Xrm_MostSocket_t *ms = (Ucs_Xrm_MostSocket_t *)resource_ptr;
458             assert(ms->resource_type == resource_type);
459             UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): MOST socket %s, handle=%04X, "\
460                 "direction=%d, type=%d, bandwidth=%d", 6, adr, msg, ms->most_port_handle,
461                 ms->direction, ms->data_type, ms->bandwidth);
462             break;
463         }
464         case UCS_XRM_RC_TYPE_MLB_PORT:
465         {
466             Ucs_Xrm_MlbPort_t *m = (Ucs_Xrm_MlbPort_t *)resource_ptr;
467             assert(m->resource_type == resource_type);
468             UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): MLB port %s, index=%d, clock=%d", 4,
469                 adr, msg, m->index, m->clock_config);
470             break;
471         }
472         case UCS_XRM_RC_TYPE_MLB_SOCKET:
473         {
474             Ucs_Xrm_MlbSocket_t *m = (Ucs_Xrm_MlbSocket_t *)resource_ptr;
475             assert(m->resource_type == resource_type);
476             UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): MLB socket %s, direction=%d, type=%d,"\
477                 " bandwidth=%d, channel=%d", 6, adr, msg, m->direction, m->data_type,
478                 m->bandwidth, m->channel_address);
479             break;
480         }
481         case UCS_XRM_RC_TYPE_USB_PORT:
482         {
483             Ucs_Xrm_UsbPort_t *m = (Ucs_Xrm_UsbPort_t *)resource_ptr;
484             assert(m->resource_type == resource_type);
485             UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): USB port %s, in-cnt=%d, out-cnt=%d", 4,
486                 adr, msg, m->streaming_if_ep_in_count, m->streaming_if_ep_out_count);
487             break;
488         }
489         case UCS_XRM_RC_TYPE_USB_SOCKET:
490         {
491             Ucs_Xrm_UsbSocket_t *m = (Ucs_Xrm_UsbSocket_t *)resource_ptr;
492             assert(m->resource_type == resource_type);
493             UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): USB socket %s, direction=%d, type=%d," \
494                 " ep-addr=%02X, frames=%d", 6, adr, msg, m->direction, m->data_type,
495                 m->end_point_addr, m->frames_per_transfer);
496             break;
497         }
498         case UCS_XRM_RC_TYPE_STRM_PORT:
499         {
500             Ucs_Xrm_StrmPort_t *m = (Ucs_Xrm_StrmPort_t *)resource_ptr;
501             assert(m->resource_type == resource_type);
502             UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): I2S port %s, index=%d, clock=%d, "\
503                 "align=%d", 5, adr, msg, m->index, m->clock_config, m->data_alignment);
504             break;
505         }
506         case UCS_XRM_RC_TYPE_STRM_SOCKET:
507         {
508             Ucs_Xrm_StrmSocket_t *m = (Ucs_Xrm_StrmSocket_t *)resource_ptr;
509             assert(m->resource_type == resource_type);
510             UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): I2S socket %s, direction=%d, type=%d"\
511                 ", bandwidth=%d, pin=%d", 6, adr, msg, m->direction, m->data_type,
512                 m->bandwidth, m->stream_pin_id);
513             break;
514         }
515         case UCS_XRM_RC_TYPE_SYNC_CON:
516         {
517             Ucs_Xrm_SyncCon_t *m = (Ucs_Xrm_SyncCon_t *)resource_ptr;
518             assert(m->resource_type == resource_type);
519             UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): Sync connection %s, mute=%d, "\
520                 "offset=%d", 4, adr, msg, m->mute_mode, m->offset);
521             break;
522         }
523         case UCS_XRM_RC_TYPE_COMBINER:
524         {
525             Ucs_Xrm_Combiner_t *m = (Ucs_Xrm_Combiner_t *)resource_ptr;
526             assert(m->resource_type == resource_type);
527             UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): Combiner %s, bytes per frame=%d",
528                 3, adr, msg, m->bytes_per_frame);
529             break;
530         }
531         case UCS_XRM_RC_TYPE_SPLITTER:
532         {
533             Ucs_Xrm_Splitter_t *m = (Ucs_Xrm_Splitter_t *)resource_ptr;
534             assert(m->resource_type == resource_type);
535             UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): Splitter %s, bytes per frame=%d",
536                 3, adr, msg, m->bytes_per_frame);
537             break;
538         }
539         case UCS_XRM_RC_TYPE_AVP_CON:
540         {
541             Ucs_Xrm_AvpCon_t *m = (Ucs_Xrm_AvpCon_t *)resource_ptr;
542             assert(m->resource_type == resource_type);
543             UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): Isoc-AVP connection %s, packetSize=%d",
544                 3, adr, msg, m->isoc_packet_size);
545             break;
546         }
547         default:
548         UCSI_CB_OnUserMessage(my->tag, "Xrm-Debug (0x%03X): Unknown type=%d %s", 3 , adr, resource_type, msg);
549     }
550 #endif
551 }
552
553 static void OnUcsInitResult(Ucs_InitResult_t result, void *user_ptr)
554 {
555     UnicensCmdEntry_t e;
556     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
557     assert(MAGIC == my->magic);
558     my->initialized = (UCS_INIT_RES_SUCCESS == result);
559     OnCommandExecuted(my, UnicensCmd_Init);
560     if (!my->initialized)
561     {
562         UCSI_CB_OnUserMessage(my->tag, "UcsInitResult reported error (0x%X), restarting...", 1, result);
563         e.cmd = UnicensCmd_Init;
564         e.val.Init.init_ptr = &my->uniInitData;
565         EnqueueCommand(my, &e);
566     }
567 }
568
569 static void OnUcsStopResult(Ucs_StdResult_t result, void *user_ptr)
570 {
571     result = result; //TODO: check error case
572     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
573     assert(MAGIC == my->magic);
574     my->initialized = false;
575     OnCommandExecuted(my, UnicensCmd_Stop);
576     UCSI_CB_OnStop(my->tag);
577 }
578
579 static void OnUcsMgrReport(Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr, void *user_ptr)
580 {
581     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
582     assert(MAGIC == my->magic);
583     if (node_ptr && node_ptr->script_list_ptr && node_ptr->script_list_size)
584     {
585         UnicensCmdEntry_t e;
586         e.cmd = UnicensCmd_NsRun;
587         e.val.NsRun.node_ptr = node_ptr;
588         EnqueueCommand(my, &e);
589     }
590     UCSI_CB_OnMgrReport(my->tag, code, node_address, node_ptr);
591 }
592
593 static void OnUcsNsRun(Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCode_t result, void *ucs_user_ptr)
594 {
595 #ifndef DEBUG_XRM
596     node_ptr = node_ptr;
597     result = result;
598     ucs_user_ptr;
599 #else
600     UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
601     assert(MAGIC == my->magic);
602     UCSI_CB_OnUserMessage(my->tag, "OnUcsNsRun (%03X): script executed %s",
603         2, node_ptr->signature_ptr->node_address,
604         (UCS_NS_RES_SUCCESS == result ? "succeeded" : "false"));
605 #endif
606 }
607
608 /*----------------------------------------
609  * Debug Message output from Unicens stack:
610  *----------------------------------------
611  */
612 #if defined(UCS_TR_ERROR) || defined(UCS_TR_INFO)
613 #include <stdio.h>
614 #define TRACE_BUFFER_SZ 200
615 void App_TraceError(void *ucs_user_ptr, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
616 {
617     void *tag = NULL;
618     UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
619     if (my)
620     {
621         assert(MAGIC == my->magic);
622         tag = my->tag;
623     }
624     char outbuf[TRACE_BUFFER_SZ];
625     va_list argptr;
626     va_start(argptr, vargs_cnt);
627     vsprintf(outbuf, entry_str, argptr);
628     va_end(argptr);
629     UCSI_CB_OnUserMessage(tag, "Error | %s | %s", 2, module_str, outbuf);
630 }
631 void App_TraceInfo(void *ucs_user_ptr, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
632 {
633     void *tag = NULL;
634     UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
635     if (my)
636     {
637         assert(MAGIC == my->magic);
638         tag = my->tag;
639     }
640     char outbuf[TRACE_BUFFER_SZ];
641     va_list argptr;
642     va_start(argptr, vargs_cnt);
643     vsprintf(outbuf, entry_str, argptr);
644     va_end(argptr);
645     UCSI_CB_OnUserMessage(tag, "Info | %s | %s", 2, module_str, outbuf);
646 }
647 #endif