5a6c08b73cd3a48527ed3334594179a0eb546d2d
[apps/agl-service-unicens.git] / ucs2-interface / ucs_lib_interf.c
1 /*------------------------------------------------------------------------------------------------*/
2 /* Unicens Integration Helper Component                                                           */
3 /* Copyright 2017, Microchip Technology Inc. and its subsidiaries.                                */
4 /*                                                                                                */
5 /* Redistribution and use in source and binary forms, with or without                             */
6 /* modification, are permitted provided that the following conditions are met:                    */
7 /*                                                                                                */
8 /* 1. Redistributions of source code must retain the above copyright notice, this                 */
9 /*    list of conditions and the following disclaimer.                                            */
10 /*                                                                                                */
11 /* 2. Redistributions in binary form must reproduce the above copyright notice,                   */
12 /*    this list of conditions and the following disclaimer in the documentation                   */
13 /*    and/or other materials provided with the distribution.                                      */
14 /*                                                                                                */
15 /* 3. Neither the name of the copyright holder nor the names of its                               */
16 /*    contributors may be used to endorse or promote products derived from                        */
17 /*    this software without specific prior written permission.                                    */
18 /*                                                                                                */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"                    */
20 /* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE                      */
21 /* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE                 */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE                   */
23 /* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL                     */
24 /* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR                     */
25 /* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER                     */
26 /* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,                  */
27 /* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE                  */
28 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
29 /*------------------------------------------------------------------------------------------------*/
30 #include <assert.h>
31 #include <stdio.h>
32 #include "ucs_interface.h"
33
34 /************************************************************************/
35 /* Private Definitions and variables                                    */
36 /************************************************************************/
37 #define MAGIC (0xA144BEAF)
38
39 /************************************************************************/
40 /* Private Function Prototypes                                          */
41 /************************************************************************/
42 static bool EnqueueCommand(UCSI_Data_t *my, UnicensCmdEntry_t *cmd);
43 static void OnCommandExecuted(UCSI_Data_t *my, UnicensCmd_t cmd);
44 static void RB_Init(RB_t *rb, uint16_t amountOfEntries, uint32_t sizeOfEntry, uint8_t *workingBuffer);
45 static void *RB_GetReadPtr(RB_t *rb);
46 static void RB_PopReadPtr(RB_t *rb);
47 static void *RB_GetWritePtr(RB_t *rb);
48 static void RB_PopWritePtr(RB_t *rb);
49 static uint16_t OnUnicensGetTime(void *user_ptr);
50 static void OnUnicensService( void *user_ptr );
51 static void OnUnicensError( Ucs_Error_t error_code, void *user_ptr );
52 static void OnUnicensAppTimer( uint16_t timeout, void *user_ptr );
53 static void OnUnicensDebugErrorMsg(Msg_MostTel_t *m, void *user_ptr);
54 static void OnLldCtrlStart( Ucs_Lld_Api_t* api_ptr, void *inst_ptr, void *lld_user_ptr );
55 static void OnLldCtrlStop( void *lld_user_ptr );
56 static void OnLldCtrlRxMsgAvailable( void *lld_user_ptr );
57 static void OnLldCtrlTxTransmitC( Ucs_Lld_TxMsg_t *msg_ptr, void *lld_user_ptr );
58 static void OnUnicensRoutingResult(Ucs_Rm_Route_t* route_ptr, Ucs_Rm_RouteInfos_t route_infos, void *user_ptr);
59 static void OnUnicensMostPortStatus(uint16_t most_port_handle,
60     Ucs_Most_PortAvail_t availability, Ucs_Most_PortAvailInfo_t avail_info,
61     uint16_t free_streaming_bw, void* user_ptr);
62 static void OnUnicensDebugXrmResources(Ucs_Xrm_ResourceType_t resource_type,
63     Ucs_Xrm_ResObject_t *resource_ptr, Ucs_Xrm_ResourceInfos_t resource_infos,
64     Ucs_Rm_EndPoint_t *endpoint_inst_ptr, void *user_ptr);
65 static void OnUcsInitResult(Ucs_InitResult_t result, void *user_ptr);
66 static void OnUcsStopResult(Ucs_StdResult_t result, void *user_ptr);
67 static void OnUcsMgrReport(Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr, void *user_ptr);
68 static void OnUcsNsRun(Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCode_t result, void *ucs_user_ptr);
69 static void OnUcsAmsRxMsgReceived(void *user_ptr);
70
71 /************************************************************************/
72 /* Public Function Implementations                                      */
73 /************************************************************************/
74
75 void UCSI_Init(UCSI_Data_t *my, void *pTag)
76 {
77     Ucs_Return_t result;
78     assert(NULL != my);
79     memset(my, 0, sizeof(UCSI_Data_t));
80     my->magic = MAGIC;
81     my->tag = pTag;
82     my->unicens = Ucs_CreateInstance();
83     if (NULL == my->unicens)
84     {
85         UCSI_CB_OnUserMessage(my->tag, true, "Can not instance a new version of UNICENS, "\
86             "increase UCS_NUM_INSTANCES define", 0);
87         assert(false);
88         return;
89     }
90     result = Ucs_SetDefaultConfig(&my->uniInitData);
91     if(UCS_RET_SUCCESS != result)
92     {
93         UCSI_CB_OnUserMessage(my->tag, true, "Can not set default values to Unicens config (result=0x%X)", 1, result);
94         assert(false);
95         return;
96     }
97     my->uniInitData.user_ptr = my;
98     my->uniInitData.mgr.report_fptr = OnUcsMgrReport;
99
100     my->uniInitData.general.inic_watchdog_enabled = ENABLE_INIC_WATCHDOG;
101     my->uniInitData.general.get_tick_count_fptr = &OnUnicensGetTime;
102     my->uniInitData.general.request_service_fptr = &OnUnicensService;
103     my->uniInitData.general.error_fptr = &OnUnicensError;
104     my->uniInitData.general.set_application_timer_fptr = &OnUnicensAppTimer;
105     my->uniInitData.general.debug_error_msg_fptr = &OnUnicensDebugErrorMsg;
106     my->uniInitData.ams.enabled = ENABLE_AMS_LIB;
107     my->uniInitData.ams.rx.message_received_fptr = &OnUcsAmsRxMsgReceived;
108
109     my->uniInitData.lld.lld_user_ptr = my;
110     my->uniInitData.lld.start_fptr =  &OnLldCtrlStart;
111     my->uniInitData.lld.stop_fptr = &OnLldCtrlStop;
112     my->uniInitData.lld.rx_available_fptr = &OnLldCtrlRxMsgAvailable;
113     my->uniInitData.lld.tx_transmit_fptr = &OnLldCtrlTxTransmitC;
114
115     my->uniInitData.rm.report_fptr = &OnUnicensRoutingResult;
116     my->uniInitData.rm.xrm.most_port_status_fptr = &OnUnicensMostPortStatus;
117     my->uniInitData.rm.debug_resource_status_fptr = &OnUnicensDebugXrmResources;
118
119     RB_Init(&my->rb, CMD_QUEUE_LEN, sizeof(UnicensCmdEntry_t), my->rbBuf);
120 }
121
122 bool UCSI_NewConfig(UCSI_Data_t *my, UcsXmlVal_t *ucsConfig) {
123
124     UnicensCmdEntry_t *e;
125     assert(MAGIC == my->magic);
126     if (my->initialized)
127     {
128         e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
129         if (NULL == e) return false;
130         e->cmd = UnicensCmd_Stop;
131         RB_PopWritePtr(&my->rb);
132     }
133     my->uniInitData.mgr.packet_bw = ucsConfig->packetBw;
134     my->uniInitData.mgr.routes_list_ptr = ucsConfig->pRoutes;
135     my->uniInitData.mgr.routes_list_size = ucsConfig->routesSize;
136     my->uniInitData.mgr.nodes_list_ptr = ucsConfig->pNod;
137     my->uniInitData.mgr.nodes_list_size = ucsConfig->nodSize;
138     my->uniInitData.mgr.enabled = true;
139     e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
140     if (NULL == e) return false;
141     e->cmd =  UnicensCmd_Init;
142     e->val.Init.init_ptr = &my->uniInitData;
143     RB_PopWritePtr(&my->rb);
144     UCSI_CB_OnServiceRequired(my->tag);
145     return true;
146 }
147
148 bool UCSI_ProcessRxData(UCSI_Data_t *my,
149     const uint8_t *pBuffer, uint16_t len)
150 {
151     Ucs_Lld_RxMsg_t *msg = NULL;
152     assert(MAGIC == my->magic);
153     if (NULL == my->uniLld || NULL == my->uniLldHPtr) return false;
154     msg = my->uniLld->rx_allocate_fptr(my->uniLldHPtr, len);
155     if (NULL == msg)
156     {
157         /*This may happen by definition, OnLldCtrlRxMsgAvailable()
158           will be called, once buffers are available again*/
159         return false;
160     }
161     msg->data_size = len;
162     memcpy(msg->data_ptr, pBuffer, len);
163     my->uniLld->rx_receive_fptr(my->uniLldHPtr, msg);
164     return true;
165 }
166
167 void UCSI_Service(UCSI_Data_t *my)
168 {
169     UnicensCmdEntry_t *e;
170     bool popEntry = true; /*Set to false in specific case, where function will callback asynchrony.*/
171     assert(MAGIC == my->magic);
172     if (NULL != my->unicens && my->triggerService) {
173         my->triggerService = false;
174         Ucs_Service(my->unicens);
175     }
176     if (NULL != my->currentCmd) return;
177     my->currentCmd = e = (UnicensCmdEntry_t *)RB_GetReadPtr(&my->rb);
178     if (NULL == e) return;
179     switch (e->cmd) {
180         case UnicensCmd_Init:
181             if (UCS_RET_SUCCESS == Ucs_Init(my->unicens, e->val.Init.init_ptr, OnUcsInitResult))
182                 popEntry = false;
183             else
184                 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Init failed", 0);
185             break;
186         case UnicensCmd_Stop:
187             if (UCS_RET_SUCCESS == Ucs_Stop(my->unicens, OnUcsStopResult))
188                 popEntry = false;
189             else
190                 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Stop failed", 0);
191             break;
192         case UnicensCmd_RmSetRoute:
193             if (UCS_RET_SUCCESS != Ucs_Rm_SetRouteActive(my->unicens, e->val.RmSetRoute.routePtr, e->val.RmSetRoute.isActive))
194                 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Rm_SetRouteActive failed", 0);
195             break;
196         case UnicensCmd_NsRun:
197             if (UCS_RET_SUCCESS != Ucs_Ns_Run(my->unicens, e->val.NsRun.node_ptr, OnUcsNsRun))
198                 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Ns_Run failed", 0);
199             break;
200         default:
201             assert(false);
202             break;
203     }
204     if (popEntry)
205     {
206         my->currentCmd = NULL;
207         RB_PopReadPtr(&my->rb);
208     }
209 }
210
211 void UCSI_Timeout(UCSI_Data_t *my)
212 {
213     assert(MAGIC == my->magic);
214     if (NULL == my->unicens) return;
215     Ucs_ReportTimeout(my->unicens);
216 }
217
218 bool UCSI_SendAmsMessage(UCSI_Data_t *my, uint16_t msgId, uint16_t targetAddress, uint8_t *pPayload, uint32_t payloadLen)
219 {
220     Ucs_AmsTx_Msg_t *msg;
221     Ucs_Return_t result;
222     assert(MAGIC == my->magic);
223     if (NULL == my->unicens) return false;
224     msg = Ucs_AmsTx_AllocMsg(my->unicens, payloadLen);
225     if (NULL == msg) return false;
226     if (0 != payloadLen)
227     {
228         assert(NULL != msg->data_ptr);
229         memcpy(msg->data_ptr, pPayload, payloadLen);
230     }
231     msg->custom_info_ptr = NULL;
232     msg->data_size = payloadLen;
233     msg->destination_address = targetAddress;
234     msg->llrbc = 10;
235     msg->msg_id = msgId;
236     result = Ucs_AmsTx_SendMsg(my->unicens, msg, NULL);
237     if (UCS_RET_SUCCESS != result)
238         Ucs_AmsTx_FreeUnusedMsg(my->unicens, msg);
239     return UCS_RET_SUCCESS == result;
240 }
241
242 bool UCSI_GetAmsMessage(UCSI_Data_t *my, uint16_t *pMsgId, uint16_t *pSourceAddress, uint8_t **pPayload, uint32_t *pPayloadLen)
243 {
244     Ucs_AmsRx_Msg_t *msg;
245     assert(MAGIC == my->magic);
246     if (NULL == my->unicens || NULL == pPayload || NULL == pPayloadLen) return false;
247     msg = Ucs_AmsRx_PeekMsg(my->unicens);
248     if (NULL == msg) return false;
249     *pMsgId = msg->msg_id;
250     *pSourceAddress = msg->source_address;
251     *pPayload = msg->data_ptr;
252     *pPayloadLen = msg->data_size;
253     return true;
254 }
255
256 void UCSI_ReleaseAmsMessage(UCSI_Data_t *my)
257 {
258     assert(MAGIC == my->magic);
259     if (NULL == my->unicens) return;
260     Ucs_AmsRx_ReleaseMsg(my->unicens);
261 }
262
263 bool UCSI_SetRouteActive(UCSI_Data_t *my, uint16_t routeId, bool isActive)
264 {
265     uint16_t i;
266     UnicensCmdEntry_t entry;
267     assert(MAGIC == my->magic);
268     if (NULL == my || NULL == my->uniInitData.mgr.routes_list_ptr) return false;
269     for (i = 0; i < my->uniInitData.mgr.routes_list_size; i++)
270     {
271         Ucs_Rm_Route_t *route = &my->uniInitData.mgr.routes_list_ptr[i];
272         if (route->route_id != routeId)
273             continue;
274         entry.cmd = UnicensCmd_RmSetRoute;
275         entry.val.RmSetRoute.routePtr = route;
276         entry.val.RmSetRoute.isActive = isActive;
277         return EnqueueCommand(my, &entry);
278     }
279     return false;
280 }
281
282 /************************************************************************/
283 /* Private Functions                                                    */
284 /************************************************************************/
285 static bool EnqueueCommand(UCSI_Data_t *my, UnicensCmdEntry_t *cmd)
286 {
287     UnicensCmdEntry_t *e;
288     if (NULL == my || NULL == cmd)
289     {
290         assert(false);
291         return false;
292     }
293     e = RB_GetWritePtr(&my->rb);
294     if (NULL == e)
295     {
296         UCSI_CB_OnUserMessage(my->tag, true, "Could not enqueue command. Increase CMD_QUEUE_LEN define", 0);
297         return false;
298     }
299     memcpy(e, cmd, sizeof(UnicensCmdEntry_t));
300     RB_PopWritePtr(&my->rb);
301     UCSI_CB_OnServiceRequired(my->tag);
302     return true;
303 }
304
305 static void OnCommandExecuted(UCSI_Data_t *my, UnicensCmd_t cmd)
306 {
307     if (NULL == my)
308     {
309         assert(false);
310         return;
311     }
312     if (NULL == my->currentCmd)
313     {
314         UCSI_CB_OnUserMessage(my->tag, true, "OnUniCommandExecuted was called, but no "\
315             "command is in queue", 0);
316         assert(false);
317         return;
318     }
319     if (my->currentCmd->cmd != cmd)
320     {
321         UCSI_CB_OnUserMessage(my->tag, true, "OnUniCommandExecuted was called with "\
322             "wrong command (Expected=0x%X, Got=0x%X", 2, my->currentCmd->cmd, cmd);
323         assert(false);
324         return;
325     }
326     my->currentCmd = NULL;
327     RB_PopReadPtr(&my->rb);
328 }
329
330 static void RB_Init(RB_t *rb, uint16_t amountOfEntries, uint32_t sizeOfEntry, uint8_t *workingBuffer)
331 {
332     assert(NULL != rb);
333     assert(NULL != workingBuffer);
334     rb->dataQueue = workingBuffer;
335     rb->pRx = rb->dataQueue;
336     rb->pTx = rb->dataQueue;
337     rb->amountOfEntries = amountOfEntries;
338     rb->sizeOfEntry = sizeOfEntry;
339     rb->rxPos = 0;
340     rb->txPos = 0;
341 }
342
343 static void *RB_GetReadPtr(RB_t *rb)
344 {
345     assert(NULL != rb);
346     assert(0 != rb->dataQueue);
347     if (rb->txPos - rb->rxPos > 0)
348     return (void *)rb->pRx;
349     return NULL;
350 }
351
352 static void RB_PopReadPtr(RB_t *rb)
353 {
354     assert(NULL != rb);
355     assert(0 != rb->dataQueue);
356
357     rb->pRx += rb->sizeOfEntry;
358     if (rb->pRx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
359     rb->pRx = rb->dataQueue;
360     ++rb->rxPos;
361     assert(rb->txPos >= rb->rxPos);
362 }
363
364 static void *RB_GetWritePtr(RB_t *rb)
365 {
366     assert(NULL != rb);
367     assert(0 != rb->dataQueue);
368     if (rb->txPos - rb->rxPos < rb->amountOfEntries)
369     return (void *)rb->pTx;
370     return NULL;
371 }
372
373 static void RB_PopWritePtr(RB_t *rb)
374 {
375     assert(NULL != rb);
376     assert(0 != rb->dataQueue);
377     rb->pTx += rb->sizeOfEntry;
378     if (rb->pTx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
379     rb->pTx = rb->dataQueue;
380     ++rb->txPos;
381     assert(rb->txPos >= rb->rxPos);
382 }
383
384 static uint16_t OnUnicensGetTime(void *user_ptr)
385 {
386     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
387     assert(MAGIC == my->magic);
388     return UCSI_CB_OnGetTime(my->tag);
389 }
390
391 static void OnUnicensService( void *user_ptr )
392 {
393     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
394     assert(MAGIC == my->magic);
395     my->triggerService = true;
396     UCSI_CB_OnServiceRequired(my->tag);
397 }
398
399 static void OnUnicensError( Ucs_Error_t error_code, void *user_ptr )
400 {
401     UnicensCmdEntry_t e;
402     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
403     error_code = error_code;
404     assert(MAGIC == my->magic);
405     UCSI_CB_OnUserMessage(my->tag, true, "Unicens general error, code=0x%X, restarting", 1, error_code);
406     e.cmd = UnicensCmd_Init;
407     e.val.Init.init_ptr = &my->uniInitData;
408     EnqueueCommand(my, &e);
409 }
410
411 static void OnUnicensAppTimer( uint16_t timeout, void *user_ptr )
412 {
413     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
414     assert(MAGIC == my->magic);
415     UCSI_CB_OnSetServiceTimer(my->tag, timeout);
416 }
417
418 static void OnUnicensDebugErrorMsg(Msg_MostTel_t *m, void *user_ptr)
419 {
420     char buffer[100];
421     char val[5];
422     uint8_t i;
423     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
424     assert(MAGIC == my->magic);
425     buffer[0] = '\0';
426     for (i = 0; NULL != m->tel.tel_data_ptr && i < m->tel.tel_len; i++)
427     {
428         snprintf(val, sizeof(val), "%02X ", m->tel.tel_data_ptr[i]);
429         strcat(buffer, val);
430     }
431     UCSI_CB_OnUserMessage(my->tag, true, "Received error message, source=%x, %X.%X.%X.%X, [ %s ]",
432         6, m->source_addr, m->id.fblock_id, m->id.instance_id,
433         m->id.function_id, m->id.op_type, buffer);
434 }
435
436 static void OnLldCtrlStart( Ucs_Lld_Api_t* api_ptr, void *inst_ptr, void *lld_user_ptr )
437 {
438     UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
439     assert(MAGIC == my->magic);
440     my->uniLld = api_ptr;
441     my->uniLldHPtr = inst_ptr;
442 }
443
444 static void OnLldCtrlStop( void *lld_user_ptr )
445 {
446     UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
447     assert(MAGIC == my->magic);
448     my->uniLld = NULL;
449     my->uniLldHPtr = NULL;
450 }
451
452 static void OnLldCtrlRxMsgAvailable( void *lld_user_ptr )
453 {
454     UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
455     assert(MAGIC == my->magic);
456     UCSI_CB_OnServiceRequired(my->tag);
457 }
458
459 static void OnLldCtrlTxTransmitC( Ucs_Lld_TxMsg_t *msg_ptr, void *lld_user_ptr )
460 {
461     UCSI_Data_t *my;
462     Ucs_Mem_Buffer_t * buf_ptr;
463     uint8_t buffer[BOARD_PMS_TX_SIZE];
464     uint32_t bufferPos = 0;
465     my = (UCSI_Data_t *)lld_user_ptr;
466     assert(MAGIC == my->magic);
467     if (NULL == msg_ptr || NULL == my || NULL == my->uniLld || NULL == my->uniLldHPtr)
468     {
469         assert(false);
470         return;
471     }
472     for (buf_ptr = msg_ptr->memory_ptr; buf_ptr != NULL; buf_ptr = buf_ptr->next_buffer_ptr)
473     {
474         if (buf_ptr->data_size + bufferPos > sizeof(buffer))
475         {
476             UCSI_CB_OnUserMessage(my->tag, true, "TX buffer is too small, increase " \
477                 "BOARD_PMS_TX_SIZE define (%lu > %lu)", 2, buf_ptr->data_size + bufferPos, sizeof(buffer));
478             my->uniLld->tx_release_fptr(my->uniLldHPtr, msg_ptr);
479             return;
480         }
481         memcpy(&buffer[bufferPos], buf_ptr->data_ptr, buf_ptr->data_size);
482         bufferPos += buf_ptr->data_size;
483     }
484     assert(bufferPos == msg_ptr->memory_ptr->total_size);
485     my->uniLld->tx_release_fptr(my->uniLldHPtr, msg_ptr);
486     UCSI_CB_OnTxRequest(my->tag, buffer, bufferPos);
487 }
488
489 static void OnUnicensRoutingResult(Ucs_Rm_Route_t* route_ptr, Ucs_Rm_RouteInfos_t route_infos, void *user_ptr)
490 {
491     /*TODO: implement*/
492     route_ptr = route_ptr;
493     route_infos = route_infos;
494     user_ptr = user_ptr;
495 }
496
497 static void OnUnicensMostPortStatus(uint16_t most_port_handle,
498     Ucs_Most_PortAvail_t availability, Ucs_Most_PortAvailInfo_t avail_info,
499     uint16_t free_streaming_bw, void* user_ptr)
500 {
501     /*TODO: implement*/
502     most_port_handle = most_port_handle;
503     availability = availability;
504     avail_info = avail_info;
505     free_streaming_bw = free_streaming_bw;
506     user_ptr = user_ptr;
507 }
508
509 static void OnUnicensDebugXrmResources(Ucs_Xrm_ResourceType_t resource_type,
510     Ucs_Xrm_ResObject_t *resource_ptr, Ucs_Xrm_ResourceInfos_t resource_infos,
511     Ucs_Rm_EndPoint_t *endpoint_inst_ptr, void *user_ptr)
512 {
513     char *msg = NULL;
514     UCSI_Data_t *my;
515     uint16_t adr = 0xFFFF;
516 #ifndef DEBUG_XRM
517     resource_type = resource_type;
518     resource_ptr = resource_ptr;
519     resource_infos = resource_infos;
520     endpoint_inst_ptr = endpoint_inst_ptr;
521     user_ptr = user_ptr;
522 #else
523     endpoint_inst_ptr = endpoint_inst_ptr;
524     my = (UCSI_Data_t *)user_ptr;
525     assert(MAGIC == my->magic);
526     if (NULL == resource_ptr) return;
527     if (endpoint_inst_ptr && endpoint_inst_ptr->node_obj_ptr &&
528             endpoint_inst_ptr->node_obj_ptr->signature_ptr)
529         adr = endpoint_inst_ptr->node_obj_ptr->signature_ptr->node_address;
530     switch (resource_infos)
531     {
532         case UCS_XRM_INFOS_BUILT:
533         msg = (char *)"has been built";
534         break;
535         case UCS_XRM_INFOS_DESTROYED:
536         msg = (char *)"has been destroyed";
537         break;
538         case UCS_XRM_INFOS_ERR_BUILT:
539         msg = (char *)"cannot be built";
540         break;
541         default:
542         msg = (char *)"cannot be destroyed";
543         break;
544     }
545     switch(resource_type)
546     {
547         case UCS_XRM_RC_TYPE_MOST_SOCKET:
548         {
549             Ucs_Xrm_MostSocket_t *ms = (Ucs_Xrm_MostSocket_t *)resource_ptr;
550             assert(ms->resource_type == resource_type);
551             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): MOST socket %s, handle=%04X, "\
552                 "direction=%d, type=%d, bandwidth=%d", 6, adr, msg, ms->most_port_handle,
553                 ms->direction, ms->data_type, ms->bandwidth);
554             break;
555         }
556         case UCS_XRM_RC_TYPE_MLB_PORT:
557         {
558             Ucs_Xrm_MlbPort_t *m = (Ucs_Xrm_MlbPort_t *)resource_ptr;
559             assert(m->resource_type == resource_type);
560             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): MLB port %s, index=%d, clock=%d", 4,
561                 adr, msg, m->index, m->clock_config);
562             break;
563         }
564         case UCS_XRM_RC_TYPE_MLB_SOCKET:
565         {
566             Ucs_Xrm_MlbSocket_t *m = (Ucs_Xrm_MlbSocket_t *)resource_ptr;
567             assert(m->resource_type == resource_type);
568             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): MLB socket %s, direction=%d, type=%d,"\
569                 " bandwidth=%d, channel=%d", 6, adr, msg, m->direction, m->data_type,
570                 m->bandwidth, m->channel_address);
571             break;
572         }
573         case UCS_XRM_RC_TYPE_USB_PORT:
574         {
575             Ucs_Xrm_UsbPort_t *m = (Ucs_Xrm_UsbPort_t *)resource_ptr;
576             assert(m->resource_type == resource_type);
577             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): USB port %s, in-cnt=%d, out-cnt=%d", 4,
578                 adr, msg, m->streaming_if_ep_in_count, m->streaming_if_ep_out_count);
579             break;
580         }
581         case UCS_XRM_RC_TYPE_USB_SOCKET:
582         {
583             Ucs_Xrm_UsbSocket_t *m = (Ucs_Xrm_UsbSocket_t *)resource_ptr;
584             assert(m->resource_type == resource_type);
585             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): USB socket %s, direction=%d, type=%d," \
586                 " ep-addr=%02X, frames=%d", 6, adr, msg, m->direction, m->data_type,
587                 m->end_point_addr, m->frames_per_transfer);
588             break;
589         }
590         case UCS_XRM_RC_TYPE_STRM_PORT:
591         {
592             Ucs_Xrm_StrmPort_t *m = (Ucs_Xrm_StrmPort_t *)resource_ptr;
593             assert(m->resource_type == resource_type);
594             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): I2S port %s, index=%d, clock=%d, "\
595                 "align=%d", 5, adr, msg, m->index, m->clock_config, m->data_alignment);
596             break;
597         }
598         case UCS_XRM_RC_TYPE_STRM_SOCKET:
599         {
600             Ucs_Xrm_StrmSocket_t *m = (Ucs_Xrm_StrmSocket_t *)resource_ptr;
601             assert(m->resource_type == resource_type);
602             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): I2S socket %s, direction=%d, type=%d"\
603                 ", bandwidth=%d, pin=%d", 6, adr, msg, m->direction, m->data_type,
604                 m->bandwidth, m->stream_pin_id);
605             break;
606         }
607         case UCS_XRM_RC_TYPE_SYNC_CON:
608         {
609             Ucs_Xrm_SyncCon_t *m = (Ucs_Xrm_SyncCon_t *)resource_ptr;
610             assert(m->resource_type == resource_type);
611             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Sync connection %s, mute=%d, "\
612                 "offset=%d", 4, adr, msg, m->mute_mode, m->offset);
613             break;
614         }
615         case UCS_XRM_RC_TYPE_COMBINER:
616         {
617             Ucs_Xrm_Combiner_t *m = (Ucs_Xrm_Combiner_t *)resource_ptr;
618             assert(m->resource_type == resource_type);
619             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Combiner %s, bytes per frame=%d",
620                 3, adr, msg, m->bytes_per_frame);
621             break;
622         }
623         case UCS_XRM_RC_TYPE_SPLITTER:
624         {
625             Ucs_Xrm_Splitter_t *m = (Ucs_Xrm_Splitter_t *)resource_ptr;
626             assert(m->resource_type == resource_type);
627             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Splitter %s, bytes per frame=%d",
628                 3, adr, msg, m->bytes_per_frame);
629             break;
630         }
631         case UCS_XRM_RC_TYPE_AVP_CON:
632         {
633             Ucs_Xrm_AvpCon_t *m = (Ucs_Xrm_AvpCon_t *)resource_ptr;
634             assert(m->resource_type == resource_type);
635             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Isoc-AVP connection %s, packetSize=%d",
636                 3, adr, msg, m->isoc_packet_size);
637             break;
638         }
639         default:
640         UCSI_CB_OnUserMessage(my->tag, true, "Xrm-Debug (0x%03X): Unknown type=%d %s", 3 , adr, resource_type, msg);
641     }
642 #endif
643 }
644
645 static void OnUcsInitResult(Ucs_InitResult_t result, void *user_ptr)
646 {
647     UnicensCmdEntry_t e;
648     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
649     assert(MAGIC == my->magic);
650     my->initialized = (UCS_INIT_RES_SUCCESS == result);
651     OnCommandExecuted(my, UnicensCmd_Init);
652     if (!my->initialized)
653     {
654         UCSI_CB_OnUserMessage(my->tag, true, "UcsInitResult reported error (0x%X), restarting...", 1, result);
655         e.cmd = UnicensCmd_Init;
656         e.val.Init.init_ptr = &my->uniInitData;
657         EnqueueCommand(my, &e);
658     }
659 }
660
661 static void OnUcsStopResult(Ucs_StdResult_t result, void *user_ptr)
662 {
663     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
664     result = result; /*TODO: check error case*/
665     assert(MAGIC == my->magic);
666     my->initialized = false;
667     OnCommandExecuted(my, UnicensCmd_Stop);
668     UCSI_CB_OnStop(my->tag);
669 }
670
671 static void OnUcsMgrReport(Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr, void *user_ptr)
672 {
673     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
674     assert(MAGIC == my->magic);
675     if (node_ptr && node_ptr->script_list_ptr && node_ptr->script_list_size)
676     {
677         UnicensCmdEntry_t e;
678         e.cmd = UnicensCmd_NsRun;
679         e.val.NsRun.node_ptr = node_ptr;
680         EnqueueCommand(my, &e);
681     }
682     switch (code)
683     {
684     case UCS_MGR_REP_IGNORED_UNKNOWN:
685         UCSI_CB_OnUserMessage(my->tag, false, "Node=%X: Ignored, because unknown", 1, node_address);
686         break;
687     case UCS_MGR_REP_IGNORED_DUPLICATE:
688         UCSI_CB_OnUserMessage(my->tag, true, "Node=%X: Ignored, because duplicated", 1, node_address);
689         break;
690     case UCS_MGR_REP_AVAILABLE:
691         UCSI_CB_OnUserMessage(my->tag, false, "Node=%X: Available", 1, node_address);
692         break;
693     case UCS_MGR_REP_NOT_AVAILABLE:
694         UCSI_CB_OnUserMessage(my->tag, false, "Node=%X: Not available", 1, node_address);
695         break;
696     default:
697         UCSI_CB_OnUserMessage(my->tag, true, "Node=%X: unknown code", 1, node_address);
698         break;
699     }
700 }
701
702 static void OnUcsNsRun(Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCode_t result, void *ucs_user_ptr)
703 {
704     UCSI_Data_t *my;
705 #ifndef DEBUG_XRM
706     node_ptr = node_ptr;
707     result = result;
708     ucs_user_ptr;
709 #else
710     my = (UCSI_Data_t *)ucs_user_ptr;
711     assert(MAGIC == my->magic);
712     UCSI_CB_OnUserMessage(my->tag, false, "OnUcsNsRun (%03X): script executed %s",
713         2, node_ptr->signature_ptr->node_address,
714         (UCS_NS_RES_SUCCESS == result ? "succeeded" : "false"));
715 #endif
716 }
717
718 static void OnUcsAmsRxMsgReceived(void *user_ptr)
719 {
720     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
721     assert(MAGIC == my->magic);
722     UCSI_CB_OnAmsMessageReceived(my->tag);
723 }
724
725 /*----------------------------------------
726  * Debug Message output from Unicens stack:
727  *----------------------------------------
728  */
729 #if defined(UCS_TR_ERROR) || defined(UCS_TR_INFO)
730 #include <stdio.h>
731 #define TRACE_BUFFER_SZ 200
732 void App_TraceError(void *ucs_user_ptr, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
733 {
734     va_list argptr;
735     char outbuf[TRACE_BUFFER_SZ];
736     void *tag;
737     UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
738     if (my)
739     {
740         assert(MAGIC == my->magic);
741         tag = my->tag;
742     }
743     va_start(argptr, vargs_cnt);
744     vsprintf(outbuf, entry_str, argptr);
745     va_end(argptr);
746     UCSI_CB_OnUserMessage(tag, true, "Error | %s | %s", 2, module_str, outbuf);
747 }
748
749 void App_TraceInfo(void *ucs_user_ptr, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
750 {
751     va_list argptr;
752     char outbuf[TRACE_BUFFER_SZ];
753     void *tag;
754     UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
755     if (my)
756     {
757         assert(MAGIC == my->magic);
758         tag = my->tag;
759     }
760     va_start(argptr, vargs_cnt);
761     vsprintf(outbuf, entry_str, argptr);
762     va_end(argptr);
763     UCSI_CB_OnUserMessage(tag, false, "Info | %s | %s", 2, module_str, outbuf);
764 }
765 #endif