adds async. result to i2c_write
[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 OnUcsGpioPortCreate(uint16_t node_address, uint16_t gpio_port_handle, Ucs_Gpio_Result_t result, void *user_ptr);
68 static void OnUcsGpioPortWrite(uint16_t node_address, uint16_t gpio_port_handle, uint16_t current_state, uint16_t sticky_state, Ucs_Gpio_Result_t result, void *user_ptr);
69 static void OnUcsMgrReport(Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr, void *user_ptr);
70 static void OnUcsNsRun(Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCode_t result, void *ucs_user_ptr);
71 static void OnUcsAmsRxMsgReceived(void *user_ptr);
72 static void OnUcsGpioTriggerEventStatus(uint16_t node_address, uint16_t gpio_port_handle,
73     uint16_t rising_edges, uint16_t falling_edges, uint16_t levels, void * user_ptr);
74 static void OnUcsI2CWrite(uint16_t node_address, uint16_t i2c_port_handle,
75     uint8_t i2c_slave_address, uint8_t data_len, Ucs_I2c_Result_t result, void *user_ptr);
76
77 /************************************************************************/
78 /* Public Function Implementations                                      */
79 /************************************************************************/
80
81 void UCSI_Init(UCSI_Data_t *my, void *pTag)
82 {
83     Ucs_Return_t result;
84     assert(NULL != my);
85     memset(my, 0, sizeof(UCSI_Data_t));
86     my->magic = MAGIC;
87     my->tag = pTag;
88     my->unicens = Ucs_CreateInstance();
89     if (NULL == my->unicens)
90     {
91         UCSI_CB_OnUserMessage(my->tag, true, "Can not instance a new version of UNICENS, "\
92             "increase UCS_NUM_INSTANCES define", 0);
93         assert(false);
94         return;
95     }
96     result = Ucs_SetDefaultConfig(&my->uniInitData);
97     if(UCS_RET_SUCCESS != result)
98     {
99         UCSI_CB_OnUserMessage(my->tag, true, "Can not set default values to Unicens config (result=0x%X)", 1, result);
100         assert(false);
101         return;
102     }
103     my->uniInitData.user_ptr = my;
104     my->uniInitData.mgr.report_fptr = OnUcsMgrReport;
105
106     my->uniInitData.general.inic_watchdog_enabled = ENABLE_INIC_WATCHDOG;
107     my->uniInitData.general.get_tick_count_fptr = &OnUnicensGetTime;
108     my->uniInitData.general.request_service_fptr = &OnUnicensService;
109     my->uniInitData.general.error_fptr = &OnUnicensError;
110     my->uniInitData.general.set_application_timer_fptr = &OnUnicensAppTimer;
111     my->uniInitData.general.debug_error_msg_fptr = &OnUnicensDebugErrorMsg;
112     my->uniInitData.ams.enabled = ENABLE_AMS_LIB;
113     my->uniInitData.ams.rx.message_received_fptr = &OnUcsAmsRxMsgReceived;
114
115     my->uniInitData.lld.lld_user_ptr = my;
116     my->uniInitData.lld.start_fptr =  &OnLldCtrlStart;
117     my->uniInitData.lld.stop_fptr = &OnLldCtrlStop;
118     my->uniInitData.lld.rx_available_fptr = &OnLldCtrlRxMsgAvailable;
119     my->uniInitData.lld.tx_transmit_fptr = &OnLldCtrlTxTransmitC;
120
121     my->uniInitData.rm.report_fptr = &OnUnicensRoutingResult;
122     my->uniInitData.rm.xrm.most_port_status_fptr = &OnUnicensMostPortStatus;
123     my->uniInitData.rm.debug_resource_status_fptr = &OnUnicensDebugXrmResources;
124
125     my->uniInitData.gpio.trigger_event_status_fptr = &OnUcsGpioTriggerEventStatus;
126
127     RB_Init(&my->rb, CMD_QUEUE_LEN, sizeof(UnicensCmdEntry_t), my->rbBuf);
128 }
129
130 bool UCSI_NewConfig(UCSI_Data_t *my, UcsXmlVal_t *ucsConfig) {
131
132     UnicensCmdEntry_t *e;
133     assert(MAGIC == my->magic);
134     if (my->initialized)
135     {
136         e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
137         if (NULL == e) return false;
138         e->cmd = UnicensCmd_Stop;
139         RB_PopWritePtr(&my->rb);
140     }
141     my->uniInitData.mgr.packet_bw = ucsConfig->packetBw;
142     my->uniInitData.mgr.routes_list_ptr = ucsConfig->pRoutes;
143     my->uniInitData.mgr.routes_list_size = ucsConfig->routesSize;
144     my->uniInitData.mgr.nodes_list_ptr = ucsConfig->pNod;
145     my->uniInitData.mgr.nodes_list_size = ucsConfig->nodSize;
146     my->uniInitData.mgr.enabled = true;
147     e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
148     if (NULL == e) return false;
149     e->cmd =  UnicensCmd_Init;
150     e->val.Init.init_ptr = &my->uniInitData;
151     RB_PopWritePtr(&my->rb);
152     UCSI_CB_OnServiceRequired(my->tag);
153     return true;
154 }
155
156 bool UCSI_ProcessRxData(UCSI_Data_t *my,
157     const uint8_t *pBuffer, uint16_t len)
158 {
159     Ucs_Lld_RxMsg_t *msg = NULL;
160     assert(MAGIC == my->magic);
161     if (NULL == my->uniLld || NULL == my->uniLldHPtr) return false;
162     msg = my->uniLld->rx_allocate_fptr(my->uniLldHPtr, len);
163     if (NULL == msg)
164     {
165         /*This may happen by definition, OnLldCtrlRxMsgAvailable()
166           will be called, once buffers are available again*/
167         return false;
168     }
169     msg->data_size = len;
170     memcpy(msg->data_ptr, pBuffer, len);
171     my->uniLld->rx_receive_fptr(my->uniLldHPtr, msg);
172     return true;
173 }
174
175 void UCSI_Service(UCSI_Data_t *my)
176 {
177     UnicensCmdEntry_t *e;
178     bool popEntry = true; /*Set to false in specific case, where function will callback asynchrony.*/
179     assert(MAGIC == my->magic);
180     if (NULL != my->unicens && my->triggerService) {
181         my->triggerService = false;
182         Ucs_Service(my->unicens);
183     }
184     if (NULL != my->currentCmd) return;
185     my->currentCmd = e = (UnicensCmdEntry_t *)RB_GetReadPtr(&my->rb);
186     if (NULL == e) return;
187     switch (e->cmd) {
188         case UnicensCmd_Init:
189             if (UCS_RET_SUCCESS == Ucs_Init(my->unicens, e->val.Init.init_ptr, OnUcsInitResult))
190                 popEntry = false;
191             else
192                 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Init failed", 0);
193             break;
194         case UnicensCmd_Stop:
195             if (UCS_RET_SUCCESS == Ucs_Stop(my->unicens, OnUcsStopResult))
196                 popEntry = false;
197             else
198                 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Stop failed", 0);
199             break;
200         case UnicensCmd_RmSetRoute:
201             if (UCS_RET_SUCCESS != Ucs_Rm_SetRouteActive(my->unicens, e->val.RmSetRoute.routePtr, e->val.RmSetRoute.isActive))
202                 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Rm_SetRouteActive failed", 0);
203             break;
204         case UnicensCmd_NsRun:
205             if (UCS_RET_SUCCESS != Ucs_Ns_Run(my->unicens, e->val.NsRun.node_ptr, OnUcsNsRun))
206                 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Ns_Run failed", 0);
207             break;
208         case UnicensCmd_GpioCreatePort:
209             if (UCS_RET_SUCCESS == Ucs_Gpio_CreatePort(my->unicens, e->val.GpioCreatePort.destination, 0, e->val.GpioCreatePort.debounceTime, OnUcsGpioPortCreate))
210                 popEntry = false;
211             else
212                 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Gpio_CreatePort failed", 0);
213             break;
214         case UnicensCmd_GpioWritePort:
215             if (UCS_RET_SUCCESS == Ucs_Gpio_WritePort(my->unicens, e->val.GpioWritePort.destination, 0x1D00, e->val.GpioWritePort.mask, e->val.GpioWritePort.data, OnUcsGpioPortWrite))
216                 popEntry = false;
217             else
218                 UCSI_CB_OnUserMessage(my->tag, true, "UnicensCmd_GpioWritePort failed", 0);
219             break;
220         case UnicensCmd_I2CWrite:
221             if (UCS_RET_SUCCESS == Ucs_I2c_WritePort(my->unicens, e->val.I2CWrite.destination, 0x0F00, 
222                 (e->val.I2CWrite.isBurst ? UCS_I2C_BURST_MODE : UCS_I2C_DEFAULT_MODE), e->val.I2CWrite.blockCount,
223                 e->val.I2CWrite.slaveAddr, e->val.I2CWrite.timeout, e->val.I2CWrite.dataLen, e->val.I2CWrite.data, OnUcsI2CWrite))
224                 popEntry = false;
225             else {
226                 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_I2c_WritePort failed", 0);
227                 assert(e->val.I2CWrite.result_fptr != NULL);
228                 e->val.I2CWrite.result_fptr(NULL /*processing error*/, e->val.I2CWrite.request_ptr);
229             }
230             break;
231         default:
232             assert(false);
233             break;
234     }
235     if (popEntry)
236     {
237         my->currentCmd = NULL;
238         RB_PopReadPtr(&my->rb);
239     }
240 }
241
242 void UCSI_Timeout(UCSI_Data_t *my)
243 {
244     assert(MAGIC == my->magic);
245     if (NULL == my->unicens) return;
246     Ucs_ReportTimeout(my->unicens);
247 }
248
249 bool UCSI_SendAmsMessage(UCSI_Data_t *my, uint16_t msgId, uint16_t targetAddress, uint8_t *pPayload, uint32_t payloadLen)
250 {
251     Ucs_AmsTx_Msg_t *msg;
252     Ucs_Return_t result;
253     assert(MAGIC == my->magic);
254     if (NULL == my->unicens) return false;
255     msg = Ucs_AmsTx_AllocMsg(my->unicens, payloadLen);
256     if (NULL == msg) return false;
257     if (0 != payloadLen)
258     {
259         assert(NULL != msg->data_ptr);
260         memcpy(msg->data_ptr, pPayload, payloadLen);
261     }
262     msg->custom_info_ptr = NULL;
263     msg->data_size = payloadLen;
264     msg->destination_address = targetAddress;
265     msg->llrbc = 10;
266     msg->msg_id = msgId;
267     result = Ucs_AmsTx_SendMsg(my->unicens, msg, NULL);
268     if (UCS_RET_SUCCESS != result)
269         Ucs_AmsTx_FreeUnusedMsg(my->unicens, msg);
270     return UCS_RET_SUCCESS == result;
271 }
272
273 bool UCSI_GetAmsMessage(UCSI_Data_t *my, uint16_t *pMsgId, uint16_t *pSourceAddress, uint8_t **pPayload, uint32_t *pPayloadLen)
274 {
275     Ucs_AmsRx_Msg_t *msg;
276     assert(MAGIC == my->magic);
277     if (NULL == my->unicens || NULL == pPayload || NULL == pPayloadLen) return false;
278     msg = Ucs_AmsRx_PeekMsg(my->unicens);
279     if (NULL == msg) return false;
280     *pMsgId = msg->msg_id;
281     *pSourceAddress = msg->source_address;
282     *pPayload = msg->data_ptr;
283     *pPayloadLen = msg->data_size;
284     return true;
285 }
286
287 void UCSI_ReleaseAmsMessage(UCSI_Data_t *my)
288 {
289     assert(MAGIC == my->magic);
290     if (NULL == my->unicens) return;
291     Ucs_AmsRx_ReleaseMsg(my->unicens);
292 }
293
294 bool UCSI_SetRouteActive(UCSI_Data_t *my, uint16_t routeId, bool isActive)
295 {
296     uint16_t i;
297     UnicensCmdEntry_t entry;
298     assert(MAGIC == my->magic);
299     if (NULL == my || NULL == my->uniInitData.mgr.routes_list_ptr) return false;
300     for (i = 0; i < my->uniInitData.mgr.routes_list_size; i++)
301     {
302         Ucs_Rm_Route_t *route = &my->uniInitData.mgr.routes_list_ptr[i];
303         if (route->route_id != routeId)
304             continue;
305         entry.cmd = UnicensCmd_RmSetRoute;
306         entry.val.RmSetRoute.routePtr = route;
307         entry.val.RmSetRoute.isActive = isActive;
308         return EnqueueCommand(my, &entry);
309     }
310     return false;
311 }
312
313 bool UCSI_I2CWrite(UCSI_Data_t *my, uint16_t targetAddress, bool isBurst, uint8_t blockCount,
314     uint8_t slaveAddr, uint16_t timeout, uint8_t dataLen, uint8_t *pData, 
315     Ucsi_ResultCb_t result_fptr, void *request_ptr)
316 {
317     UnicensCmdEntry_t entry;
318     assert(MAGIC == my->magic);
319     if (NULL == my || NULL == pData || 0 == dataLen) return false;
320     if (dataLen > I2C_WRITE_MAX_LEN) return false;
321     entry.cmd = UnicensCmd_I2CWrite;
322     entry.val.I2CWrite.destination = targetAddress;
323     entry.val.I2CWrite.isBurst = isBurst;
324     entry.val.I2CWrite.blockCount = blockCount;
325     entry.val.I2CWrite.slaveAddr = slaveAddr;
326     entry.val.I2CWrite.timeout = timeout;
327     entry.val.I2CWrite.dataLen = dataLen;
328     entry.val.I2CWrite.result_fptr = result_fptr;
329     entry.val.I2CWrite.request_ptr = request_ptr;
330     memcpy(entry.val.I2CWrite.data, pData, dataLen);
331     return EnqueueCommand(my, &entry);
332 }
333
334 bool UCSI_SetGpioState(UCSI_Data_t *my, uint16_t targetAddress, uint8_t gpioPinId, bool isHighState)
335 {
336     uint16_t mask;
337     UnicensCmdEntry_t entry;
338     assert(MAGIC == my->magic);
339     if (NULL == my) return false;
340     mask = 1 << gpioPinId;
341     entry.cmd = UnicensCmd_GpioWritePort;
342     entry.val.GpioWritePort.destination = targetAddress;
343     entry.val.GpioWritePort.mask = mask;
344     entry.val.GpioWritePort.data = isHighState ? mask : 0;
345     return EnqueueCommand(my, &entry);
346 }
347
348 /************************************************************************/
349 /* Private Functions                                                    */
350 /************************************************************************/
351 static bool EnqueueCommand(UCSI_Data_t *my, UnicensCmdEntry_t *cmd)
352 {
353     UnicensCmdEntry_t *e;
354     if (NULL == my || NULL == cmd)
355     {
356         assert(false);
357         return false;
358     }
359     e = RB_GetWritePtr(&my->rb);
360     if (NULL == e)
361     {
362         UCSI_CB_OnUserMessage(my->tag, true, "Could not enqueue command. Increase CMD_QUEUE_LEN define", 0);
363         return false;
364     }
365     memcpy(e, cmd, sizeof(UnicensCmdEntry_t));
366     RB_PopWritePtr(&my->rb);
367     UCSI_CB_OnServiceRequired(my->tag);
368     return true;
369 }
370
371 static void OnCommandExecuted(UCSI_Data_t *my, UnicensCmd_t cmd)
372 {
373     if (NULL == my)
374     {
375         assert(false);
376         return;
377     }
378     if (NULL == my->currentCmd)
379     {
380         UCSI_CB_OnUserMessage(my->tag, true, "OnUniCommandExecuted was called, but no "\
381             "command is in queue", 0);
382         assert(false);
383         return;
384     }
385     if (my->currentCmd->cmd != cmd)
386     {
387         UCSI_CB_OnUserMessage(my->tag, true, "OnUniCommandExecuted was called with "\
388             "wrong command (Expected=0x%X, Got=0x%X", 2, my->currentCmd->cmd, cmd);
389         assert(false);
390         return;
391     }
392     my->currentCmd = NULL;
393     RB_PopReadPtr(&my->rb);
394 }
395
396 static void RB_Init(RB_t *rb, uint16_t amountOfEntries, uint32_t sizeOfEntry, uint8_t *workingBuffer)
397 {
398     assert(NULL != rb);
399     assert(NULL != workingBuffer);
400     rb->dataQueue = workingBuffer;
401     rb->pRx = rb->dataQueue;
402     rb->pTx = rb->dataQueue;
403     rb->amountOfEntries = amountOfEntries;
404     rb->sizeOfEntry = sizeOfEntry;
405     rb->rxPos = 0;
406     rb->txPos = 0;
407 }
408
409 static void *RB_GetReadPtr(RB_t *rb)
410 {
411     assert(NULL != rb);
412     assert(0 != rb->dataQueue);
413     if (rb->txPos - rb->rxPos > 0)
414     return (void *)rb->pRx;
415     return NULL;
416 }
417
418 static void RB_PopReadPtr(RB_t *rb)
419 {
420     assert(NULL != rb);
421     assert(0 != rb->dataQueue);
422
423     rb->pRx += rb->sizeOfEntry;
424     if (rb->pRx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
425     rb->pRx = rb->dataQueue;
426     ++rb->rxPos;
427     assert(rb->txPos >= rb->rxPos);
428 }
429
430 static void *RB_GetWritePtr(RB_t *rb)
431 {
432     assert(NULL != rb);
433     assert(0 != rb->dataQueue);
434     if (rb->txPos - rb->rxPos < rb->amountOfEntries)
435     return (void *)rb->pTx;
436     return NULL;
437 }
438
439 static void RB_PopWritePtr(RB_t *rb)
440 {
441     assert(NULL != rb);
442     assert(0 != rb->dataQueue);
443     rb->pTx += rb->sizeOfEntry;
444     if (rb->pTx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
445     rb->pTx = rb->dataQueue;
446     ++rb->txPos;
447     assert(rb->txPos >= rb->rxPos);
448 }
449
450 static uint16_t OnUnicensGetTime(void *user_ptr)
451 {
452     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
453     assert(MAGIC == my->magic);
454     return UCSI_CB_OnGetTime(my->tag);
455 }
456
457 static void OnUnicensService( void *user_ptr )
458 {
459     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
460     assert(MAGIC == my->magic);
461     my->triggerService = true;
462     UCSI_CB_OnServiceRequired(my->tag);
463 }
464
465 static void OnUnicensError( Ucs_Error_t error_code, void *user_ptr )
466 {
467     UnicensCmdEntry_t e;
468     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
469     error_code = error_code;
470     assert(MAGIC == my->magic);
471     UCSI_CB_OnUserMessage(my->tag, true, "Unicens general error, code=0x%X, restarting", 1, error_code);
472     e.cmd = UnicensCmd_Init;
473     e.val.Init.init_ptr = &my->uniInitData;
474     EnqueueCommand(my, &e);
475 }
476
477 static void OnUnicensAppTimer( uint16_t timeout, void *user_ptr )
478 {
479     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
480     assert(MAGIC == my->magic);
481     UCSI_CB_OnSetServiceTimer(my->tag, timeout);
482 }
483
484 static void OnUnicensDebugErrorMsg(Msg_MostTel_t *m, void *user_ptr)
485 {
486     char buffer[100];
487     char val[5];
488     uint8_t i;
489     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
490     assert(MAGIC == my->magic);
491     buffer[0] = '\0';
492     for (i = 0; NULL != m->tel.tel_data_ptr && i < m->tel.tel_len; i++)
493     {
494         snprintf(val, sizeof(val), "%02X ", m->tel.tel_data_ptr[i]);
495         strcat(buffer, val);
496     }
497     UCSI_CB_OnUserMessage(my->tag, true, "Received error message, source=%x, %X.%X.%X.%X, [ %s ]",
498         6, m->source_addr, m->id.fblock_id, m->id.instance_id,
499         m->id.function_id, m->id.op_type, buffer);
500 }
501
502 static void OnLldCtrlStart( Ucs_Lld_Api_t* api_ptr, void *inst_ptr, void *lld_user_ptr )
503 {
504     UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
505     assert(MAGIC == my->magic);
506     my->uniLld = api_ptr;
507     my->uniLldHPtr = inst_ptr;
508 }
509
510 static void OnLldCtrlStop( void *lld_user_ptr )
511 {
512     UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
513     assert(MAGIC == my->magic);
514     my->uniLld = NULL;
515     my->uniLldHPtr = NULL;
516 }
517
518 static void OnLldCtrlRxMsgAvailable( void *lld_user_ptr )
519 {
520     UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
521     assert(MAGIC == my->magic);
522     UCSI_CB_OnServiceRequired(my->tag);
523 }
524
525 static void OnLldCtrlTxTransmitC( Ucs_Lld_TxMsg_t *msg_ptr, void *lld_user_ptr )
526 {
527     UCSI_Data_t *my;
528     Ucs_Mem_Buffer_t * buf_ptr;
529     uint8_t buffer[BOARD_PMS_TX_SIZE];
530     uint32_t bufferPos = 0;
531     my = (UCSI_Data_t *)lld_user_ptr;
532     assert(MAGIC == my->magic);
533     if (NULL == msg_ptr || NULL == my || NULL == my->uniLld || NULL == my->uniLldHPtr)
534     {
535         assert(false);
536         return;
537     }
538     for (buf_ptr = msg_ptr->memory_ptr; buf_ptr != NULL; buf_ptr = buf_ptr->next_buffer_ptr)
539     {
540         if (buf_ptr->data_size + bufferPos > sizeof(buffer))
541         {
542             UCSI_CB_OnUserMessage(my->tag, true, "TX buffer is too small, increase " \
543                 "BOARD_PMS_TX_SIZE define (%lu > %lu)", 2, buf_ptr->data_size + bufferPos, sizeof(buffer));
544             my->uniLld->tx_release_fptr(my->uniLldHPtr, msg_ptr);
545             return;
546         }
547         memcpy(&buffer[bufferPos], buf_ptr->data_ptr, buf_ptr->data_size);
548         bufferPos += buf_ptr->data_size;
549     }
550     assert(bufferPos == msg_ptr->memory_ptr->total_size);
551     my->uniLld->tx_release_fptr(my->uniLldHPtr, msg_ptr);
552     UCSI_CB_OnTxRequest(my->tag, buffer, bufferPos);
553 }
554
555 static void OnUnicensRoutingResult(Ucs_Rm_Route_t* route_ptr, Ucs_Rm_RouteInfos_t route_infos, void *user_ptr)
556 {
557     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
558     assert(MAGIC == my->magic);
559     UCSI_CB_OnRouteResult(my->tag, route_ptr->route_id, UCS_RM_ROUTE_INFOS_BUILT == route_infos);
560 }
561
562 static void OnUnicensMostPortStatus(uint16_t most_port_handle,
563     Ucs_Most_PortAvail_t availability, Ucs_Most_PortAvailInfo_t avail_info,
564     uint16_t free_streaming_bw, void* user_ptr)
565 {
566     /*TODO: implement*/
567     most_port_handle = most_port_handle;
568     availability = availability;
569     avail_info = avail_info;
570     free_streaming_bw = free_streaming_bw;
571     user_ptr = user_ptr;
572 }
573
574 static void OnUnicensDebugXrmResources(Ucs_Xrm_ResourceType_t resource_type,
575     Ucs_Xrm_ResObject_t *resource_ptr, Ucs_Xrm_ResourceInfos_t resource_infos,
576     Ucs_Rm_EndPoint_t *endpoint_inst_ptr, void *user_ptr)
577 {
578     char *msg = NULL;
579     UCSI_Data_t *my;
580     uint16_t adr = 0xFFFF;
581 #ifndef DEBUG_XRM
582     resource_type = resource_type;
583     resource_ptr = resource_ptr;
584     resource_infos = resource_infos;
585     endpoint_inst_ptr = endpoint_inst_ptr;
586     user_ptr = user_ptr;
587 #else
588     endpoint_inst_ptr = endpoint_inst_ptr;
589     my = (UCSI_Data_t *)user_ptr;
590     assert(MAGIC == my->magic);
591     if (NULL == resource_ptr) return;
592     if (endpoint_inst_ptr && endpoint_inst_ptr->node_obj_ptr &&
593             endpoint_inst_ptr->node_obj_ptr->signature_ptr)
594         adr = endpoint_inst_ptr->node_obj_ptr->signature_ptr->node_address;
595     switch (resource_infos)
596     {
597         case UCS_XRM_INFOS_BUILT:
598         msg = (char *)"has been built";
599         break;
600         case UCS_XRM_INFOS_DESTROYED:
601         msg = (char *)"has been destroyed";
602         break;
603         case UCS_XRM_INFOS_ERR_BUILT:
604         msg = (char *)"cannot be built";
605         break;
606         default:
607         msg = (char *)"cannot be destroyed";
608         break;
609     }
610     switch(resource_type)
611     {
612         case UCS_XRM_RC_TYPE_MOST_SOCKET:
613         {
614             Ucs_Xrm_MostSocket_t *ms = (Ucs_Xrm_MostSocket_t *)resource_ptr;
615             assert(ms->resource_type == resource_type);
616             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): MOST socket %s, handle=%04X, "\
617                 "direction=%d, type=%d, bandwidth=%d", 6, adr, msg, ms->most_port_handle,
618                 ms->direction, ms->data_type, ms->bandwidth);
619             break;
620         }
621         case UCS_XRM_RC_TYPE_MLB_PORT:
622         {
623             Ucs_Xrm_MlbPort_t *m = (Ucs_Xrm_MlbPort_t *)resource_ptr;
624             assert(m->resource_type == resource_type);
625             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): MLB port %s, index=%d, clock=%d", 4,
626                 adr, msg, m->index, m->clock_config);
627             break;
628         }
629         case UCS_XRM_RC_TYPE_MLB_SOCKET:
630         {
631             Ucs_Xrm_MlbSocket_t *m = (Ucs_Xrm_MlbSocket_t *)resource_ptr;
632             assert(m->resource_type == resource_type);
633             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): MLB socket %s, direction=%d, type=%d,"\
634                 " bandwidth=%d, channel=%d", 6, adr, msg, m->direction, m->data_type,
635                 m->bandwidth, m->channel_address);
636             break;
637         }
638         case UCS_XRM_RC_TYPE_USB_PORT:
639         {
640             Ucs_Xrm_UsbPort_t *m = (Ucs_Xrm_UsbPort_t *)resource_ptr;
641             assert(m->resource_type == resource_type);
642             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): USB port %s, in-cnt=%d, out-cnt=%d", 4,
643                 adr, msg, m->streaming_if_ep_in_count, m->streaming_if_ep_out_count);
644             break;
645         }
646         case UCS_XRM_RC_TYPE_USB_SOCKET:
647         {
648             Ucs_Xrm_UsbSocket_t *m = (Ucs_Xrm_UsbSocket_t *)resource_ptr;
649             assert(m->resource_type == resource_type);
650             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): USB socket %s, direction=%d, type=%d," \
651                 " ep-addr=%02X, frames=%d", 6, adr, msg, m->direction, m->data_type,
652                 m->end_point_addr, m->frames_per_transfer);
653             break;
654         }
655         case UCS_XRM_RC_TYPE_STRM_PORT:
656         {
657             Ucs_Xrm_StrmPort_t *m = (Ucs_Xrm_StrmPort_t *)resource_ptr;
658             assert(m->resource_type == resource_type);
659             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): I2S port %s, index=%d, clock=%d, "\
660                 "align=%d", 5, adr, msg, m->index, m->clock_config, m->data_alignment);
661             break;
662         }
663         case UCS_XRM_RC_TYPE_STRM_SOCKET:
664         {
665             Ucs_Xrm_StrmSocket_t *m = (Ucs_Xrm_StrmSocket_t *)resource_ptr;
666             assert(m->resource_type == resource_type);
667             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): I2S socket %s, direction=%d, type=%d"\
668                 ", bandwidth=%d, pin=%d", 6, adr, msg, m->direction, m->data_type,
669                 m->bandwidth, m->stream_pin_id);
670             break;
671         }
672         case UCS_XRM_RC_TYPE_SYNC_CON:
673         {
674             Ucs_Xrm_SyncCon_t *m = (Ucs_Xrm_SyncCon_t *)resource_ptr;
675             assert(m->resource_type == resource_type);
676             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Sync connection %s, mute=%d, "\
677                 "offset=%d", 4, adr, msg, m->mute_mode, m->offset);
678             break;
679         }
680         case UCS_XRM_RC_TYPE_COMBINER:
681         {
682             Ucs_Xrm_Combiner_t *m = (Ucs_Xrm_Combiner_t *)resource_ptr;
683             assert(m->resource_type == resource_type);
684             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Combiner %s, bytes per frame=%d",
685                 3, adr, msg, m->bytes_per_frame);
686             break;
687         }
688         case UCS_XRM_RC_TYPE_SPLITTER:
689         {
690             Ucs_Xrm_Splitter_t *m = (Ucs_Xrm_Splitter_t *)resource_ptr;
691             assert(m->resource_type == resource_type);
692             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Splitter %s, bytes per frame=%d",
693                 3, adr, msg, m->bytes_per_frame);
694             break;
695         }
696         case UCS_XRM_RC_TYPE_AVP_CON:
697         {
698             Ucs_Xrm_AvpCon_t *m = (Ucs_Xrm_AvpCon_t *)resource_ptr;
699             assert(m->resource_type == resource_type);
700             UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Isoc-AVP connection %s, packetSize=%d",
701                 3, adr, msg, m->isoc_packet_size);
702             break;
703         }
704         default:
705         UCSI_CB_OnUserMessage(my->tag, true, "Xrm-Debug (0x%03X): Unknown type=%d %s", 3 , adr, resource_type, msg);
706     }
707 #endif
708 }
709
710 static void OnUcsInitResult(Ucs_InitResult_t result, void *user_ptr)
711 {
712     UnicensCmdEntry_t e;
713     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
714     assert(MAGIC == my->magic);
715     my->initialized = (UCS_INIT_RES_SUCCESS == result);
716     OnCommandExecuted(my, UnicensCmd_Init);
717     if (!my->initialized)
718     {
719         UCSI_CB_OnUserMessage(my->tag, true, "UcsInitResult reported error (0x%X), restarting...", 1, result);
720         e.cmd = UnicensCmd_Init;
721         e.val.Init.init_ptr = &my->uniInitData;
722         EnqueueCommand(my, &e);
723     }
724 }
725
726 static void OnUcsStopResult(Ucs_StdResult_t result, void *user_ptr)
727 {
728     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
729     result = result; /*TODO: check error case*/
730     assert(MAGIC == my->magic);
731     my->initialized = false;
732     OnCommandExecuted(my, UnicensCmd_Stop);
733     UCSI_CB_OnStop(my->tag);
734 }
735
736 static void OnUcsGpioPortCreate(uint16_t node_address, uint16_t gpio_port_handle, Ucs_Gpio_Result_t result, void *user_ptr)
737 {
738     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
739     assert(MAGIC == my->magic);
740     OnCommandExecuted(my, UnicensCmd_GpioCreatePort);
741 }
742
743 static void OnUcsGpioPortWrite(uint16_t node_address, uint16_t gpio_port_handle, uint16_t current_state, uint16_t sticky_state, Ucs_Gpio_Result_t result, void *user_ptr)
744 {
745     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
746     assert(MAGIC == my->magic);
747     OnCommandExecuted(my, UnicensCmd_GpioWritePort);
748 }
749
750 static void OnUcsMgrReport(Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr, void *user_ptr)
751 {
752     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
753     assert(MAGIC == my->magic);
754     switch (code)
755     {
756     case UCS_MGR_REP_IGNORED_UNKNOWN:
757         UCSI_CB_OnUserMessage(my->tag, false, "Node=%X: Ignored, because unknown", 1, node_address);
758         break;
759     case UCS_MGR_REP_IGNORED_DUPLICATE:
760         UCSI_CB_OnUserMessage(my->tag, true, "Node=%X: Ignored, because duplicated", 1, node_address);
761         break;
762     case UCS_MGR_REP_AVAILABLE:
763     {
764         UnicensCmdEntry_t e;
765         UCSI_CB_OnUserMessage(my->tag, false, "Node=%X: Available", 1, node_address);
766         /* Enable usage of remote GPIO ports */
767         e.cmd = UnicensCmd_GpioCreatePort;
768         e.val.GpioCreatePort.destination = node_address;
769         e.val.GpioCreatePort.debounceTime = 20;
770         EnqueueCommand(my, &e);
771         /* Execute scripts, if there are any */
772         if (node_ptr && node_ptr->script_list_ptr && node_ptr->script_list_size)
773         {
774             e.cmd = UnicensCmd_NsRun;
775             e.val.NsRun.node_ptr = node_ptr;
776             EnqueueCommand(my, &e);
777         }
778         break;
779     }
780     case UCS_MGR_REP_NOT_AVAILABLE:
781         UCSI_CB_OnUserMessage(my->tag, false, "Node=%X: Not available", 1, node_address);
782         break;
783     default:
784         UCSI_CB_OnUserMessage(my->tag, true, "Node=%X: unknown code", 1, node_address);
785         break;
786     }
787 }
788
789 static void OnUcsNsRun(Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCode_t result, void *ucs_user_ptr)
790 {
791     UCSI_Data_t *my;
792 #ifndef DEBUG_XRM
793     node_ptr = node_ptr;
794     result = result;
795     ucs_user_ptr;
796 #else
797     my = (UCSI_Data_t *)ucs_user_ptr;
798     assert(MAGIC == my->magic);
799     UCSI_CB_OnUserMessage(my->tag, false, "OnUcsNsRun (%03X): script executed %s",
800         2, node_ptr->signature_ptr->node_address,
801         (UCS_NS_RES_SUCCESS == result ? "succeeded" : "false"));
802 #endif
803 }
804
805 static void OnUcsAmsRxMsgReceived(void *user_ptr)
806 {
807     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
808     assert(MAGIC == my->magic);
809     UCSI_CB_OnAmsMessageReceived(my->tag);
810 }
811
812 static void OnUcsGpioTriggerEventStatus(uint16_t node_address, uint16_t gpio_port_handle,
813     uint16_t rising_edges, uint16_t falling_edges, uint16_t levels, void * user_ptr)
814 {
815     uint8_t i;
816     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
817     assert(MAGIC == my->magic);
818     for (i = 0; i < 16; i++)
819     {
820         if (0 != ((rising_edges >> i) & 0x1))
821             UCSI_CB_OnGpioStateChange(my->tag, node_address, i, true);
822         if (0 != ((falling_edges >> i) & 0x1))
823             UCSI_CB_OnGpioStateChange(my->tag, node_address, i, false);
824     }
825 }
826
827 static void OnUcsI2CWrite(uint16_t node_address, uint16_t i2c_port_handle,
828     uint8_t i2c_slave_address, uint8_t data_len, Ucs_I2c_Result_t result, void *user_ptr)
829 {
830     UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
831     assert(MAGIC == my->magic);
832     
833     if ((my->currentCmd->cmd == UnicensCmd_I2CWrite) 
834         && (my->currentCmd->val.I2CWrite.result_fptr)) {
835         
836         my->currentCmd->val.I2CWrite.result_fptr(&result.code, my->currentCmd->val.I2CWrite.request_ptr);
837     }
838     else {
839         assert(false);
840     }
841     
842     OnCommandExecuted(my, UnicensCmd_I2CWrite);
843     if (UCS_I2C_RES_SUCCESS != result.code)
844         UCSI_CB_OnUserMessage(my->tag, true, "Remote I2C Write to node=0x%X failed", 1, node_address);
845 }
846
847 /*----------------------------------------
848  * Debug Message output from Unicens stack:
849  *----------------------------------------
850  */
851 #if defined(UCS_TR_ERROR) || defined(UCS_TR_INFO)
852 #include <stdio.h>
853 #define TRACE_BUFFER_SZ 200
854 void App_TraceError(void *ucs_user_ptr, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
855 {
856     va_list argptr;
857     char outbuf[TRACE_BUFFER_SZ];
858     void *tag;
859     UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
860     if (my)
861     {
862         assert(MAGIC == my->magic);
863         tag = my->tag;
864     }
865     va_start(argptr, vargs_cnt);
866     vsprintf(outbuf, entry_str, argptr);
867     va_end(argptr);
868     UCSI_CB_OnUserMessage(tag, true, "Error | %s | %s", 2, module_str, outbuf);
869 }
870
871 void App_TraceInfo(void *ucs_user_ptr, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
872 {
873     va_list argptr;
874     char outbuf[TRACE_BUFFER_SZ];
875     void *tag;
876     UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
877     if (my)
878     {
879         assert(MAGIC == my->magic);
880         tag = my->tag;
881     }
882     va_start(argptr, vargs_cnt);
883     vsprintf(outbuf, entry_str, argptr);
884     va_end(argptr);
885     UCSI_CB_OnUserMessage(tag, false, "Info | %s | %s", 2, module_str, outbuf);
886 }
887 #endif