1 /*------------------------------------------------------------------------------------------------*/
2 /* UNICENS Integration Helper Component */
3 /* Copyright 2017, Microchip Technology Inc. and its subsidiaries. */
5 /* Redistribution and use in source and binary forms, with or without */
6 /* modification, are permitted provided that the following conditions are met: */
8 /* 1. Redistributions of source code must retain the above copyright notice, this */
9 /* list of conditions and the following disclaimer. */
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. */
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. */
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 /*------------------------------------------------------------------------------------------------*/
32 #include "ucs_interface.h"
34 /************************************************************************/
35 /* Private Definitions and variables */
36 /************************************************************************/
37 #define MAGIC (0xA144BEAF)
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 OnUnicensNetworkStatus(uint16_t change_mask, uint16_t events, Ucs_Network_Availability_t availability,
60 Ucs_Network_AvailInfo_t avail_info, Ucs_Network_AvailTransCause_t avail_trans_cause, uint16_t node_address,
61 uint8_t node_position, uint8_t max_position, uint16_t packet_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);
77 /************************************************************************/
78 /* Public Function Implementations */
79 /************************************************************************/
81 void UCSI_Init(UCSI_Data_t *my, void *pTag)
85 memset(my, 0, sizeof(UCSI_Data_t));
88 my->unicens = Ucs_CreateInstance();
89 if (NULL == my->unicens)
91 UCSI_CB_OnUserMessage(my->tag, true, "Can not instance a new version of UNICENS, "\
92 "increase UCS_NUM_INSTANCES define", 0);
96 result = Ucs_SetDefaultConfig(&my->uniInitData);
97 if(UCS_RET_SUCCESS != result)
99 UCSI_CB_OnUserMessage(my->tag, true, "Can not set default values to UNICENS config (result=0x%X)", 1, result);
103 my->uniInitData.user_ptr = my;
104 my->uniInitData.mgr.report_fptr = OnUcsMgrReport;
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 my->uniInitData.network.status.notification_mask = 0xC2;
115 my->uniInitData.network.status.cb_fptr = &OnUnicensNetworkStatus;
117 my->uniInitData.lld.lld_user_ptr = my;
118 my->uniInitData.lld.start_fptr = &OnLldCtrlStart;
119 my->uniInitData.lld.stop_fptr = &OnLldCtrlStop;
120 my->uniInitData.lld.rx_available_fptr = &OnLldCtrlRxMsgAvailable;
121 my->uniInitData.lld.tx_transmit_fptr = &OnLldCtrlTxTransmitC;
123 my->uniInitData.rm.report_fptr = &OnUnicensRoutingResult;
124 my->uniInitData.rm.debug_resource_status_fptr = &OnUnicensDebugXrmResources;
126 my->uniInitData.gpio.trigger_event_status_fptr = &OnUcsGpioTriggerEventStatus;
128 RB_Init(&my->rb, CMD_QUEUE_LEN, sizeof(UnicensCmdEntry_t), my->rbBuf);
131 bool UCSI_NewConfig(UCSI_Data_t *my, UcsXmlVal_t *ucsConfig) {
133 UnicensCmdEntry_t *e;
134 assert(MAGIC == my->magic);
137 e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
138 if (NULL == e) return false;
139 e->cmd = UnicensCmd_Stop;
140 RB_PopWritePtr(&my->rb);
142 my->uniInitData.mgr.packet_bw = ucsConfig->packetBw;
143 my->uniInitData.mgr.routes_list_ptr = ucsConfig->pRoutes;
144 my->uniInitData.mgr.routes_list_size = ucsConfig->routesSize;
145 my->uniInitData.mgr.nodes_list_ptr = ucsConfig->pNod;
146 my->uniInitData.mgr.nodes_list_size = ucsConfig->nodSize;
147 my->uniInitData.mgr.enabled = true;
148 e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
149 if (NULL == e) return false;
150 e->cmd = UnicensCmd_Init;
151 e->val.Init.init_ptr = &my->uniInitData;
152 RB_PopWritePtr(&my->rb);
153 UCSI_CB_OnServiceRequired(my->tag);
157 bool UCSI_ProcessRxData(UCSI_Data_t *my,
158 const uint8_t *pBuffer, uint16_t len)
160 Ucs_Lld_RxMsg_t *msg = NULL;
161 assert(MAGIC == my->magic);
162 if (NULL == my->uniLld || NULL == my->uniLldHPtr) return false;
163 msg = my->uniLld->rx_allocate_fptr(my->uniLldHPtr, len);
166 /*This may happen by definition, OnLldCtrlRxMsgAvailable()
167 will be called, once buffers are available again*/
170 msg->data_size = len;
171 memcpy(msg->data_ptr, pBuffer, len);
172 my->uniLld->rx_receive_fptr(my->uniLldHPtr, msg);
176 void UCSI_Service(UCSI_Data_t *my)
179 UnicensCmdEntry_t *e;
180 bool popEntry = true; /*Set to false in specific case, where function will callback asynchrony.*/
181 assert(MAGIC == my->magic);
182 if (NULL != my->unicens && my->triggerService) {
183 my->triggerService = false;
184 Ucs_Service(my->unicens);
186 if (NULL != my->currentCmd) return;
187 my->currentCmd = e = (UnicensCmdEntry_t *)RB_GetReadPtr(&my->rb);
188 if (NULL == e) return;
190 case UnicensCmd_Init:
191 if (UCS_RET_SUCCESS == Ucs_Init(my->unicens, e->val.Init.init_ptr, OnUcsInitResult))
194 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Init failed", 0);
196 case UnicensCmd_Stop:
197 if (UCS_RET_SUCCESS == Ucs_Stop(my->unicens, OnUcsStopResult))
200 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Stop failed", 0);
202 case UnicensCmd_RmSetRoute:
203 if (UCS_RET_SUCCESS != Ucs_Rm_SetRouteActive(my->unicens, e->val.RmSetRoute.routePtr, e->val.RmSetRoute.isActive))
204 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Rm_SetRouteActive failed", 0);
206 case UnicensCmd_NsRun:
207 if (UCS_RET_SUCCESS != Ucs_Ns_Run(my->unicens, e->val.NsRun.node_ptr, OnUcsNsRun))
208 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Ns_Run failed", 0);
210 case UnicensCmd_GpioCreatePort:
211 if (UCS_RET_SUCCESS == Ucs_Gpio_CreatePort(my->unicens, e->val.GpioCreatePort.destination, 0, e->val.GpioCreatePort.debounceTime, OnUcsGpioPortCreate))
214 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Gpio_CreatePort failed", 0);
216 case UnicensCmd_GpioWritePort:
217 if (UCS_RET_SUCCESS == Ucs_Gpio_WritePort(my->unicens, e->val.GpioWritePort.destination, 0x1D00, e->val.GpioWritePort.mask, e->val.GpioWritePort.data, OnUcsGpioPortWrite))
220 UCSI_CB_OnUserMessage(my->tag, true, "UnicensCmd_GpioWritePort failed", 0);
222 case UnicensCmd_I2CWrite:
223 ret = Ucs_I2c_WritePort(my->unicens, e->val.I2CWrite.destination, 0x0F00,
224 (e->val.I2CWrite.isBurst ? UCS_I2C_BURST_MODE : UCS_I2C_DEFAULT_MODE), e->val.I2CWrite.blockCount,
225 e->val.I2CWrite.slaveAddr, e->val.I2CWrite.timeout, e->val.I2CWrite.dataLen, e->val.I2CWrite.data, OnUcsI2CWrite);
226 if (UCS_RET_SUCCESS == ret)
229 UCSI_CB_OnUserMessage(my->tag, true, "Ucs_I2c_WritePort failed ret=%d", 1, ret);
230 assert(e->val.I2CWrite.result_fptr != NULL);
231 e->val.I2CWrite.result_fptr(NULL /*processing error*/, e->val.I2CWrite.request_ptr);
240 my->currentCmd = NULL;
241 RB_PopReadPtr(&my->rb);
245 void UCSI_Timeout(UCSI_Data_t *my)
247 assert(MAGIC == my->magic);
248 if (NULL == my->unicens) return;
249 Ucs_ReportTimeout(my->unicens);
252 bool UCSI_SendAmsMessage(UCSI_Data_t *my, uint16_t msgId, uint16_t targetAddress, uint8_t *pPayload, uint32_t payloadLen)
254 Ucs_AmsTx_Msg_t *msg;
256 assert(MAGIC == my->magic);
257 if (NULL == my->unicens) return false;
258 msg = Ucs_AmsTx_AllocMsg(my->unicens, payloadLen);
259 if (NULL == msg) return false;
262 assert(NULL != msg->data_ptr);
263 memcpy(msg->data_ptr, pPayload, payloadLen);
265 msg->custom_info_ptr = NULL;
266 msg->data_size = payloadLen;
267 msg->destination_address = targetAddress;
270 result = Ucs_AmsTx_SendMsg(my->unicens, msg, NULL);
271 if (UCS_RET_SUCCESS != result)
272 Ucs_AmsTx_FreeUnusedMsg(my->unicens, msg);
273 return UCS_RET_SUCCESS == result;
276 bool UCSI_GetAmsMessage(UCSI_Data_t *my, uint16_t *pMsgId, uint16_t *pSourceAddress, uint8_t **pPayload, uint32_t *pPayloadLen)
278 Ucs_AmsRx_Msg_t *msg;
279 assert(MAGIC == my->magic);
280 if (NULL == my->unicens || NULL == pPayload || NULL == pPayloadLen) return false;
281 msg = Ucs_AmsRx_PeekMsg(my->unicens);
282 if (NULL == msg) return false;
283 *pMsgId = msg->msg_id;
284 *pSourceAddress = msg->source_address;
285 *pPayload = msg->data_ptr;
286 *pPayloadLen = msg->data_size;
290 void UCSI_ReleaseAmsMessage(UCSI_Data_t *my)
292 assert(MAGIC == my->magic);
293 if (NULL == my->unicens) return;
294 Ucs_AmsRx_ReleaseMsg(my->unicens);
297 bool UCSI_SetRouteActive(UCSI_Data_t *my, uint16_t routeId, bool isActive)
300 UnicensCmdEntry_t entry;
301 assert(MAGIC == my->magic);
302 if (NULL == my || NULL == my->uniInitData.mgr.routes_list_ptr) return false;
303 for (i = 0; i < my->uniInitData.mgr.routes_list_size; i++)
305 Ucs_Rm_Route_t *route = &my->uniInitData.mgr.routes_list_ptr[i];
306 if (route->route_id != routeId)
308 entry.cmd = UnicensCmd_RmSetRoute;
309 entry.val.RmSetRoute.routePtr = route;
310 entry.val.RmSetRoute.isActive = isActive;
311 return EnqueueCommand(my, &entry);
316 bool UCSI_I2CWrite(UCSI_Data_t *my, uint16_t targetAddress, bool isBurst, uint8_t blockCount,
317 uint8_t slaveAddr, uint16_t timeout, uint8_t dataLen, uint8_t *pData,
318 Ucsi_ResultCb_t result_fptr, void *request_ptr)
320 UnicensCmdEntry_t entry;
321 assert(MAGIC == my->magic);
322 if (NULL == my || NULL == pData || 0 == dataLen) return false;
323 if (dataLen > I2C_WRITE_MAX_LEN) return false;
324 entry.cmd = UnicensCmd_I2CWrite;
325 entry.val.I2CWrite.destination = targetAddress;
326 entry.val.I2CWrite.isBurst = isBurst;
327 entry.val.I2CWrite.blockCount = blockCount;
328 entry.val.I2CWrite.slaveAddr = slaveAddr;
329 entry.val.I2CWrite.timeout = timeout;
330 entry.val.I2CWrite.dataLen = dataLen;
331 entry.val.I2CWrite.result_fptr = result_fptr;
332 entry.val.I2CWrite.request_ptr = request_ptr;
333 memcpy(entry.val.I2CWrite.data, pData, dataLen);
334 return EnqueueCommand(my, &entry);
337 bool UCSI_SetGpioState(UCSI_Data_t *my, uint16_t targetAddress, uint8_t gpioPinId, bool isHighState)
340 UnicensCmdEntry_t entry;
341 assert(MAGIC == my->magic);
342 if (NULL == my) return false;
343 mask = 1 << gpioPinId;
344 entry.cmd = UnicensCmd_GpioWritePort;
345 entry.val.GpioWritePort.destination = targetAddress;
346 entry.val.GpioWritePort.mask = mask;
347 entry.val.GpioWritePort.data = isHighState ? mask : 0;
348 return EnqueueCommand(my, &entry);
351 /************************************************************************/
352 /* Private Functions */
353 /************************************************************************/
354 static bool EnqueueCommand(UCSI_Data_t *my, UnicensCmdEntry_t *cmd)
356 UnicensCmdEntry_t *e;
357 if (NULL == my || NULL == cmd)
362 e = RB_GetWritePtr(&my->rb);
365 UCSI_CB_OnUserMessage(my->tag, true, "Could not enqueue command. Increase CMD_QUEUE_LEN define", 0);
368 memcpy(e, cmd, sizeof(UnicensCmdEntry_t));
369 RB_PopWritePtr(&my->rb);
370 UCSI_CB_OnServiceRequired(my->tag);
374 static void OnCommandExecuted(UCSI_Data_t *my, UnicensCmd_t cmd)
381 if (NULL == my->currentCmd)
383 UCSI_CB_OnUserMessage(my->tag, true, "OnUniCommandExecuted was called, but no "\
384 "command is in queue", 0);
388 if (my->currentCmd->cmd != cmd)
390 UCSI_CB_OnUserMessage(my->tag, true, "OnUniCommandExecuted was called with "\
391 "wrong command (Expected=0x%X, Got=0x%X", 2, my->currentCmd->cmd, cmd);
395 my->currentCmd = NULL;
396 RB_PopReadPtr(&my->rb);
399 static void RB_Init(RB_t *rb, uint16_t amountOfEntries, uint32_t sizeOfEntry, uint8_t *workingBuffer)
402 assert(NULL != workingBuffer);
403 rb->dataQueue = workingBuffer;
404 rb->pRx = rb->dataQueue;
405 rb->pTx = rb->dataQueue;
406 rb->amountOfEntries = amountOfEntries;
407 rb->sizeOfEntry = sizeOfEntry;
412 static void *RB_GetReadPtr(RB_t *rb)
415 assert(0 != rb->dataQueue);
416 if (rb->txPos - rb->rxPos > 0)
417 return (void *)rb->pRx;
421 static void RB_PopReadPtr(RB_t *rb)
424 assert(0 != rb->dataQueue);
426 rb->pRx += rb->sizeOfEntry;
427 if (rb->pRx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
428 rb->pRx = rb->dataQueue;
430 assert(rb->txPos >= rb->rxPos);
433 static void *RB_GetWritePtr(RB_t *rb)
436 assert(0 != rb->dataQueue);
437 if (rb->txPos - rb->rxPos < rb->amountOfEntries)
438 return (void *)rb->pTx;
442 static void RB_PopWritePtr(RB_t *rb)
445 assert(0 != rb->dataQueue);
446 rb->pTx += rb->sizeOfEntry;
447 if (rb->pTx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
448 rb->pTx = rb->dataQueue;
450 assert(rb->txPos >= rb->rxPos);
453 static uint16_t OnUnicensGetTime(void *user_ptr)
455 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
456 assert(MAGIC == my->magic);
457 return UCSI_CB_OnGetTime(my->tag);
460 static void OnUnicensService( void *user_ptr )
462 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
463 assert(MAGIC == my->magic);
464 my->triggerService = true;
465 UCSI_CB_OnServiceRequired(my->tag);
468 static void OnUnicensError( Ucs_Error_t error_code, void *user_ptr )
471 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
472 error_code = error_code;
473 assert(MAGIC == my->magic);
474 UCSI_CB_OnUserMessage(my->tag, true, "UNICENS general error, code=0x%X, restarting", 1, error_code);
475 e.cmd = UnicensCmd_Init;
476 e.val.Init.init_ptr = &my->uniInitData;
477 EnqueueCommand(my, &e);
480 static void OnUnicensAppTimer( uint16_t timeout, void *user_ptr )
482 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
483 assert(MAGIC == my->magic);
484 UCSI_CB_OnSetServiceTimer(my->tag, timeout);
487 static void OnUnicensDebugErrorMsg(Msg_MostTel_t *m, void *user_ptr)
492 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
493 assert(MAGIC == my->magic);
495 for (i = 0; NULL != m->tel.tel_data_ptr && i < m->tel.tel_len; i++)
497 snprintf(val, sizeof(val), "%02X ", m->tel.tel_data_ptr[i]);
500 UCSI_CB_OnUserMessage(my->tag, true, "Received error message, source=%x, %X.%X.%X.%X, [ %s ]",
501 6, m->source_addr, m->id.fblock_id, m->id.instance_id,
502 m->id.function_id, m->id.op_type, buffer);
505 static void OnLldCtrlStart( Ucs_Lld_Api_t* api_ptr, void *inst_ptr, void *lld_user_ptr )
507 UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
508 assert(MAGIC == my->magic);
509 my->uniLld = api_ptr;
510 my->uniLldHPtr = inst_ptr;
513 static void OnLldCtrlStop( void *lld_user_ptr )
515 UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
516 assert(MAGIC == my->magic);
518 my->uniLldHPtr = NULL;
521 static void OnLldCtrlRxMsgAvailable( void *lld_user_ptr )
523 UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
524 assert(MAGIC == my->magic);
525 UCSI_CB_OnServiceRequired(my->tag);
528 static void OnLldCtrlTxTransmitC( Ucs_Lld_TxMsg_t *msg_ptr, void *lld_user_ptr )
531 Ucs_Mem_Buffer_t * buf_ptr;
532 uint8_t buffer[BOARD_PMS_TX_SIZE];
533 uint32_t bufferPos = 0;
534 my = (UCSI_Data_t *)lld_user_ptr;
535 assert(MAGIC == my->magic);
536 if (NULL == msg_ptr || NULL == my || NULL == my->uniLld || NULL == my->uniLldHPtr)
541 for (buf_ptr = msg_ptr->memory_ptr; buf_ptr != NULL; buf_ptr = buf_ptr->next_buffer_ptr)
543 if (buf_ptr->data_size + bufferPos > sizeof(buffer))
545 UCSI_CB_OnUserMessage(my->tag, true, "TX buffer is too small, increase " \
546 "BOARD_PMS_TX_SIZE define (%lu > %lu)", 2, buf_ptr->data_size + bufferPos, sizeof(buffer));
547 my->uniLld->tx_release_fptr(my->uniLldHPtr, msg_ptr);
550 memcpy(&buffer[bufferPos], buf_ptr->data_ptr, buf_ptr->data_size);
551 bufferPos += buf_ptr->data_size;
553 assert(bufferPos == msg_ptr->memory_ptr->total_size);
554 my->uniLld->tx_release_fptr(my->uniLldHPtr, msg_ptr);
555 UCSI_CB_OnTxRequest(my->tag, buffer, bufferPos);
558 static void OnUnicensRoutingResult(Ucs_Rm_Route_t* route_ptr, Ucs_Rm_RouteInfos_t route_infos, void *user_ptr)
561 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
562 assert(MAGIC == my->magic);
563 conLabel = Ucs_Rm_GetConnectionLabel(my->unicens, route_ptr);
564 UCSI_CB_OnRouteResult(my->tag, route_ptr->route_id, UCS_RM_ROUTE_INFOS_BUILT == route_infos, conLabel);
567 static void OnUnicensNetworkStatus(uint16_t change_mask, uint16_t events, Ucs_Network_Availability_t availability,
568 Ucs_Network_AvailInfo_t avail_info, Ucs_Network_AvailTransCause_t avail_trans_cause, uint16_t node_address,
569 uint8_t node_position, uint8_t max_position, uint16_t packet_bw, void *user_ptr)
571 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
572 assert(MAGIC == my->magic);
573 UCSI_CB_OnNetworkState(my->tag, UCS_NW_AVAILABLE == availability, packet_bw, max_position);
576 static void OnUnicensDebugXrmResources(Ucs_Xrm_ResourceType_t resource_type,
577 Ucs_Xrm_ResObject_t *resource_ptr, Ucs_Xrm_ResourceInfos_t resource_infos,
578 Ucs_Rm_EndPoint_t *endpoint_inst_ptr, void *user_ptr)
582 uint16_t adr = 0xFFFF;
584 resource_type = resource_type;
585 resource_ptr = resource_ptr;
586 resource_infos = resource_infos;
587 endpoint_inst_ptr = endpoint_inst_ptr;
590 endpoint_inst_ptr = endpoint_inst_ptr;
591 my = (UCSI_Data_t *)user_ptr;
592 assert(MAGIC == my->magic);
593 if (NULL == resource_ptr) return;
594 if (endpoint_inst_ptr && endpoint_inst_ptr->node_obj_ptr &&
595 endpoint_inst_ptr->node_obj_ptr->signature_ptr)
596 adr = endpoint_inst_ptr->node_obj_ptr->signature_ptr->node_address;
597 switch (resource_infos)
599 case UCS_XRM_INFOS_BUILT:
600 msg = (char *)"has been built";
602 case UCS_XRM_INFOS_DESTROYED:
603 msg = (char *)"has been destroyed";
605 case UCS_XRM_INFOS_ERR_BUILT:
606 msg = (char *)"cannot be built";
609 msg = (char *)"cannot be destroyed";
612 switch(resource_type)
614 case UCS_XRM_RC_TYPE_MOST_SOCKET:
616 Ucs_Xrm_MostSocket_t *ms = (Ucs_Xrm_MostSocket_t *)resource_ptr;
617 assert(ms->resource_type == resource_type);
618 UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): MOST socket %s, handle=%04X, "\
619 "direction=%d, type=%d, bandwidth=%d", 6, adr, msg, ms->most_port_handle,
620 ms->direction, ms->data_type, ms->bandwidth);
623 case UCS_XRM_RC_TYPE_MLB_PORT:
625 Ucs_Xrm_MlbPort_t *m = (Ucs_Xrm_MlbPort_t *)resource_ptr;
626 assert(m->resource_type == resource_type);
627 UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): MLB port %s, index=%d, clock=%d", 4,
628 adr, msg, m->index, m->clock_config);
631 case UCS_XRM_RC_TYPE_MLB_SOCKET:
633 Ucs_Xrm_MlbSocket_t *m = (Ucs_Xrm_MlbSocket_t *)resource_ptr;
634 assert(m->resource_type == resource_type);
635 UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): MLB socket %s, direction=%d, type=%d,"\
636 " bandwidth=%d, channel=%d", 6, adr, msg, m->direction, m->data_type,
637 m->bandwidth, m->channel_address);
640 case UCS_XRM_RC_TYPE_USB_PORT:
642 Ucs_Xrm_UsbPort_t *m = (Ucs_Xrm_UsbPort_t *)resource_ptr;
643 assert(m->resource_type == resource_type);
644 UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): USB port %s, in-cnt=%d, out-cnt=%d", 4,
645 adr, msg, m->streaming_if_ep_in_count, m->streaming_if_ep_out_count);
648 case UCS_XRM_RC_TYPE_USB_SOCKET:
650 Ucs_Xrm_UsbSocket_t *m = (Ucs_Xrm_UsbSocket_t *)resource_ptr;
651 assert(m->resource_type == resource_type);
652 UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): USB socket %s, direction=%d, type=%d," \
653 " ep-addr=%02X, frames=%d", 6, adr, msg, m->direction, m->data_type,
654 m->end_point_addr, m->frames_per_transfer);
657 case UCS_XRM_RC_TYPE_STRM_PORT:
659 Ucs_Xrm_StrmPort_t *m = (Ucs_Xrm_StrmPort_t *)resource_ptr;
660 assert(m->resource_type == resource_type);
661 UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): I2S port %s, index=%d, clock=%d, "\
662 "align=%d", 5, adr, msg, m->index, m->clock_config, m->data_alignment);
665 case UCS_XRM_RC_TYPE_STRM_SOCKET:
667 Ucs_Xrm_StrmSocket_t *m = (Ucs_Xrm_StrmSocket_t *)resource_ptr;
668 assert(m->resource_type == resource_type);
669 UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): I2S socket %s, direction=%d, type=%d"\
670 ", bandwidth=%d, pin=%d", 6, adr, msg, m->direction, m->data_type,
671 m->bandwidth, m->stream_pin_id);
674 case UCS_XRM_RC_TYPE_SYNC_CON:
676 Ucs_Xrm_SyncCon_t *m = (Ucs_Xrm_SyncCon_t *)resource_ptr;
677 assert(m->resource_type == resource_type);
678 UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Sync connection %s, mute=%d, "\
679 "offset=%d", 4, adr, msg, m->mute_mode, m->offset);
682 case UCS_XRM_RC_TYPE_COMBINER:
684 Ucs_Xrm_Combiner_t *m = (Ucs_Xrm_Combiner_t *)resource_ptr;
685 assert(m->resource_type == resource_type);
686 UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Combiner %s, bytes per frame=%d",
687 3, adr, msg, m->bytes_per_frame);
690 case UCS_XRM_RC_TYPE_SPLITTER:
692 Ucs_Xrm_Splitter_t *m = (Ucs_Xrm_Splitter_t *)resource_ptr;
693 assert(m->resource_type == resource_type);
694 UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Splitter %s, bytes per frame=%d",
695 3, adr, msg, m->bytes_per_frame);
698 case UCS_XRM_RC_TYPE_AVP_CON:
700 Ucs_Xrm_AvpCon_t *m = (Ucs_Xrm_AvpCon_t *)resource_ptr;
701 assert(m->resource_type == resource_type);
702 UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Isoc-AVP connection %s, packetSize=%d",
703 3, adr, msg, m->isoc_packet_size);
707 UCSI_CB_OnUserMessage(my->tag, true, "Xrm-Debug (0x%03X): Unknown type=%d %s", 3 , adr, resource_type, msg);
712 static void OnUcsInitResult(Ucs_InitResult_t result, void *user_ptr)
715 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
716 assert(MAGIC == my->magic);
717 my->initialized = (UCS_INIT_RES_SUCCESS == result);
718 OnCommandExecuted(my, UnicensCmd_Init);
719 if (!my->initialized)
721 UCSI_CB_OnUserMessage(my->tag, true, "UcsInitResult reported error (0x%X), restarting...", 1, result);
722 e.cmd = UnicensCmd_Init;
723 e.val.Init.init_ptr = &my->uniInitData;
724 EnqueueCommand(my, &e);
728 static void OnUcsStopResult(Ucs_StdResult_t result, void *user_ptr)
730 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
731 result = result; /*TODO: check error case*/
732 assert(MAGIC == my->magic);
733 my->initialized = false;
734 OnCommandExecuted(my, UnicensCmd_Stop);
735 UCSI_CB_OnStop(my->tag);
738 static void OnUcsGpioPortCreate(uint16_t node_address, uint16_t gpio_port_handle, Ucs_Gpio_Result_t result, void *user_ptr)
740 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
741 assert(MAGIC == my->magic);
742 OnCommandExecuted(my, UnicensCmd_GpioCreatePort);
745 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)
747 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
748 assert(MAGIC == my->magic);
749 OnCommandExecuted(my, UnicensCmd_GpioWritePort);
752 static void OnUcsMgrReport(Ucs_MgrReport_t code, uint16_t node_address, Ucs_Rm_Node_t *node_ptr, void *user_ptr)
754 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
755 assert(MAGIC == my->magic);
758 case UCS_MGR_REP_IGNORED_UNKNOWN:
759 UCSI_CB_OnUserMessage(my->tag, false, "Node=%X: Ignored, because unknown", 1, node_address);
761 case UCS_MGR_REP_IGNORED_DUPLICATE:
762 UCSI_CB_OnUserMessage(my->tag, true, "Node=%X: Ignored, because duplicated", 1, node_address);
764 case UCS_MGR_REP_AVAILABLE:
767 UCSI_CB_OnUserMessage(my->tag, false, "Node=%X: Available", 1, node_address);
768 /* Enable usage of remote GPIO ports */
769 e.cmd = UnicensCmd_GpioCreatePort;
770 e.val.GpioCreatePort.destination = node_address;
771 e.val.GpioCreatePort.debounceTime = 20;
772 EnqueueCommand(my, &e);
773 /* Execute scripts, if there are any */
774 if (node_ptr && node_ptr->script_list_ptr && node_ptr->script_list_size)
776 e.cmd = UnicensCmd_NsRun;
777 e.val.NsRun.node_ptr = node_ptr;
778 EnqueueCommand(my, &e);
782 case UCS_MGR_REP_NOT_AVAILABLE:
783 UCSI_CB_OnUserMessage(my->tag, false, "Node=%X: Not available", 1, node_address);
786 UCSI_CB_OnUserMessage(my->tag, true, "Node=%X: unknown code", 1, node_address);
790 UCSI_CB_OnMgrReport(my->tag, code, node_address, node_ptr);
793 static void OnUcsNsRun(Ucs_Rm_Node_t * node_ptr, Ucs_Ns_ResultCode_t result, void *ucs_user_ptr)
801 my = (UCSI_Data_t *)ucs_user_ptr;
802 assert(MAGIC == my->magic);
803 UCSI_CB_OnUserMessage(my->tag, false, "OnUcsNsRun (%03X): script executed %s",
804 2, node_ptr->signature_ptr->node_address,
805 (UCS_NS_RES_SUCCESS == result ? "succeeded" : "false"));
809 static void OnUcsAmsRxMsgReceived(void *user_ptr)
811 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
812 assert(MAGIC == my->magic);
813 UCSI_CB_OnAmsMessageReceived(my->tag);
816 static void OnUcsGpioTriggerEventStatus(uint16_t node_address, uint16_t gpio_port_handle,
817 uint16_t rising_edges, uint16_t falling_edges, uint16_t levels, void * user_ptr)
820 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
821 assert(MAGIC == my->magic);
822 for (i = 0; i < 16; i++)
824 if (0 != ((rising_edges >> i) & 0x1))
825 UCSI_CB_OnGpioStateChange(my->tag, node_address, i, true);
826 if (0 != ((falling_edges >> i) & 0x1))
827 UCSI_CB_OnGpioStateChange(my->tag, node_address, i, false);
831 static void OnUcsI2CWrite(uint16_t node_address, uint16_t i2c_port_handle,
832 uint8_t i2c_slave_address, uint8_t data_len, Ucs_I2c_Result_t result, void *user_ptr)
834 UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
835 assert(MAGIC == my->magic);
837 if ((my->currentCmd->cmd == UnicensCmd_I2CWrite)
838 && (my->currentCmd->val.I2CWrite.result_fptr)) {
840 my->currentCmd->val.I2CWrite.result_fptr(&result.code, my->currentCmd->val.I2CWrite.request_ptr);
846 OnCommandExecuted(my, UnicensCmd_I2CWrite);
847 if (UCS_I2C_RES_SUCCESS != result.code)
848 UCSI_CB_OnUserMessage(my->tag, true, "Remote I2C Write to node=0x%X failed", 1, node_address);
851 /************************************************************************/
852 /* Debug Message output from UNICENS stack: */
853 /************************************************************************/
854 #if defined(UCS_TR_ERROR) || defined(UCS_TR_INFO)
856 #define TRACE_BUFFER_SZ 200
857 void App_TraceError(void *ucs_user_ptr, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
860 char outbuf[TRACE_BUFFER_SZ];
862 UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
865 assert(MAGIC == my->magic);
868 va_start(argptr, vargs_cnt);
869 vsprintf(outbuf, entry_str, argptr);
871 UCSI_CB_OnUserMessage(tag, true, "Error | %s | %s", 2, module_str, outbuf);
874 void App_TraceInfo(void *ucs_user_ptr, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
877 char outbuf[TRACE_BUFFER_SZ];
879 UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
882 assert(MAGIC == my->magic);
885 va_start(argptr, vargs_cnt);
886 vsprintf(outbuf, entry_str, argptr);
888 UCSI_CB_OnUserMessage(tag, false, "Info | %s | %s", 2, module_str, outbuf);