1 /***************************************************************************//**
2 * \file cybt_platform_freertos.c
3 *
4 * \brief
5 * Implementation for BT porting interface on FreeRTOS
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2019 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 *     http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24 
25 #include <string.h>
26 #include "cy_ipc_bt.h"
27 #include "cybt_platform_trace.h"
28 #include "cyabs_rtos.h"
29 #include "cybt_platform_task.h"
30 #include "cybt_platform_interface.h"
31 #include "cybt_platform_internal.h"
32 #include "cybt_platform_config.h"
33 #include "cybt_platform_util.h"
34 
35 /******************************************************************************
36  *                                Constants
37  ******************************************************************************/
38 #define NOT_IN_ISR              (false)
39 #define IN_ISR                  (true)
40 
41 /* MCU IPC interupt */
42 #define IPC1_INTERRUPT          (btss_interrupt_btss_ipc_IRQn)
43 #define IPC1_PRIORITY           (5u)      /* IPC1 interrupt priority */
44 
45 /* MCU IPC channel definition */
46 #define MCU_IPC_HCI_UL          (0)       /* For HCI  MCU -> BLE */
47 #define MCU_IPC_HCI_DL          (1)       /* For HCI  BLE -> MCU */
48 #define MCU_IPC_HPC_UL          (2)       /* For HPC  MCU -> BLE */
49 #define MCU_IPC_HPC_DL          (3)       /* For HPC  BLE -> MCU */
50 
51 /* Interrupt Structure definition */
52 #define IPC_INTR_BLE            (0)
53 #define IPC_INTR_MCU            (1)
54 
55 #define MAX_IPC_RETRIES         (20)
56 
57 #define RECORD_IPC_STATS
58 
59 /*****************************************************************************
60  *                           Type Definitions
61  *****************************************************************************/
62 typedef struct
63 {
64     bool            inited;
65     cy_semaphore_t  boot_fully_up;
66     /* Context for MCU IPC */
67     cy_stc_ipc_bt_context_t ipc_context;
68 } hci_interface_t;
69 
70 typedef uint16_t bt_task_event_t;
71 
72 #ifdef RECORD_IPC_STATS
73 typedef struct {
74     uint32_t get_buf_fail_count; /* Number of get buffer requests that failed. This does not count number of retries performed for same request.  */
75     uint32_t get_buf_max_retry_count; /* Maximum number of failed retries permormed for get buffer request. 0 <= MAX_IPC_RETRIES */
76     uint32_t write_fail_count; /* Number of write requests that failed. This does not count number of retries performed for same request.  */
77     uint32_t write_max_retry_count; /* Maximum number of failed retries permormed for write request. 0 <= MAX_IPC_RETRIES */
78 }cybt_ipc_stats_t;
79 #endif
80 
81 /******************************************************************************
82  *                           Callback Prototypes
83  ******************************************************************************/
84 cy_en_syspm_status_t cybt_platform_syspm_DeepSleepCallback(cy_stc_syspm_callback_params_t* callbackParams,
85                                                  cy_en_syspm_callback_mode_t mode);
86 
87 /******************************************************************************
88  *                           Variables Definitions
89  ******************************************************************************/
90 static hci_interface_t   hci_cb;
91 static bt_task_event_t timer_msg = BT_EVT_TIMEOUT;
92 static bt_task_event_t hci_core_msg = BT_EVT_CORE_HCI;
93 static bt_task_event_t hci_boot_msg = BT_EVT_TASK_BOOT_COMPLETES;
94 static bt_task_event_t shutdown_msg = BT_EVT_TASK_SHUTDOWN;
95 static bt_task_event_t buffer_msg = BT_EVT_CORE_HCI_WRITE_BUF_AVAIL;
96 static bt_task_event_t reset_msg = BT_EVT_TASK_RESET_COMPLETE;
97 
98 #ifdef RECORD_IPC_STATS
99 static cybt_ipc_stats_t ipc_stats;
100 #endif
101 
102 static cy_stc_syspm_callback_params_t cybt_syspm_callback_param = { NULL, NULL };
103 static cy_stc_syspm_callback_t        cybt_syspm_callback       =
104 {
105     .callback       = &cybt_platform_syspm_DeepSleepCallback,
106     .type           = (cy_en_syspm_callback_type_t) CY_SYSPM_MODE_DEEPSLEEP_RAM,
107     .callbackParams = &cybt_syspm_callback_param,
108     .order          = 253u,
109 };
110 
111 
112 /******************************************************************************
113  *                          Function Declarations
114  ******************************************************************************/
115 extern cybt_result_t cybt_platform_msg_to_bt_task(const uint16_t msg, bool is_from_isr);
116 extern void cybt_platform_exception_handler(cybt_exception_t error, uint8_t *info, uint32_t length);
117 
118 /******************************************************************************
119  *                           Function Definitions
120  ******************************************************************************/
reset_btss(void)121 static void reset_btss(void)
122 {
123     HCIDRV_TRACE_DEBUG("BTSS Reset\n");
124 
125     /* It will assert reset ( release group 3 IP ) */
126     (void)Cy_SysClk_PeriGroupSetSlaveCtl(3, CY_SYSCLK_PERI_GROUP_SL_CTL2, 0xFFFFFFFFU); /* Suppress a compiler warning about unused return value */
127 
128     /* It will de-assert reset ( release group 3 IP ) */
129     (void)Cy_SysClk_PeriGroupSetSlaveCtl(3, CY_SYSCLK_PERI_GROUP_SL_CTL2, 0x0U); /* Suppress a compiler warning about unused return value */
130 
131     HCIDRV_TRACE_DEBUG("BTSS Reset Complete\n");
132 }
133 
134 BTSTACK_PORTING_SECTION_BEGIN
notify_rx_not_empty(uint32_t * msg)135 static void notify_rx_not_empty(uint32_t * msg)
136 {
137     cybt_platform_msg_to_bt_task(BT_EVT_CORE_HCI, IN_ISR);
138     return;
139 }
140 BTSTACK_PORTING_SECTION_END
141 
notify_write_buffer_available(cy_en_btipc_buftype_t type)142 static void notify_write_buffer_available(cy_en_btipc_buftype_t type)
143 {
144     UNUSED_VARIABLE(type);
145     cybt_platform_msg_to_bt_task(BT_EVT_CORE_HCI_WRITE_BUF_AVAIL, IN_ISR);
146     return;
147 }
148 
149 /* IPC IRQ Handler for MCU */
150 BTSTACK_PORTING_SECTION_BEGIN
ipc_irq_handler_mcu(void)151 static void ipc_irq_handler_mcu(void)
152 {
153     CONTROLLER_SLEEP(LOCK); // before Cy_BTIPC_IRQ_Handler
154     Cy_BTIPC_IRQ_Handler(&hci_cb.ipc_context);
155     CONTROLLER_SLEEP(UNLOCK); // after Cy_BTIPC_IRQ_Handler
156 }
157 BTSTACK_PORTING_SECTION_END
158 
159 /* Release callback for MCU */
release_on_tx_done(void)160 static void release_on_tx_done(void)
161 {
162 
163 }
164 
165 #ifdef NOTIFY_IPC_PM
166 /* HPC Notify callback to MCU for power management */
notify_callback_mcu_pm(uint32_t * msg)167 static void notify_callback_mcu_pm(uint32_t * msg)
168 {
169     HCIDRV_TRACE_DEBUG("MCU: HPC Power Manager  0x%lx, 0x%lx\n",msg[0], msg[1]);
170     return;
171 }
172 #endif
173 
174 /* HPC Notify callback to MCU for boot type in init process */
notify_callback_mcu_longmsg(uint32_t * msg)175 static void notify_callback_mcu_longmsg(uint32_t * msg)
176 {
177     /* Don't add any prints in ISR Context. It may lead to crash */
178     uint8_t bootType = *(((uint8_t*)msg)+2);
179     switch(bootType)
180     {
181         case CY_BT_IPC_BOOT_CONFIG_WAIT:
182             cybt_platform_msg_to_bt_task(BT_EVT_TASK_BOOT_COMPLETES, IN_ISR);
183             break;
184         case CY_BT_IPC_BOOT_FULLY_UP:
185 #ifdef FPGA_TEST_PLATFORM
186             /* On FPGA, controller does not send CY_BT_IPC_BOOT_CONFIG_WAIT and directly sends CY_BT_IPC_BOOT_FULLY_UP */
187             cybt_platform_msg_to_bt_task(BT_EVT_TASK_BOOT_COMPLETES, IN_ISR);
188 #else
189             cy_rtos_set_semaphore(&hci_cb.boot_fully_up, IN_ISR);
190 #endif /* FPGA_TEST_PLATFORM */
191             break;
192         default:
193             break;
194     }
195     return;
196 }
197 
198 #ifdef NOTIFY_IPC_TRNG
199 /* HPC Notify callback to MCU for TRNG */
notify_callback_mcu_trng(uint32_t * msg)200 static void notify_callback_mcu_trng(uint32_t * msg)
201 {
202     HCIDRV_TRACE_DEBUG("MCU: HPC TRNG indication: 0x%lx, 0x%lx\n",msg[0], msg[1]);
203     return;
204 }
205 #endif
206 
207 BTSTACK_PORTING_SECTION_BEGIN
ipc_hci_release_buffer(uint32_t * p_msg)208 static cybt_result_t ipc_hci_release_buffer(uint32_t *p_msg)
209 {
210     uint32_t time_out = 2000UL; //2ms
211     cy_en_btipcdrv_status_t ipc_status;
212 
213     do
214     {
215         ipc_status = Cy_BTIPC_HCI_RelBuffer(&hci_cb.ipc_context, p_msg);
216 
217         if(CY_BT_IPC_DRV_SUCCESS == ipc_status)
218             return CYBT_SUCCESS;
219 
220         RELBUF_DELAY(); // default it will be dummy
221 
222         time_out--;
223     } while (time_out > 0);
224 
225     cybt_platform_exception_handler(CYBT_HCI_IPC_REL_BUFFER, (uint8_t *)&ipc_status, sizeof(ipc_status));
226 
227     /* App wants to continue on error, we can proceed */
228     return CYBT_ERR_HCI_IPC_REL_BUFFER_FAILED;
229 }
230 BTSTACK_PORTING_SECTION_END
231 
cybt_platform_hci_wait_for_boot_fully_up(bool is_from_isr)232 void cybt_platform_hci_wait_for_boot_fully_up(bool is_from_isr)
233 {
234     cy_rtos_get_semaphore(&hci_cb.boot_fully_up, CY_RTOS_NEVER_TIMEOUT, is_from_isr);
235 }
236 
237 BTSTACK_PORTING_SECTION_BEGIN
cybt_platform_hci_get_buffer(hci_packet_type_t pti,uint32_t size)238 uint8_t *cybt_platform_hci_get_buffer(hci_packet_type_t pti, uint32_t size)
239 {
240     static uint8_t short_msg[MAX_SHORT_MESG_LENGTH] = {0};
241     cy_en_btipcdrv_status_t ipc_status;
242     uint8_t *p_txbuffer = &short_msg[0];
243     cy_en_btipc_hcipti_t hci_pti = (cy_en_btipc_hcipti_t) pti;
244 
245     /* Sleep lock to get and access shared buffer.
246      * It will be unlocked in cybt_platform_hci_write() */
247     CONTROLLER_SLEEP(LOCK); // before get_ipc_write_buffer and ipc_write
248 
249     if ( (size > MAX_SHORT_MESG_LENGTH) || (hci_pti == CY_BT_IPC_HCI_ISO) || (hci_pti == CY_BT_IPC_HCI_ACL) )
250     {
251         int retries = 0;
252 
253         do
254         {
255             ipc_status = Cy_BTIPC_HCI_GetWriteBufPtr(&hci_cb.ipc_context, hci_pti, (void**)&p_txbuffer, size);
256 
257             if (CY_BT_IPC_DRV_SUCCESS != ipc_status)
258             {
259                 /* adding a delay before retrying */
260                 {
261                     volatile int delay = 1000;
262                     while(delay--);
263                 }
264                 //HCIDRV_TRACE_ERROR("MCU Error: IPC Get Buffer to BLE failed 0x%x!\n", ipc_status);
265 #ifdef RECORD_IPC_STATS
266                 if (!retries)
267                     ++ipc_stats.get_buf_fail_count;
268 
269                 if (retries > ipc_stats.get_buf_max_retry_count){
270                     ipc_stats.get_buf_max_retry_count = retries;
271                 }
272 #endif
273             }
274             else {
275                 return (p_txbuffer);
276             }
277         }while(++retries < MAX_IPC_RETRIES);
278 
279         /* Unlocking here since no buffer available */
280         CONTROLLER_SLEEP(UNLOCK); // if no ipc_write_buffer
281         return (NULL);
282     }
283     return (p_txbuffer);
284 }
285 BTSTACK_PORTING_SECTION_END
286 
cybt_platform_hci_post_stack_init(void)287 void cybt_platform_hci_post_stack_init(void)
288 {
289     Cy_BTIPC_Buffer_RegisterCb(&hci_cb.ipc_context, notify_write_buffer_available);
290 }
291 
292 BTSTACK_PORTING_SECTION_BEGIN
cybt_platform_msg_to_bt_task(const uint16_t msg,bool is_from_isr)293 cybt_result_t cybt_platform_msg_to_bt_task(const uint16_t msg, bool is_from_isr)
294 {
295     cybt_result_t result;
296     switch(msg)
297     {
298         case BT_EVT_TIMEOUT:
299             result = cybt_send_msg_to_bt_task(&timer_msg, is_from_isr);
300             break;
301         case BT_EVT_CORE_HCI:
302             result = cybt_send_msg_to_bt_task(&hci_core_msg, is_from_isr);
303             break;
304         case BT_EVT_TASK_BOOT_COMPLETES:
305             result = cybt_send_msg_to_bt_task(&hci_boot_msg, is_from_isr);
306             break;
307         case BT_EVT_TASK_SHUTDOWN:
308             result = cybt_send_msg_to_bt_task(&shutdown_msg, is_from_isr);
309             result = cybt_send_msg_to_bt_task(&reset_msg, is_from_isr);
310             break;
311         case BT_EVT_CORE_HCI_WRITE_BUF_AVAIL:
312             result = cybt_send_msg_to_bt_task(&buffer_msg, is_from_isr);
313             break;
314         default:
315             result = CYBT_ERR_BADARG;
316             break;
317     }
318     return (result);
319 }
320 BTSTACK_PORTING_SECTION_END
321 
cybt_platform_syspm_DeepSleepCallback(cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)322 cy_en_syspm_status_t cybt_platform_syspm_DeepSleepCallback(cy_stc_syspm_callback_params_t* callbackParams,
323                                                  cy_en_syspm_callback_mode_t mode)
324 {
325     cy_en_syspm_status_t retVal = CY_SYSPM_FAIL;
326 
327     CY_UNUSED_PARAMETER(callbackParams);
328 
329     switch (mode)
330     {
331         case CY_SYSPM_CHECK_READY:
332         {
333             retVal = CY_SYSPM_SUCCESS;
334             break;
335         }
336 
337         case CY_SYSPM_CHECK_FAIL:
338         {
339             retVal = CY_SYSPM_SUCCESS;
340             break;
341         }
342 
343         case CY_SYSPM_BEFORE_TRANSITION:
344         {
345             retVal = CY_SYSPM_SUCCESS;
346             break;
347         }
348 
349         case CY_SYSPM_AFTER_TRANSITION:
350         {
351             Cy_BTSS_PowerDep(true);
352             Cy_BTIPC_WarmInit(&hci_cb.ipc_context, (cy_stc_ipc_bt_config_t *) 0xFFFFFFFF);
353             Cy_BTSS_PowerDep(false);
354 
355             retVal = CY_SYSPM_SUCCESS;
356             break;
357         }
358 
359         default:
360             break;
361     }
362 
363     return retVal;
364 }
365 
cybt_platform_hci_open(void * p_arg)366 cybt_result_t cybt_platform_hci_open(void *p_arg)
367 {
368     cy_en_btipcdrv_status_t ipc_status;
369     uint32_t interruptState;
370 
371     /* MCU IPC Config */
372     cy_stc_ipc_bt_config_t btIpcHciConfig_mcu = {
373         .ulChannelHCI = MCU_IPC_HCI_UL, /* HCI Uplink channel from MCU to BLE */
374         .dlChannelHCI = MCU_IPC_HCI_DL, /* HCI Downlink channel from BLE to MCU */
375         .ulChannelHPC = MCU_IPC_HPC_UL, /* HPC Uplink channel from MCU to BLE */
376         .dlChannelHPC = MCU_IPC_HPC_DL, /* HPC Downlink channel from BLE to MCU */
377 
378         .intStuctureSelf = IPC_INTR_MCU, /* Interrupt Structure 1 is used for MCU */
379         .intStucturePeer = IPC_INTR_BLE, /* Interrupt Structure 0 is used for BLE */
380 
381         .ipcIntConfig.intrSrc = IPC1_INTERRUPT,
382         .ipcIntConfig.intrPriority = IPC1_PRIORITY,
383 
384         /* This handler will be removed later once simulations are done */
385         .irqHandlerPtr = ipc_irq_handler_mcu,
386         /* This callback will be removed later once simulations are done */
387         .internal_hpc_notify_cb = Cy_BTIPC_HPC_Notify,
388 
389         .ulReleaseCallbackPtr = release_on_tx_done,
390         .bufCallbackPtr  = NULL, // will register once host stack init is done
391     };
392 
393     UNUSED_VARIABLE(p_arg);
394 
395     if(true == hci_cb.inited)
396     {
397         return  CYBT_SUCCESS;
398     }
399 
400     /* host power domain: CY_PD_PDCM_MAIN (MAIN Power domain)
401      * destination power doamin: CY_PD_PDCM_BTSS (BTSS Power domain)
402      * cy_pd_pdcm_set_dependency() will create dependency settting of host on destination.
403      * which indirectly means host will not go into deep sleep until destination is running.*/
404     (void)cy_pd_pdcm_set_dependency(CY_PD_PDCM_MAIN, CY_PD_PDCM_BTSS); /* Suppress a compiler warning about unused return value */
405 
406     memset(&hci_cb, 0, sizeof(hci_interface_t));
407 
408     cy_rtos_init_semaphore(&hci_cb.boot_fully_up, 1, 0);
409 
410     interruptState = Cy_SysLib_EnterCriticalSection();
411     reset_btss();
412 
413     CONTROLLER_SLEEP(LOCK); // Cy_BTIPC_Init lock
414     ipc_status = Cy_BTIPC_Init(&hci_cb.ipc_context, &btIpcHciConfig_mcu);
415     CONTROLLER_SLEEP(UNLOCK); // Cy_BTIPC_Init unlock
416 
417     if (ipc_status)
418     {
419         HCIDRV_TRACE_ERROR("MCU Error: IPC HCI Init failed !\n");
420         CY_ASSERT(0);
421     }
422 
423     /* MCU Register HCI notify callback */
424     ipc_status = Cy_BTIPC_HCI_RegisterCb(&hci_cb.ipc_context, notify_rx_not_empty);
425     if (ipc_status)
426     {
427         HCIDRV_TRACE_ERROR("MCU Error: IPC HCI Notify Cb register failed 0x%x!\n", ipc_status);
428         CY_ASSERT(0);
429     }
430 
431     /* MCU Register HPC callback for power management */
432     {
433         cy_stc_ipc_hcp_cb_t notifyCallbackParam[] = {
434 #ifdef NOTIFY_IPC_PM
435             {.hpcNotifyCallbackPtr = notify_callback_mcu_pm, .msgType = CY_BT_IPC_HPC_PM},
436 #endif
437             {.hpcNotifyCallbackPtr = notify_callback_mcu_longmsg, .msgType = CY_BT_IPC_HPC_LONG},
438 #ifdef NOTIFY_IPC_TRNG
439             {.hpcNotifyCallbackPtr = notify_callback_mcu_trng, .msgType = CY_BT_IPC_HPC_REQTRNG},
440 #endif
441         };
442 
443         for (int i = 0; i < sizeof(notifyCallbackParam)/sizeof(notifyCallbackParam[0]); i++)
444         {
445             if(notifyCallbackParam[i].hpcNotifyCallbackPtr){
446             ipc_status = Cy_BTIPC_HPC_RegisterCb(&hci_cb.ipc_context, &notifyCallbackParam[i]);
447                 if (ipc_status)
448                 {
449                     HCIDRV_TRACE_ERROR("MCU Error: IPC register %d failed 0x%x!\n", i, ipc_status);
450                     CY_ASSERT(0);
451                 }
452             }
453         }
454     }
455 
456     Cy_SysLib_ExitCriticalSection(interruptState);
457 
458     if (!Cy_SysPm_RegisterCallback(&cybt_syspm_callback))
459     {
460     	HCIDRV_TRACE_ERROR("MCU Error: Syspm Callback registering failed 0x%x!\n", ipc_status);
461         CY_ASSERT(0);
462     }
463 
464     hci_cb.inited = true;
465 
466     HCIDRV_TRACE_DEBUG("hci_open(): Done");
467 
468     return  CYBT_SUCCESS;
469 }
470 
471 BTSTACK_PORTING_SECTION_BEGIN
cybt_platform_hci_write(hci_packet_type_t pti,uint8_t * p_data,uint32_t length)472 cybt_result_t cybt_platform_hci_write(hci_packet_type_t pti,
473                                       uint8_t *p_data,
474                                       uint32_t length
475                                       )
476 {
477     cybt_result_t status =  CYBT_SUCCESS;
478     cy_en_btipcdrv_status_t ipc_status;
479     int retries = 0;
480 
481     do
482     {
483         ipc_status = Cy_BTIPC_HCI_Write(&hci_cb.ipc_context, (cy_en_btipc_hcipti_t)pti, p_data, length);
484 
485         if (ipc_status)
486         {
487             /* adding a delay before retrying */
488             {
489                 volatile int delay = 1000;
490                 while(delay--);
491             }
492 
493             status = CYBT_ERR_HCI_WRITE_FAILED;
494 
495 #ifdef RECORD_IPC_STATS
496 			if (!retries)
497 				++ipc_stats.write_fail_count;
498 
499 			if (retries > ipc_stats.write_max_retry_count){
500 				ipc_stats.write_max_retry_count = retries;
501             }
502 #endif
503         }else{
504             status = CYBT_SUCCESS;
505             break;
506         }
507     }while(++retries < MAX_IPC_RETRIES);
508 
509     /* Sleep unlock which was already locked in cybt_platform_hci_get_buffer */
510     CONTROLLER_SLEEP(UNLOCK); // after get_ipc_write_buffer and ipc_write
511     return status;
512 }
513 BTSTACK_PORTING_SECTION_END
514 
515 BTSTACK_PORTING_SECTION_BEGIN
cybt_platfrom_hci_get_rx_fifo_count(void)516 uint16_t cybt_platfrom_hci_get_rx_fifo_count(void)
517 {
518     if(!hci_cb.inited)
519         return 0;
520     return (Cy_BTIPC_HCI_FIFOCount(&hci_cb.ipc_context));
521 }
522 BTSTACK_PORTING_SECTION_END
523 
524 BTSTACK_PORTING_SECTION_BEGIN
cybt_platform_hci_read(void * event,hci_packet_type_t * pti,uint8_t * p_data,uint32_t * p_length)525 cybt_result_t cybt_platform_hci_read(void *event,
526                                      hci_packet_type_t *pti,
527                                      uint8_t  *p_data,
528                                      uint32_t *p_length
529                                      )
530 {
531     cybt_result_t status =  CYBT_SUCCESS;
532     uint8_t *ptr_rx_hci = NULL;
533     uint32_t *p_msg = NULL;
534 
535     UNUSED_VARIABLE(event);
536 
537     if(!(hci_cb.inited && pti && p_data && p_length))
538     {
539         HCIDRV_TRACE_ERROR("hci_read(): UART is NOT initialized");
540         return  CYBT_ERR_HCI_NOT_INITIALIZE;
541     }
542 
543     CONTROLLER_SLEEP(LOCK); // before ipc_read
544 
545     /* cybt_platform_hci_read only be called when FIFO count is non-zero.
546      * And NULL check already handling in the beginning.
547      * Hence no need to check return values for below IPC API's */
548     Cy_BTIPC_HCI_FIFOGet(&hci_cb.ipc_context, &p_msg, 0);
549     Cy_BTIPC_HCI_getPTI ((cy_en_btipc_hcipti_t *)pti, p_length, p_msg);
550     Cy_BTIPC_HCI_GetReadBufPtr (&hci_cb.ipc_context, (void**)&ptr_rx_hci, (size_t*)p_length);
551 
552     memcpy((uint8_t*)p_data, ptr_rx_hci, *p_length);
553     status = ipc_hci_release_buffer(p_msg);
554 
555     CONTROLLER_SLEEP(UNLOCK); // after ipc_read
556 
557     return status;
558 }
559 BTSTACK_PORTING_SECTION_END
560 
cybt_platform_hci_close(void)561 cybt_result_t cybt_platform_hci_close(void)
562 {
563     cybt_result_t status = CYBT_SUCCESS;
564     if(false == hci_cb.inited)
565     {
566         HCIDRV_TRACE_ERROR("hci_close(): Not inited\n");
567         return  CYBT_ERR_HCI_NOT_INITIALIZE;
568     }
569 
570     if(CY_BT_IPC_DRV_SUCCESS != Cy_BTIPC_Deinit(&hci_cb.ipc_context))
571     {
572         HCIDRV_TRACE_ERROR("hci_close(): Cy_BTIPC_Deinit failed\n");
573         status = CYBT_ERR_HCI_IPC_DEINIT_FAILED;
574     }
575 
576     if (!Cy_SysPm_UnregisterCallback(&cybt_syspm_callback))
577     {
578         HCIDRV_TRACE_ERROR("MCU Error: Syspm Callback Unregistering failed!\n");
579         CY_ASSERT(0);
580     }
581 
582     memset(&hci_cb, 0, sizeof(hci_interface_t));
583 
584     return status;
585 }
586 
587 BTSTACK_PORTING_SECTION_BEGIN
cybt_platform_get_event_id(void * event)588 uint16_t cybt_platform_get_event_id(void *event)
589 {
590     bt_task_event_t *evt = (bt_task_event_t *)event;
591     return (*evt);
592 }
593 BTSTACK_PORTING_SECTION_END
594 
cybt_platform_hci_set_baudrate(uint32_t baudrate)595 cybt_result_t cybt_platform_hci_set_baudrate(uint32_t baudrate)
596 {
597     /* This function is not applicable if HCI communication is using IPC instead UART
598      * Only reason to keeping this function is to maintain compatibility
599      */
600 
601     UNUSED_VARIABLE(baudrate);
602     return  CYBT_SUCCESS;
603 }
604 
605 BTSTACK_PORTING_SECTION_BEGIN
cybt_platform_hci_process_if_coredump(uint8_t * p_data,uint32_t length)606 bool cybt_platform_hci_process_if_coredump(uint8_t *p_data, uint32_t length)
607 {
608     if (0xF4FF != *((uint16_t *)&p_data[0]))
609     {
610         /* Packet raw data will be like this
611          * fff41b03107907020000001800000004000081f0d80020000000000000000000
612          * 0xFFF4 opcode, 0x1B DBFW dump event subcode, 0x03 dumpp type, 0x10 length, 0x79 check sum */
613         return false;
614     }
615 
616     /* You may get multiple core dump packets don't assert here */
617     cybt_platform_exception_handler(CYBT_CONTROLLER_CORE_DUMP, p_data, length);
618     return true;
619 }
620 BTSTACK_PORTING_SECTION_END
621 
622 #ifdef RECORD_IPC_STATS
cybt_platform_hci_get_ipc_stats(cybt_ipc_stats_t * p_stats)623 cybt_result_t cybt_platform_hci_get_ipc_stats(cybt_ipc_stats_t *p_stats)
624 {
625 	p_stats->get_buf_fail_count = ipc_stats.get_buf_fail_count;
626 	p_stats->get_buf_max_retry_count = ipc_stats.get_buf_max_retry_count;
627 	p_stats->write_fail_count = ipc_stats.write_fail_count;
628 	p_stats->write_max_retry_count = ipc_stats.write_max_retry_count;
629 	return  CYBT_SUCCESS;
630 }
631 #endif
632