1 /***************************************************************************//**
2 * \file cy_ipc_bt.c
3 * \version 1.130
4 *
5 * \brief
6 *  This driver provides the source code for BT IPC.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright (c) (2020-2022), Cypress Semiconductor Corporation (an Infineon company) or
11 * an affiliate of Cypress Semiconductor Corporation.
12 * SPDX-License-Identifier: Apache-2.0
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 *     http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *******************************************************************************/
26 
27 #include "cy_device.h"
28 
29 #if defined (CY_IP_MXS40BLE52SS) && defined (CY_IP_MXIPC)
30 
31 #include "cy_ipc_bt.h"
32 #include "cy_syspm_btss.h"
33 
34 /* Should not include this. To be removed */
35 #include <string.h>
36 
37 #include <stdio.h>
38 
39 CY_MISRA_DEVIATE_BLOCK_START('ARRAY_VS_SINGLETON', 1, \
40 'Checked manually. Using pointer as an array will not corrupt or misinterpret adjacent memory locations.')
41 
42 //#define BTIPC_DBG_L0
43 //#define BTIPC_DBG_L1
44 //#define BTIPC_DBG_L2
45 //#define BTIPC_STATUS
46 
47 /** Buffer descriptor offset in the init message */
48 #ifndef BT_OLD_INIT
49 #define INIT_IPC_BUFF_DESC_OFFSET 5
50 #else
51 #define INIT_IPC_BUFF_DESC_OFFSET 1
52 #endif
53 
54 #ifdef BTIPC_DBG_L0
55 #define BTIPC_LOG_L0(...)   printf(__VA_ARGS__)
56 #else
57 #define BTIPC_LOG_L0(...)
58 #endif
59 
60 #ifdef BTIPC_DBG_L1
61 #define BTIPC_LOG_L1(...)   printf(__VA_ARGS__)
62 #else
63 #define BTIPC_LOG_L1(...)
64 #endif
65 
66 #ifdef BTIPC_DBG_L2
67 #define BTIPC_LOG_L2(...)   printf(__VA_ARGS__)
68 #else
69 #define BTIPC_LOG_L2(...)
70 #endif
71 
72 /* local functions prototype */
73 cy_en_btipcdrv_status_t Cy_bt_handle_hpclong_msg(cy_stc_ipc_bt_context_t *btIpcContext, uint32_t * msgPtr);
74 cy_en_btipcdrv_status_t Cy_bt_handle_buf_add(cy_stc_ipc_bt_context_t *btIpcContext, uint32_t * msgPtr);
75 cy_en_btipcdrv_status_t Cy_bt_handle_buf_remove(cy_stc_ipc_bt_context_t *btIpcContext, uint32_t * msgPtr);
76 static cy_en_btipc_buftype_t Cy_bt_get_buf_type(cy_en_btipc_hcipti_t pti);
77 static uint32_t Cy_bt_getPLLegnth(cy_en_btipc_hcipti_t pti, uint8_t* bufAddr);
78 static bool Cy_bt_isOffsetNeeded(cy_en_btipc_hcipti_t pti);
79 static cy_en_btipcdrv_status_t Cy_bt_GetBuffer (cy_stc_ipc_bt_context_t *btIpcContext, void **ppBuf, cy_en_btipc_buftype_t bufType, size_t length);
80 static cy_en_btipcdrv_status_t Cy_bt_PutBuffer(cy_stc_ipc_bt_context_t *btIpcContext, cy_stc_ipc_bt_buf_t *bufDecriptor);
81 static cy_en_btipcdrv_status_t Cy_BTIPC_HCI_FIFOPut(cy_stc_ipc_bt_context_t *btIpcContext, uint32_t *pMsg);
82 cy_en_btipcdrv_status_t Cy_BTIPC_HPC_RelBuffer(cy_stc_ipc_bt_context_t *btIpcContext, uint32_t* msgPtr);
83 
84 CY_IPC_SECTION_BEGIN
Cy_BTIPC_IRQ_Handler(cy_stc_ipc_bt_context_t * btIpcContext)85 void Cy_BTIPC_IRQ_Handler(cy_stc_ipc_bt_context_t *btIpcContext)
86 {
87     uint32_t shadowIntr;
88     IPC_STRUCT_Type *ipcPtr;
89     IPC_INTR_STRUCT_Type *ipcIntrPtr;
90     uint32_t mesg[2], backup[2];
91     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
92     uint32_t notify;
93     uint32_t release;
94     uint32_t channelHCI;
95     uint32_t channelHPC;
96     uint8_t idx;
97     cy_en_btipc_hpcpti_t msgType;
98 
99     if (NULL == contextPtr)
100     {
101         BTIPC_LOG_L0("Context ptr null\n");
102         return;
103     }
104 
105 #ifdef CY_BTIPC_STATS
106     contextPtr->ipc_int_count++;
107 #endif
108 
109     ipcIntrPtr = Cy_IPC_Drv_GetIntrBaseAddr(contextPtr->intStuctureSelf);
110     shadowIntr = Cy_IPC_Drv_GetInterruptStatusMasked(ipcIntrPtr);
111 
112     notify = Cy_IPC_Drv_ExtractAcquireMask(shadowIntr);
113 
114     /* Check to make sure the interrupt was a release interrupt */
115     release = Cy_IPC_Drv_ExtractReleaseMask(shadowIntr);
116 
117     BTIPC_LOG_L1("shadow 0x%lx, notifyMask 0x%lx, relMask 0x%lx\n", shadowIntr, notify, release);
118 
119     /* First process the release callback */
120     if (0UL != release)  /* Check for a Release interrupt */
121     {
122         BTIPC_LOG_L1("Release int\n");
123         /* Clear the release interrupt  */
124         Cy_IPC_Drv_ClearInterrupt(ipcIntrPtr, release, CY_IPC_NO_NOTIFICATION);
125 
126         if ((release & (uint32_t)(0x1UL << contextPtr->ulChannelHPC)) != 0UL)
127         {
128 #ifdef CY_BTIPC_STATS
129             contextPtr->ipc_hpc_release_count++;
130 #endif
131             (void)Cy_BTSS_PowerDep(false);
132         }
133         if ((release & (uint32_t)(0x1UL << contextPtr->ulChannelHCI)) != 0UL)
134         {
135 #ifdef CY_BTIPC_STATS
136             contextPtr->ipc_hci_release_count++;
137 #endif
138             (void)Cy_BTSS_PowerDep(false);
139         }
140 
141         /* release callback can be added here. */
142         if ((contextPtr->ulReleaseCallbackPtr) != NULL )
143         {
144             contextPtr->ulReleaseCallbackPtr();
145         }
146     }
147 
148     /* Check to make sure the interrupt was a notify interrupt */
149     if (0UL != notify)
150     {
151         BTIPC_LOG_L1("Notify int ");
152         /* Clear the notify interrupt.  */
153         Cy_IPC_Drv_ClearInterrupt(ipcIntrPtr, CY_IPC_NO_NOTIFICATION, notify);
154 
155         if ((notify & (uint32_t)(0x1UL << contextPtr->dlChannelHPC)) != 0UL)
156         {
157 #ifdef CY_BTIPC_STATS
158             contextPtr->ipc_hpc_notify_count++;
159             if (contextPtr->ipc_hci_fifo_full > 0UL)
160             {
161                 contextPtr->ipc_hci_notify_in_fifo_full++;
162             }
163 #endif
164             channelHPC = contextPtr->dlChannelHPC;
165 
166             BTIPC_LOG_L1("on ch %ld\n",channelHPC);
167 
168             ipcPtr = Cy_IPC_Drv_GetIpcBaseAddress(channelHPC);
169             Cy_IPC_Drv_ReadDDataValue(ipcPtr, mesg);
170             /* Keep back up of mesg needed to release the buffer */
171             backup[0] = mesg[0];
172             backup[1] = mesg[1];
173 
174             CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.8','Intentional typecast to cy_en_btipc_hpcpti_t enum.');
175             msgType = (cy_en_btipc_hpcpti_t)((0xFFUL) & mesg[0]);
176 
177             BTIPC_LOG_L1("HPC payload type %d\n",msgType);
178 
179             if ((contextPtr->internal_hpc_notify_cb) != NULL)
180             {
181                 BTIPC_LOG_L1("Notify HPC int cb+\n");
182                 contextPtr->internal_hpc_notify_cb((void*)contextPtr, mesg);
183                 BTIPC_LOG_L1("Notify HPC int cb-\n");
184             }
185             for (idx = 0; idx < ((uint8_t)MAX_BT_IPC_HPC_CB); idx++)
186             {
187                 BTIPC_LOG_L1("idx %d, Notify HPC cb %p, msgType %d\n",idx, contextPtr->hpcNotifyCallbackParam[idx].hpcNotifyCallbackPtr, contextPtr->hpcNotifyCallbackParam[idx].msgType);
188                 if ((contextPtr->hpcNotifyCallbackParam[idx].msgType == msgType) &&
189                     (contextPtr->hpcNotifyCallbackParam[idx].hpcNotifyCallbackPtr != NULL))
190                 {
191                    BTIPC_LOG_L1("Calling Notify HPC cb %p\n",contextPtr->hpcNotifyCallbackParam[idx].hpcNotifyCallbackPtr);
192                     if ((msgType == CY_BT_IPC_HPC_LONG) && (*(((uint8_t*)mesg)+1) == (uint8_t)CY_BT_IPC_HPC_INIT))
193                     {
194                         /* Add Boot type to the message add pass it to the application */
195                         *(((uint8_t*)mesg)+2) = contextPtr->bootType;
196                         /* Certificate error field, so that the app can process if needed */
197                         mesg[1] = contextPtr->certError;
198                     }
199                     contextPtr->hpcNotifyCallbackParam[idx].hpcNotifyCallbackPtr(mesg);
200                 }
201             }
202             /* Release channel for HPC message only */
203             (void)Cy_BTIPC_HPC_RelChannel(contextPtr, backup); /* Suppress a compiler warning about unused return value */
204 #ifdef CY_BTIPC_STATS
205             contextPtr->ipc_hpc_peer_release_count++;
206 #endif
207             if (0xFFUL == (0xFFUL & mesg[0]))
208             {
209 
210                     (void)Cy_BTIPC_HPC_RelBuffer(contextPtr, backup); /* Suppress a compiler warning about unused return value */
211 
212             }
213             /*At boot config wait BT FW does not process HPC release buffer and hence fails to release IPC channel.
214             Since we want to lock PDCM at IPC write and release only after BT does IPC CH release, we need a count reset
215             to avoid PDCM use count mismatch, which will prevent BT from doing a DS*/
216             if((cy_en_btipc_boottype_t)contextPtr->bootType == CY_BT_IPC_BOOT_FULLY_UP)
217             {
218                 Cy_BTSS_PowerDepResetCount();
219             }
220         }
221 
222         if ((notify & (uint32_t)(0x1UL << contextPtr->dlChannelHCI)) != 0UL)
223         {
224 #ifdef CY_BTIPC_STATS
225             contextPtr->ipc_hci_notify_count++;
226 #endif
227             channelHCI = contextPtr->dlChannelHCI;
228 
229             BTIPC_LOG_L1("on ch %ld\n",channelHCI);
230 
231             ipcPtr = Cy_IPC_Drv_GetIpcBaseAddress(channelHCI);
232             Cy_IPC_Drv_ReadDDataValue(ipcPtr, mesg);
233             /* Push the mesg to FIFO */
234             if (((uint32_t)Cy_BTIPC_HCI_FIFOPut(contextPtr, mesg)) == 0UL)
235             {
236                 if (((uint16_t)MAX_IPC_FIFO_SIZE) > Cy_BTIPC_HCI_FIFOCount(contextPtr))
237                 {
238                     /* Release channel for HCI message only if FIFO is not full */
239                     (void)Cy_BTIPC_HCI_RelChannel(contextPtr); /* Suppress a compiler warning about unused return value */
240 #ifdef CY_BTIPC_STATS
241                     contextPtr->ipc_hci_peer_release_count++;
242 #endif
243                 }
244                 else
245                 {
246                     contextPtr->ipc_hci_fifo_full++;
247                     BTIPC_LOG_L0("\nFIFO is Full. Ch 0x%lx not released !\n",channelHCI);
248                 }
249                 BTIPC_LOG_L1("FIFO count %d\n",contextPtr->IpcFifo.bufLen);
250 
251                 /* call the callback function */
252                 if ((contextPtr->dlNotifyCallbackPtr) != NULL)
253                 {
254 
255                     BTIPC_LOG_L1("Notify HCI cb\n");
256                     contextPtr->dlNotifyCallbackPtr(mesg);
257                 }
258             }
259             else
260             {
261                 BTIPC_LOG_L0("Error: Msg received after FIFO is full !\n");
262                 contextPtr->droppedHCI++;
263                 /* Add assert here */
264                 CY_ASSERT_L1(false);
265                 return;
266             }
267         }
268     }
269 }
270 CY_IPC_SECTION_END
271 
272 CY_IPC_SECTION_BEGIN
Cy_BTIPC_HCI_RelChannel(cy_stc_ipc_bt_context_t * btIpcContext)273 cy_en_btipcdrv_status_t Cy_BTIPC_HCI_RelChannel(cy_stc_ipc_bt_context_t *btIpcContext)
274 {
275     IPC_STRUCT_Type *ipcPtr;
276     uint32_t rel_mask;
277     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
278 
279     if (NULL == contextPtr)
280     {
281         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
282     }
283 
284     ipcPtr = Cy_IPC_Drv_GetIpcBaseAddress (contextPtr->dlChannelHCI);
285 
286     rel_mask = (uint32_t)(1UL << contextPtr->intStucturePeer);
287 
288     Cy_IPC_Drv_ReleaseNotify(ipcPtr, rel_mask);
289 
290     return CY_BT_IPC_DRV_SUCCESS;
291 }
292 CY_IPC_SECTION_END
293 
294 
Cy_BTIPC_HPC_RelChannel(cy_stc_ipc_bt_context_t * btIpcContext,void * buf)295 cy_en_btipcdrv_status_t Cy_BTIPC_HPC_RelChannel(cy_stc_ipc_bt_context_t *btIpcContext, void * buf)
296 {
297     IPC_STRUCT_Type *ipcPtr;
298     uint32_t rel_mask;
299     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
300     (void)buf;
301     // Fix if this is causing issue
302 #if 1
303     if ((NULL == contextPtr) || (NULL == buf))
304     {
305         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
306     }
307 #endif
308 
309     ipcPtr = Cy_IPC_Drv_GetIpcBaseAddress (contextPtr->dlChannelHPC);
310 
311     rel_mask = (uint32_t)(1UL << contextPtr->intStucturePeer);
312     BTIPC_LOG_L1("Release %p, mask 0x%lx\n", ipcPtr, rel_mask);
313     Cy_IPC_Drv_ReleaseNotify(ipcPtr, rel_mask);
314     BTIPC_LOG_L1("Release register 0x%lx\n", ipcPtr->RELEASE);
315     return CY_BT_IPC_DRV_SUCCESS;
316 }
317 
318 
Cy_BTIPC_HCI_RelBuffer(cy_stc_ipc_bt_context_t * btIpcContext,uint32_t * msgPtr)319 cy_en_btipcdrv_status_t Cy_BTIPC_HCI_RelBuffer(cy_stc_ipc_bt_context_t *btIpcContext, uint32_t* msgPtr)
320 {
321     cy_stc_ipc_msg_alloc_t ipcMsgAlloc;
322     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
323     uint8_t idx;
324     uint8_t found;
325     uint32_t interruptState;
326     uint32_t *pMsg;
327 
328     if ((NULL == contextPtr) || (NULL == msgPtr))
329     {
330         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
331     }
332 
333     if (((cy_stc_ipc_msg_buff_t*)((void*)msgPtr))->pti != ((uint8_t)CY_BT_IPC_HCI_LONG))
334     {
335         /* Remove the FIFO entry */
336         (void)Cy_BTIPC_HCI_FIFOGet(contextPtr, &pMsg, 1);
337         return CY_BT_IPC_DRV_SUCCESS;
338     }
339 
340     found = 0;
341 
342     interruptState = Cy_SysLib_EnterCriticalSection();
343 
344     /* If the channel is busy then do not proceed further, return CH BUSY error */
345     if (Cy_IPC_Drv_IsLockAcquired (Cy_IPC_Drv_GetIpcBaseAddress(contextPtr->ulChannelHPC)))
346     {
347         Cy_SysLib_ExitCriticalSection(interruptState);
348         return CY_BT_IPC_DRV_ERROR_CH_BUSY;
349     }
350 
351     for (idx = 0U; idx < ((uint8_t)MAX_TO_FREE_BUF_COUNT); idx++)
352     {
353         if (contextPtr->toFreeBuf[idx].bufPtr == (uint8_t*)msgPtr[1])
354         {
355             ipcMsgAlloc.pti = (uint8_t)CY_BT_IPC_HPC_BUFRELEASE;
356             ipcMsgAlloc.bufType = ((uint8_t)contextPtr->toFreeBuf[idx].bufType);
357             ipcMsgAlloc.bufSize = contextPtr->toFreeBuf[idx].bufLen;
358             ipcMsgAlloc.bufAddr = contextPtr->toFreeBuf[idx].bufPtr;
359             found = 1;
360             contextPtr->toFreeBuf[idx].bufType = CY_BT_IPC_HCI_INVALID_BUF;
361             contextPtr->toFreeBuf[idx].bufLen = 0;
362             contextPtr->toFreeBuf[idx].bufPtr = NULL;
363             break;
364         }
365     }
366 
367     Cy_SysLib_ExitCriticalSection(interruptState);
368 
369     /* Remove the FIFO entry */
370     (void)Cy_BTIPC_HCI_FIFOGet(contextPtr, &pMsg, 1);
371 
372     if (found != 0UL)
373     {
374 #ifdef CY_BTIPC_STATS
375         contextPtr->ipc_hci_peer_outbuf_count++;
376 #endif
377         return (Cy_BTIPC_HPC_Write(contextPtr, &ipcMsgAlloc, (size_t) 2));
378     }
379     else
380     {
381         return CY_BT_IPC_DRV_ERROR_BUF_GET;
382     }
383 }
384 
385 
Cy_BTIPC_HPC_RelBuffer(cy_stc_ipc_bt_context_t * btIpcContext,uint32_t * msgPtr)386 cy_en_btipcdrv_status_t Cy_BTIPC_HPC_RelBuffer(cy_stc_ipc_bt_context_t *btIpcContext, uint32_t* msgPtr)
387 {
388     cy_stc_ipc_msg_alloc_t ipcMsgAlloc;
389     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
390 
391     if ((NULL == contextPtr) || (NULL == msgPtr))
392     {
393         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
394     }
395 
396     BTIPC_LOG_L1("Releasing HPC buffer 0x%lx\n", msgPtr[1]);
397 #ifdef CY_BTIPC_STATS
398     contextPtr->ipc_hpc_peer_outbuf_count++;
399 #endif
400     ipcMsgAlloc.pti = (uint8_t)CY_BT_IPC_HPC_BUFRELEASE;
401     ipcMsgAlloc.bufType = 0;
402     ipcMsgAlloc.bufSize = 0;
403     ipcMsgAlloc.bufAddr = (uint8_t*)msgPtr[1];
404 
405     return (Cy_BTIPC_HPC_Write(contextPtr, &ipcMsgAlloc, (size_t) 2));
406 }
407 
408 
Cy_BTIPC_HPC_Notify(void * btIpcContext,uint32_t * msgPtr)409 void Cy_BTIPC_HPC_Notify(void *btIpcContext, uint32_t * msgPtr)
410 {
411     cy_en_btipc_hpcpti_t pti;
412     cy_stc_ipc_bt_context_t *contextPtr = (cy_stc_ipc_bt_context_t*) btIpcContext;
413     if ((NULL == contextPtr) || (NULL == msgPtr))
414     {
415         return;
416     }
417 
418     BTIPC_LOG_L1("Internal cb for HPC\n");
419 
420     CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.8','Intentional typecast to cy_en_btipc_hpcpti_t enum.');
421     pti = (cy_en_btipc_hpcpti_t)((0xFFUL) & msgPtr[0]);
422 
423     switch (pti)
424     {
425         case CY_BT_IPC_HPC_LONG:
426             (void)Cy_bt_handle_hpclong_msg(contextPtr, msgPtr);
427             break;
428         case CY_BT_IPC_HPC_BUFPROVIDE:
429             (void)Cy_bt_handle_buf_add(contextPtr, msgPtr);
430             break;
431         case CY_BT_IPC_HPC_BUFFER_REMOVE:
432             (void)Cy_bt_handle_buf_remove(contextPtr, msgPtr);
433             break;
434         default:
435             /* default invalid pti */
436             break;
437     }
438 }
439 
440 
Cy_BTIPC_Init(cy_stc_ipc_bt_context_t * btIpcContext,cy_stc_ipc_bt_config_t * btIpcConfig)441 cy_en_btipcdrv_status_t Cy_BTIPC_Init(cy_stc_ipc_bt_context_t *btIpcContext, cy_stc_ipc_bt_config_t *btIpcConfig)
442 {
443     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
444     cy_en_btipcdrv_status_t status;
445     uint8_t idx;
446 
447     if ((NULL == contextPtr) || (NULL == btIpcConfig))
448     {
449         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
450     }
451 
452     contextPtr->dlChannelHCI = btIpcConfig->dlChannelHCI;
453     contextPtr->ulChannelHCI = btIpcConfig->ulChannelHCI;
454 
455     contextPtr->dlChannelHPC = btIpcConfig->dlChannelHPC;
456     contextPtr->ulChannelHPC = btIpcConfig->ulChannelHPC;
457 
458     contextPtr->intStuctureSelf = btIpcConfig->intStuctureSelf;
459     contextPtr->intStucturePeer = btIpcConfig->intStucturePeer;
460     contextPtr->intPeerMask = (uint32_t) (0x1UL << btIpcConfig->intStucturePeer);
461 
462     contextPtr->dlNotifyCallbackPtr = NULL;
463     contextPtr->ulReleaseCallbackPtr = btIpcConfig->ulReleaseCallbackPtr;
464     contextPtr->bufCallbackPtr = btIpcConfig->bufCallbackPtr;
465 
466     contextPtr->irqHandlerPtr = btIpcConfig->irqHandlerPtr;
467     contextPtr->ipcIntConfig.intrSrc = btIpcConfig->ipcIntConfig.intrSrc;
468     contextPtr->ipcIntConfig.intrPriority = btIpcConfig->ipcIntConfig.intrPriority;
469 
470     contextPtr->internal_hpc_notify_cb = btIpcConfig->internal_hpc_notify_cb;
471 
472     contextPtr->dlNotifyMask = (uint32_t)((uint32_t)(0x1UL << btIpcConfig->dlChannelHCI) | (uint32_t)(0x1UL << btIpcConfig->dlChannelHPC));
473     contextPtr->ulReleaseMask = (uint32_t)((uint32_t)(0x1UL << btIpcConfig->ulChannelHCI) | (uint32_t)(0x1UL << btIpcConfig->ulChannelHPC));
474 
475     contextPtr->droppedHCI = 0;
476 
477     contextPtr->bootType = 0xFF;
478 
479     for (idx = 0U; idx <((uint8_t)MAX_BT_IPC_HPC_CB); idx++)
480     {
481         contextPtr->hpcNotifyCallbackParam[idx].hpcNotifyCallbackPtr = NULL;
482         contextPtr->hpcNotifyCallbackParam[idx].msgType = CY_BT_IPC_HPC_RESERVED;
483     }
484 
485     for (idx = 0U; idx < ((uint8_t)MAX_BUF_COUNT); idx++)
486     {
487         contextPtr->buffPool[idx].bufPtr = NULL;
488         contextPtr->buffPool[idx].bufType = CY_BT_IPC_HCI_INVALID_BUF;
489     }
490 
491     for (idx = 0U; idx < ((uint8_t)MAX_IPC_FIFO_SIZE); idx++)
492     {
493         contextPtr->IpcFifo.fifo[idx].msg[0] = 0;
494         contextPtr->IpcFifo.fifo[idx].msg[1] = 0;
495     }
496     contextPtr->IpcFifo.rdIdx = 0;
497     contextPtr->IpcFifo.wrIdx = 0;
498     contextPtr->IpcFifo.bufLen = 0;
499 
500     for (idx = 0U; idx < ((uint8_t)MAX_TO_FREE_BUF_COUNT); idx++)
501     {
502         contextPtr->toFreeBuf[idx].bufPtr = NULL;
503         contextPtr->toFreeBuf[idx].bufType = CY_BT_IPC_HCI_INVALID_BUF;
504         contextPtr->toFreeBuf[idx].bufLen = 0;
505     }
506 
507     status = Cy_BTIPC_WarmInit(contextPtr, btIpcConfig);
508 
509 #ifdef CY_BTIPC_STATS
510     contextPtr->ipc_int_count = 0;
511 
512     contextPtr->ipc_hci_cmd_count = 0;
513     contextPtr->ipc_hpc_cmd_count = 0;
514 
515     contextPtr->ipc_hci_release_count = 0;
516     contextPtr->ipc_hpc_release_count = 0;
517 
518     contextPtr->ipc_hci_notify_count = 0;
519     contextPtr->ipc_hpc_notify_count = 0;
520 
521     contextPtr->ipc_hci_peer_release_count = 0;
522     contextPtr->ipc_hpc_peer_release_count = 0;
523 
524     contextPtr->ipc_hci_peer_inbuf_count = 0;
525     contextPtr->ipc_hci_peer_outbuf_count = 0;
526 
527     contextPtr->ipc_hpc_peer_inbuf_count = 0;
528     contextPtr->ipc_hpc_peer_outbuf_count = 0;
529 
530     contextPtr->ipc_hci_cmd_self_outbuf_count = 0;
531     contextPtr->ipc_hci_cmd_self_inbuf_count = 0;
532     contextPtr->ipc_hci_cmd_self_outbuf_success = 0;
533 
534     contextPtr->ipc_hci_fifo_full = 0;
535     contextPtr->ipc_hci_notify_in_fifo_full = 0;
536 #endif
537     return status;
538  }
539 
540 
Cy_BTIPC_WarmInit(cy_stc_ipc_bt_context_t * btIpcContext,cy_stc_ipc_bt_config_t * btIpcConfig)541 cy_en_btipcdrv_status_t Cy_BTIPC_WarmInit(cy_stc_ipc_bt_context_t *btIpcContext, cy_stc_ipc_bt_config_t *btIpcConfig)
542 {
543     cy_en_sysint_status_t intrStatus;
544     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
545 
546     if ((NULL == contextPtr) || (NULL == btIpcConfig))
547     {
548         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
549     }
550 
551     intrStatus = Cy_SysInt_Init(&contextPtr->ipcIntConfig, contextPtr->irqHandlerPtr);
552     if (((uint32_t)intrStatus) != 0UL)
553     {
554         return CY_BT_IPC_DRV_ERROR;
555     }
556 
557     /* enable interrupt */
558     NVIC_EnableIRQ(contextPtr->ipcIntConfig.intrSrc);
559 
560     /* Set IPC Interrupt mask */
561     /* Allow only notify on DL channel  and release on UL channel interrupts */
562     Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(contextPtr->intStuctureSelf), contextPtr->ulReleaseMask, contextPtr->dlNotifyMask);
563     return CY_BT_IPC_DRV_SUCCESS;
564  }
565 
566 
Cy_BTIPC_Deinit(cy_stc_ipc_bt_context_t * btIpcContext)567 cy_en_btipcdrv_status_t Cy_BTIPC_Deinit(cy_stc_ipc_bt_context_t *btIpcContext)
568 {
569     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
570     uint8_t idx;
571 
572     if (NULL == contextPtr)
573     {
574         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
575     }
576 
577     /* enable interrupt */
578     NVIC_DisableIRQ(contextPtr->ipcIntConfig.intrSrc);
579 
580     contextPtr->irqHandlerPtr = NULL;
581     contextPtr->internal_hpc_notify_cb = NULL;
582 
583     for (idx = 0; idx < ((uint8_t)MAX_BT_IPC_HPC_CB); idx++)
584     {
585         contextPtr->hpcNotifyCallbackParam[idx].hpcNotifyCallbackPtr = NULL;
586         contextPtr->hpcNotifyCallbackParam[idx].msgType = CY_BT_IPC_HPC_RESERVED;
587     }
588 
589     for (idx = 0U; idx < ((uint8_t)MAX_BUF_COUNT); idx++)
590     {
591         contextPtr->buffPool[idx].bufPtr = NULL;
592         contextPtr->buffPool[idx].bufType = CY_BT_IPC_HCI_INVALID_BUF;
593     }
594 
595     return CY_BT_IPC_DRV_SUCCESS;
596 }
597 
598 
599 CY_IPC_SECTION_BEGIN
Cy_BTIPC_HCI_getPTI(cy_en_btipc_hcipti_t * pti,uint32_t * p_length,uint32_t * msgPtr)600 cy_en_btipcdrv_status_t Cy_BTIPC_HCI_getPTI (cy_en_btipc_hcipti_t *pti, uint32_t *p_length, uint32_t *msgPtr)
601 {
602     cy_stc_ipc_msg_buff_t *ipcMsgBuf;
603     uint8_t *bufAddr;
604     cy_en_btipc_hcipti_t mesgPti;
605 
606     if ((NULL == pti) || (NULL == msgPtr) || (NULL == p_length))
607     {
608         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
609     }
610 
611     /* Incase of long messages the PTI needs to be read from DATA0[bit 8-15] */
612     CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.8','Intentional typecast to cy_en_btipc_hcipti_t enum');
613     mesgPti = (cy_en_btipc_hcipti_t)((0xFFUL) & msgPtr[0]);
614     if (mesgPti == CY_BT_IPC_HCI_LONG)
615     {
616         ipcMsgBuf = (cy_stc_ipc_msg_buff_t*)((void*)msgPtr);
617         *pti = (cy_en_btipc_hcipti_t)ipcMsgBuf->actualPti;
618         bufAddr = ipcMsgBuf->bufAddr;
619         /* Mapping of BT address space to MCU address space */
620 #if defined(BT_IPC_SIM) || !defined (BTSS)
621         bufAddr = (uint8_t*)bufAddr;
622 #else
623         bufAddr = (uint8_t*)((uint32_t)(bufAddr) + ((uint32_t)BTSS_DATA_RAM_IPC - 0x28000000UL));
624 #endif
625 
626         if (Cy_bt_isOffsetNeeded(*pti))
627         {
628             bufAddr++;
629         }
630     }
631     else
632     {
633         *pti = mesgPti;
634         bufAddr = (uint8_t*)msgPtr;
635         /* Skip the PTI byte read from the DATA0 register */
636         bufAddr++;
637     }
638     *p_length = Cy_bt_getPLLegnth(*pti, bufAddr);
639     return CY_BT_IPC_DRV_SUCCESS;
640 }
641 CY_IPC_SECTION_END
642 
643 CY_IPC_SECTION_BEGIN
Cy_BTIPC_HCI_GetReadBufPtr(cy_stc_ipc_bt_context_t * btIpcContext,void ** ppData,size_t * pLength)644 cy_en_btipcdrv_status_t Cy_BTIPC_HCI_GetReadBufPtr (cy_stc_ipc_bt_context_t *btIpcContext, void **ppData, size_t* pLength)
645 {
646     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
647     cy_stc_ipc_msg_buff_t *ipcMsgBuf;
648     cy_stc_ipc_msg_short_t *shortMesg;
649     cy_en_btipc_hcipti_t actualPti;
650     cy_en_btipc_hcipti_t mesgPti;
651     cy_en_btipcdrv_status_t status;
652     uint32_t *pMsg;
653     uint8_t *srcPtr;
654     uint8_t idx;
655     uint8_t done;
656     uint32_t interruptState;
657 
658     if ((NULL == contextPtr) || (NULL == ppData))
659     {
660         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
661     }
662 
663     status = Cy_BTIPC_HCI_FIFOGet(contextPtr, &pMsg, 0);
664 
665     if (((uint32_t)status) != 0UL)
666     {
667         return status;
668     }
669 
670     CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 10.8','Intentional typecast to cy_en_btipc_hcipti_t enum.');
671     mesgPti = (cy_en_btipc_hcipti_t)((0xFFUL) & pMsg[0]);
672 
673     if (mesgPti == CY_BT_IPC_HCI_LONG)
674     {
675         ipcMsgBuf = (cy_stc_ipc_msg_buff_t*)((void*)pMsg);
676         actualPti = (cy_en_btipc_hcipti_t)ipcMsgBuf->actualPti;
677         srcPtr = ipcMsgBuf->bufAddr;
678         /* Mapping of BT address space to MCU address space */
679 #if defined(BT_IPC_SIM) || !defined (BTSS)
680         srcPtr = (uint8_t*)(srcPtr);
681 #else
682         srcPtr = (uint8_t*)((uint32_t)(srcPtr) + ((uint32_t)BTSS_DATA_RAM_IPC - 0x28000000UL));
683 #endif
684 #ifdef CY_BTIPC_STATS
685         contextPtr->ipc_hci_peer_inbuf_count++;
686 #endif
687         if (Cy_bt_isOffsetNeeded(actualPti))
688         {
689             srcPtr++;
690         }
691         *pLength = Cy_bt_getPLLegnth(actualPti, srcPtr);
692 
693         interruptState = Cy_SysLib_EnterCriticalSection();
694 
695         done = 0;
696         for (idx = 0U; idx < ((uint8_t)MAX_TO_FREE_BUF_COUNT); idx++)
697         {
698             if (contextPtr->toFreeBuf[idx].bufPtr == NULL)
699             {
700                 contextPtr->toFreeBuf[idx].bufType = Cy_bt_get_buf_type(actualPti);
701                 contextPtr->toFreeBuf[idx].bufLen = (uint16_t)(*pLength);
702                 contextPtr->toFreeBuf[idx].bufPtr = ipcMsgBuf->bufAddr;
703                 done = 1;
704                 break;
705             }
706         }
707 
708         Cy_SysLib_ExitCriticalSection(interruptState);
709 
710         if (done == 0U)
711         {
712             return CY_BT_IPC_DRV_ERROR_BUF_FULL;
713         }
714 
715     }
716     else
717     {
718         shortMesg = (cy_stc_ipc_msg_short_t*)((void*)pMsg);
719         srcPtr = &(shortMesg->db0);
720         *pLength = Cy_bt_getPLLegnth(mesgPti, srcPtr);
721     }
722 
723     *ppData = srcPtr;
724     return CY_BT_IPC_DRV_SUCCESS;
725 }
726 CY_IPC_SECTION_END
727 
728 CY_IPC_SECTION_BEGIN
Cy_BTIPC_HCI_GetWriteBufPtr(cy_stc_ipc_bt_context_t * btIpcContext,cy_en_btipc_hcipti_t pti,void ** ppData,size_t length)729 cy_en_btipcdrv_status_t Cy_BTIPC_HCI_GetWriteBufPtr(cy_stc_ipc_bt_context_t *btIpcContext, cy_en_btipc_hcipti_t pti, void **ppData, size_t length)
730 {
731     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
732     cy_en_btipcdrv_status_t status;
733     uint8_t *destBuf;
734     cy_en_btipc_buftype_t bufType;
735     uint8_t *bPtr;
736     uint32_t interruptState;
737 
738     if ((NULL == contextPtr) || (NULL == ppData))
739     {
740         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
741     }
742 
743     interruptState = Cy_SysLib_EnterCriticalSection();
744     /* If the HCI channel is busy then do not proceed further, return CH BUSY error */
745     if (Cy_IPC_Drv_IsLockAcquired (Cy_IPC_Drv_GetIpcBaseAddress(contextPtr->ulChannelHCI)))
746     {
747         Cy_SysLib_ExitCriticalSection(interruptState);
748         return CY_BT_IPC_DRV_ERROR_CH_BUSY;
749     }
750     Cy_SysLib_ExitCriticalSection(interruptState);
751 
752     *ppData = NULL;
753 
754     /* Get the buffer type based on the payload type indicator */
755     bufType = Cy_bt_get_buf_type(pti);
756     /* Pick a free buffer from the pool of buffers */
757     status = Cy_bt_GetBuffer (contextPtr, (void **)&destBuf, bufType, length);
758     if (((uint32_t)status) != 0UL)
759     {
760         return status;
761     }
762 
763     bPtr = destBuf;
764     /* Skip pad byte if needed */
765     if (Cy_bt_isOffsetNeeded(pti))
766     {
767         bPtr++;
768     }
769     *ppData = bPtr;
770     return CY_BT_IPC_DRV_SUCCESS;
771 }
772 CY_IPC_SECTION_END
773 
774 CY_IPC_SECTION_BEGIN
Cy_BTIPC_HCI_Write(cy_stc_ipc_bt_context_t * btIpcContext,cy_en_btipc_hcipti_t pti,void * data,size_t length)775 cy_en_btipcdrv_status_t Cy_BTIPC_HCI_Write(cy_stc_ipc_bt_context_t *btIpcContext, cy_en_btipc_hcipti_t pti, void *data, size_t length)
776 {
777     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
778     cy_stc_ipc_msg_buff_t ipcPacket;
779     cy_stc_ipc_msg_short_t ipcShort;
780     uint32_t *msgPtr;
781     uint8_t *bPtr, *bDptr;
782     uint8_t i;
783 
784     if ((NULL == contextPtr) || (NULL == data))
785     {
786         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
787     }
788 
789     /* Check if it is long message or ACL or ISO packet.
790      * As per BT FW team's request, this deviation is taken to use buffers for
791      * ACL and ISO short packets. Ref JIRA DRIVERS-6513 for more details */
792     if ((length > ((uint8_t)MAX_SHORT_MESG_LENGTH)) || (pti == CY_BT_IPC_HCI_ACL)
793         || (pti == CY_BT_IPC_HCI_ISO))
794     {
795         /* Add pad byte if needed */
796         bPtr = (uint8_t*)data;
797         if (Cy_bt_isOffsetNeeded(pti))
798         {
799             bPtr--;
800         }
801 
802         ipcPacket.pti = (uint8_t) CY_BT_IPC_HCI_LONG;
803         ipcPacket.actualPti = (uint8_t)pti;
804         ipcPacket.bufSize = 0;
805         // Remap the address to BT memory map
806 #if defined(BT_IPC_SIM) || !defined (BTSS)
807         ipcPacket.bufAddr = bPtr;
808 #else
809         ipcPacket.bufAddr = (uint8_t*)((uint32_t)bPtr - ((uint32_t)BTSS_DATA_RAM_IPC - 0x28000000UL));
810 #endif
811         /* end of buffer preparation */
812         msgPtr = (uint32_t*)((void*)&ipcPacket);
813     }
814     else /* Short Message */
815     {
816         msgPtr = (uint32_t*)((void*)&ipcShort);
817         msgPtr[0] = 0;
818         msgPtr[1] = 0;
819         ipcShort.pti = (uint8_t)pti;
820         bPtr = &(ipcShort.db0);
821         bDptr = (uint8_t*)data;
822 
823         for (i = 0; i < length; i++)
824         {
825             CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 18.1','Checked manually, these pointer will not exceed register range.');
826             *bPtr++ = *bDptr++;
827         }
828     }
829 
830     if (Cy_IPC_Drv_SendMsgDWord(Cy_IPC_Drv_GetIpcBaseAddress(contextPtr->ulChannelHCI),
831                                 contextPtr->intPeerMask, msgPtr) == CY_IPC_DRV_SUCCESS)
832     {
833 #ifdef CY_BTIPC_STATS
834         contextPtr->ipc_hci_cmd_count++;
835 #endif
836         (void)Cy_BTSS_PowerDep(true);
837 
838         return CY_BT_IPC_DRV_SUCCESS;
839     }
840     else
841     {
842         (void)ipcShort.pti; /* Suppress a compiler warning about unused variables */
843         return CY_BT_IPC_DRV_ERROR_LOCK_ACQUIRE;
844     }
845 }
846 CY_IPC_SECTION_END
847 
Cy_BTIPC_HPC_GetWriteBufPtr(cy_stc_ipc_bt_context_t * btIpcContext,void ** ppData,size_t length)848 cy_en_btipcdrv_status_t Cy_BTIPC_HPC_GetWriteBufPtr(cy_stc_ipc_bt_context_t *btIpcContext, void **ppData, size_t length)
849 {
850     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
851     cy_en_btipcdrv_status_t status;
852     uint8_t *destBuf;
853     (void)length;
854     uint32_t interruptState;
855 
856     if ((NULL == contextPtr) || (NULL == ppData))
857     {
858         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
859     }
860 
861     interruptState = Cy_SysLib_EnterCriticalSection();
862     /* If the HPC channel is busy then do not proceed further, return CH BUSY error */
863     if (Cy_IPC_Drv_IsLockAcquired (Cy_IPC_Drv_GetIpcBaseAddress(contextPtr->ulChannelHPC)))
864     {
865         Cy_SysLib_ExitCriticalSection(interruptState);
866         return CY_BT_IPC_DRV_ERROR_CH_BUSY;
867     }
868     Cy_SysLib_ExitCriticalSection(interruptState);
869 
870     *ppData = NULL;
871     /* Pick a free control buffer from the pool of buffers */
872     status = Cy_bt_GetBuffer (contextPtr, (void **)&destBuf, CY_BT_IPC_CTRL_BUF, length);
873     if (((uint32_t)status) == 0UL)
874     {
875         *ppData = destBuf;
876     }
877     (void) length; /* Suppress a compiler warning about unused variables */
878     return status;
879 }
880 
881 
Cy_BTIPC_HPC_Write(cy_stc_ipc_bt_context_t * btIpcContext,void * data,size_t length)882 cy_en_btipcdrv_status_t Cy_BTIPC_HPC_Write(cy_stc_ipc_bt_context_t *btIpcContext, void *data, size_t length)
883 {
884     uint32_t *dataPtr = (uint32_t*) data;
885     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
886 
887     (void) length;
888 
889     if ((NULL == contextPtr) || (NULL == data))
890     {
891         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
892     }
893 
894     if (!((bool)(Cy_IPC_Drv_SendMsgDWord(Cy_IPC_Drv_GetIpcBaseAddress(contextPtr->ulChannelHPC),
895                                 contextPtr->intPeerMask, (uint32_t*) dataPtr))))
896     {
897 #ifdef CY_BTIPC_STATS
898         contextPtr->ipc_hpc_cmd_count++;
899 #endif
900         (void)Cy_BTSS_PowerDep(true);
901 
902         return CY_BT_IPC_DRV_SUCCESS;
903     }
904     else
905     {
906         return CY_BT_IPC_DRV_ERROR_LOCK_ACQUIRE;
907     }
908 }
909 
910 
Cy_BTIPC_HCI_RegisterCb(cy_stc_ipc_bt_context_t * btIpcContext,cy_ipc_bt_callback_ptr_t hciNotifyCallbackPtr)911 cy_en_btipcdrv_status_t Cy_BTIPC_HCI_RegisterCb(cy_stc_ipc_bt_context_t *btIpcContext, cy_ipc_bt_callback_ptr_t hciNotifyCallbackPtr)
912 {
913     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
914 
915     if ((NULL == contextPtr) || (NULL == hciNotifyCallbackPtr))
916     {
917         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
918     }
919 
920     contextPtr->dlNotifyCallbackPtr = hciNotifyCallbackPtr;
921     return CY_BT_IPC_DRV_SUCCESS;
922 }
923 
924 
Cy_BTIPC_HCI_UnregisterCb(cy_stc_ipc_bt_context_t * btIpcContext)925 cy_en_btipcdrv_status_t Cy_BTIPC_HCI_UnregisterCb(cy_stc_ipc_bt_context_t *btIpcContext)
926 {
927     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
928 
929     if (NULL == contextPtr)
930     {
931         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
932     }
933 
934     contextPtr->dlNotifyCallbackPtr = NULL;
935 
936     return CY_BT_IPC_DRV_SUCCESS;
937 }
938 
939 
Cy_BTIPC_HPC_RegisterCb(cy_stc_ipc_bt_context_t * btIpcContext,cy_stc_ipc_hcp_cb_t * pHpcNotifyCallbackParam)940 cy_en_btipcdrv_status_t Cy_BTIPC_HPC_RegisterCb(cy_stc_ipc_bt_context_t *btIpcContext, cy_stc_ipc_hcp_cb_t *pHpcNotifyCallbackParam)
941 {
942     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
943     uint8_t idx;
944     uint8_t placed;
945 
946     if ((NULL == contextPtr) || (NULL == pHpcNotifyCallbackParam))
947     {
948         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
949     }
950 
951     placed = 0U;
952     for (idx = 0U; idx < ((uint8_t)MAX_BT_IPC_HPC_CB); idx++)
953     {
954         if ((contextPtr->hpcNotifyCallbackParam[idx].hpcNotifyCallbackPtr == NULL) &&
955             (contextPtr->hpcNotifyCallbackParam[idx].msgType == CY_BT_IPC_HPC_RESERVED))
956         {
957             contextPtr->hpcNotifyCallbackParam[idx].hpcNotifyCallbackPtr = pHpcNotifyCallbackParam->hpcNotifyCallbackPtr;
958             contextPtr->hpcNotifyCallbackParam[idx].msgType = pHpcNotifyCallbackParam->msgType;
959             placed = 1;
960             break;
961         }
962     }
963 
964     if (placed != 0U)
965     {
966         return CY_BT_IPC_DRV_SUCCESS;
967     }
968     else
969     {
970         return CY_BT_IPC_DRV_ERROR;
971     }
972 }
973 
974 
Cy_BTIPC_HPC_UnregisterCb(cy_stc_ipc_bt_context_t * btIpcContext,cy_stc_ipc_hcp_cb_t * pHpcNotifyCallbackParam)975 cy_en_btipcdrv_status_t Cy_BTIPC_HPC_UnregisterCb(cy_stc_ipc_bt_context_t *btIpcContext, cy_stc_ipc_hcp_cb_t *pHpcNotifyCallbackParam)
976 {
977     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
978     uint8_t idx;
979     uint8_t found;
980 
981     if ((NULL == contextPtr) || (NULL == pHpcNotifyCallbackParam))
982     {
983         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
984     }
985 
986     found = 0;
987     for (idx = 0U; idx < ((uint8_t)MAX_BT_IPC_HPC_CB); idx++)
988     {
989         if ((contextPtr->hpcNotifyCallbackParam[idx].hpcNotifyCallbackPtr == pHpcNotifyCallbackParam->hpcNotifyCallbackPtr) &&
990             (contextPtr->hpcNotifyCallbackParam[idx].msgType == pHpcNotifyCallbackParam->msgType))
991         {
992             contextPtr->hpcNotifyCallbackParam[idx].hpcNotifyCallbackPtr = NULL;
993             contextPtr->hpcNotifyCallbackParam[idx].msgType = CY_BT_IPC_HPC_RESERVED;
994             found = 1;
995             break;
996         }
997     }
998 
999     if (found != 0UL)
1000     {
1001         return CY_BT_IPC_DRV_SUCCESS;
1002     }
1003     else
1004     {
1005         return CY_BT_IPC_DRV_ERROR;
1006     }
1007 }
1008 
1009 
Cy_BTIPC_Buffer_RegisterCb(cy_stc_ipc_bt_context_t * btIpcContext,cy_ipc_bt_bufcallback_ptr_t bufCallbackPtr)1010 cy_en_btipcdrv_status_t Cy_BTIPC_Buffer_RegisterCb(cy_stc_ipc_bt_context_t *btIpcContext, cy_ipc_bt_bufcallback_ptr_t bufCallbackPtr)
1011 {
1012     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1013     uint32_t interruptState;
1014 
1015     if ((NULL == contextPtr) || (NULL == bufCallbackPtr))
1016     {
1017         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
1018     }
1019 
1020     interruptState = Cy_SysLib_EnterCriticalSection();
1021     contextPtr->bufCallbackPtr = bufCallbackPtr;
1022     Cy_SysLib_ExitCriticalSection(interruptState);
1023 
1024     return CY_BT_IPC_DRV_SUCCESS;
1025 }
1026 
1027 
1028 CY_IPC_SECTION_BEGIN
Cy_bt_GetBuffer(cy_stc_ipc_bt_context_t * btIpcContext,void ** ppBuf,cy_en_btipc_buftype_t bufType,size_t length)1029 static cy_en_btipcdrv_status_t Cy_bt_GetBuffer (cy_stc_ipc_bt_context_t *btIpcContext, void **ppBuf, cy_en_btipc_buftype_t bufType, size_t length)
1030 {
1031     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1032     uint8_t idx;
1033     uint8_t found;
1034     uint8_t size_error;
1035     uint32_t interruptState;
1036 
1037     if ((NULL == contextPtr) || (NULL == ppBuf))
1038     {
1039         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
1040     }
1041 
1042     interruptState = Cy_SysLib_EnterCriticalSection();
1043 
1044     found = 0;
1045     size_error = 0;
1046 
1047     BTIPC_LOG_L2("Buf req: Type 0x%x, Size %d\n",bufType,length);
1048     BTIPC_LOG_L2("Buf Pool content\n");
1049 
1050 #ifdef CY_BTIPC_STATS
1051     if (bufType == CY_BT_IPC_HCI_CMD_BUF)
1052     {
1053         contextPtr->ipc_hci_cmd_self_outbuf_count++;
1054     }
1055 #endif
1056     for (idx = 0U; idx < ((uint8_t)MAX_BUF_COUNT); idx++)
1057     {
1058         BTIPC_LOG_L2("idx %d, bufType 0x%x, bufLen %d, bufPtr %p\n",idx, contextPtr->buffPool[idx].bufType,contextPtr->buffPool[idx].bufLen, contextPtr->buffPool[idx].bufPtr);
1059 
1060         if ((contextPtr->buffPool[idx].bufType == bufType) && (contextPtr->buffPool[idx].bufPtr != NULL))
1061         {
1062             if (length <= contextPtr->buffPool[idx].bufLen)
1063             {
1064                 *ppBuf = (void*)contextPtr->buffPool[idx].bufPtr;
1065                 // Mapping of address
1066 #if defined(BT_IPC_SIM) || !defined (BTSS)
1067                 *ppBuf = (void*)(*ppBuf);
1068 #else
1069                 *ppBuf = (void*)((uint32_t)(*ppBuf) + ((uint32_t)BTSS_DATA_RAM_IPC - 0x28000000UL));
1070 #endif
1071                 contextPtr->buffPool[idx].bufPtr = NULL;
1072                 contextPtr->buffPool[idx].bufType = CY_BT_IPC_HCI_INVALID_BUF;
1073                 found = 1;
1074 #ifdef CY_BTIPC_STATS
1075                 if (bufType == CY_BT_IPC_HCI_CMD_BUF)
1076                 {
1077                    contextPtr->ipc_hci_cmd_self_outbuf_success++;
1078                 }
1079 #endif
1080                 break;
1081             }
1082             else
1083             {
1084                 size_error = 1;
1085             }
1086         }
1087     }
1088 
1089     Cy_SysLib_ExitCriticalSection(interruptState);
1090 
1091     if (found != 0UL)
1092     {
1093         return CY_BT_IPC_DRV_SUCCESS;
1094     }
1095     else if (size_error == 1UL)
1096     {
1097         return CY_BT_IPC_DRV_ERROR_BUF_SIZE;
1098     }
1099     else
1100     {
1101         *ppBuf = NULL;
1102         return CY_BT_IPC_DRV_ERROR_BUF_GET;
1103     }
1104 
1105 }
1106 CY_IPC_SECTION_END
1107 
Cy_bt_PutBuffer(cy_stc_ipc_bt_context_t * btIpcContext,cy_stc_ipc_bt_buf_t * bufDecriptor)1108 static cy_en_btipcdrv_status_t Cy_bt_PutBuffer(cy_stc_ipc_bt_context_t *btIpcContext, cy_stc_ipc_bt_buf_t *bufDecriptor)
1109 {
1110     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1111     uint8_t idx;
1112     uint32_t interruptState;
1113     cy_en_btipcdrv_status_t status = CY_BT_IPC_DRV_ERROR_BUF_FULL;
1114 
1115     BTIPC_LOG_L2("Put buffer+\n");
1116 
1117     if ((NULL == contextPtr) || (NULL == bufDecriptor) || (bufDecriptor->bufPtr == NULL))
1118     {
1119         BTIPC_LOG_L2("Put buffer-\n");
1120         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
1121     }
1122 
1123     interruptState = Cy_SysLib_EnterCriticalSection();
1124 
1125     for (idx = 0U; idx < ((uint8_t)MAX_BUF_COUNT); idx++)
1126     {
1127         if ((contextPtr->buffPool[idx].bufType == bufDecriptor->bufType) &&
1128             (contextPtr->buffPool[idx].bufPtr == bufDecriptor->bufPtr))
1129         {
1130             BTIPC_LOG_L2("Buffer already present in the pool at %d\n",idx);
1131             status = CY_BT_IPC_DRV_ERROR_BUF_PRESENT;
1132             break;
1133         }
1134         else if (contextPtr->buffPool[idx].bufType == CY_BT_IPC_HCI_INVALID_BUF)
1135         {
1136             contextPtr->buffPool[idx] = *bufDecriptor;
1137             status = CY_BT_IPC_DRV_SUCCESS;
1138             BTIPC_LOG_L2("Added buffer at index %d\n",idx);
1139             break;
1140         }
1141         else
1142         {
1143             /* This is just to keep coverity happy */
1144         }
1145     }
1146 
1147     Cy_SysLib_ExitCriticalSection(interruptState);
1148 
1149     /* Call handler for buffer */
1150     if ((status == CY_BT_IPC_DRV_SUCCESS) && (NULL != contextPtr->bufCallbackPtr))
1151     {
1152         contextPtr->bufCallbackPtr(bufDecriptor->bufType);
1153     }
1154 
1155     BTIPC_LOG_L2("Put buffer-\n");
1156     return status;
1157 }
1158 
Cy_bt_RemoveBuffer(cy_stc_ipc_bt_context_t * btIpcContext,cy_en_btipc_buftype_t buftype)1159 static cy_en_btipcdrv_status_t Cy_bt_RemoveBuffer(cy_stc_ipc_bt_context_t *btIpcContext, cy_en_btipc_buftype_t buftype)
1160 {
1161     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1162     uint8_t idx;
1163     uint32_t interruptState;
1164     cy_en_btipcdrv_status_t status = CY_BT_IPC_DRV_ERROR_BUF_GET;
1165 
1166     BTIPC_LOG_L2("Remove buffer+\n");
1167 
1168     if ((NULL == contextPtr))
1169     {
1170         BTIPC_LOG_L2("Remove buffer-\n");
1171         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
1172     }
1173 
1174     interruptState = Cy_SysLib_EnterCriticalSection();
1175 
1176     for (idx = 0U; idx < ((uint8_t)MAX_BUF_COUNT); idx++)
1177     {
1178         if (contextPtr->buffPool[idx].bufType == buftype)
1179         {
1180             BTIPC_LOG_L2("Buffer removed from the pool at %d\n",idx);
1181             contextPtr->buffPool[idx].bufPtr = NULL;
1182             contextPtr->buffPool[idx].bufType = CY_BT_IPC_HCI_INVALID_BUF;
1183             status = CY_BT_IPC_DRV_SUCCESS;
1184             break;
1185         }
1186         else
1187         {
1188             /* This is just to keep coverity happy */
1189         }
1190     }
1191 
1192     Cy_SysLib_ExitCriticalSection(interruptState);
1193 
1194     BTIPC_LOG_L2("Remove buffer-\n");
1195     return status;
1196 }
1197 
Cy_bt_handle_buf_remove(cy_stc_ipc_bt_context_t * btIpcContext,uint32_t * msgPtr)1198 cy_en_btipcdrv_status_t Cy_bt_handle_buf_remove(cy_stc_ipc_bt_context_t *btIpcContext, uint32_t * msgPtr)
1199 {
1200     cy_stc_ipc_msg_buf_remove_t remBuf;
1201     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1202     cy_en_btipcdrv_status_t status;
1203 
1204     BTIPC_LOG_L2("Removing buf\n");
1205 
1206     if ((NULL == contextPtr) || (NULL == msgPtr))
1207     {
1208         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
1209     }
1210 
1211     remBuf = *(cy_stc_ipc_msg_buf_remove_t*)((void*)msgPtr);
1212 
1213     BTIPC_LOG_L2("bufType 0x%x\n",remBuf.bufType);
1214 #ifdef CY_BTIPC_STATS
1215     if ((cy_en_btipc_buftype_t)remBuf.bufType == CY_BT_IPC_HCI_CMD_BUF)
1216     {
1217         contextPtr->ipc_hci_cmd_self_outbuf_count++;
1218     }
1219 #endif
1220     status = Cy_bt_RemoveBuffer(contextPtr, (cy_en_btipc_buftype_t)remBuf.bufType);
1221     if (((uint32_t)status) != 0UL)
1222     {
1223         /* Need to check if some cleaning needed for error condition */
1224         BTIPC_LOG_L0("Error: 0x%x in removing the buffer from pool\n",status);
1225     }
1226     return status;
1227 }
1228 
1229 /* Local function implementation */
Cy_bt_handle_hpclong_msg(cy_stc_ipc_bt_context_t * btIpcContext,uint32_t * msgPtr)1230 cy_en_btipcdrv_status_t Cy_bt_handle_hpclong_msg(cy_stc_ipc_bt_context_t *btIpcContext, uint32_t * msgPtr)
1231 {
1232     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1233     cy_stc_ipc_msg_init_t *ptr;
1234     cy_stc_ipc_bt_buf_t bufDescriptor;
1235     cy_en_btipcdrv_status_t status;
1236     uint8_t i;
1237     uint8_t bufCount;
1238     uint8_t *bPtr;
1239     uint8_t *bDptr;
1240     cy_en_btipc_hpcmsgid_t longMsgType;
1241     uint8_t idx;
1242 
1243     if ((NULL == contextPtr) || (NULL == msgPtr))
1244     {
1245         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
1246     }
1247 
1248     bPtr = (uint8_t*)msgPtr;
1249     longMsgType = (cy_en_btipc_hpcmsgid_t)(*(bPtr+1));
1250 
1251     BTIPC_LOG_L1("longMsgType %d\n", longMsgType);
1252 
1253     status = CY_BT_IPC_DRV_SUCCESS;
1254 #ifdef CY_BTIPC_STATS
1255     contextPtr->ipc_hpc_peer_inbuf_count++;
1256 #endif
1257     switch (longMsgType)
1258     {
1259         case CY_BT_IPC_HPC_INIT:
1260             ptr = (cy_stc_ipc_msg_init_t*)(* (msgPtr+1));
1261             if (NULL == ptr)
1262             {
1263                 status = CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
1264                 break;
1265             }
1266             /* mapping of memory */
1267 #if defined(BT_IPC_SIM) || !defined (BTSS)
1268             ptr = (cy_stc_ipc_msg_init_t*)(ptr);
1269 #else
1270             ptr = (cy_stc_ipc_msg_init_t*)((uint32)ptr + ((uint32_t)BTSS_DATA_RAM_IPC - 0x28000000UL));
1271 #endif
1272             /* The payloadLen includes bootype (1 byte) and error code (4 bytes).
1273             Hence, subtract INIT_IPC_BUFF_DESC_OFFSET (5 Bytes) from it */
1274             bufCount = (ptr->payLoadLen - (uint8_t)INIT_IPC_BUFF_DESC_OFFSET)/((uint8_t)BUFFER_DESCRIPTION_LEN);
1275 
1276             /* Add code to extract boot type from init structure */
1277             contextPtr->bootType = ptr->bootType;
1278 #ifndef BT_OLD_INIT
1279             bPtr = (uint8_t*)(&ptr->bootType);
1280             CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 18.1','Checked manually, the byte pointer will not corrupt memory.');
1281             bPtr++;
1282             bDptr = (uint8_t*)(&contextPtr->certError);
1283             CY_MISRA_DEVIATE_LINE('MISRA C-2012 Rule 18.1','Checked manually, the byte pointer will not corrupt memory.');
1284             *bDptr++ = *bPtr++;
1285             *bDptr++ = *bPtr++;
1286             *bDptr++ = *bPtr++;
1287             *bDptr++ = *bPtr++;
1288 #endif
1289 
1290 #ifdef BT_OLD_INIT
1291             BTIPC_LOG_L0("handling Init mesg from %p, boottype %d, payload len 0x%x, bufCount %d\n",
1292                 ptr, ptr->bootType, ptr->payLoadLen, bufCount);
1293 #else
1294             BTIPC_LOG_L0("handling Init mesg from %p, boottype %d, payload len 0x%x, certError 0x%lx bufCount %d\n",
1295                 ptr, ptr->bootType, ptr->payLoadLen, contextPtr->certError , bufCount);
1296 #endif
1297 
1298 
1299             if ((ptr->bootType == (uint8_t)CY_BT_IPC_BOOT_CONFIG_WAIT) ||
1300                 (ptr->bootType == (uint8_t)CY_BT_IPC_BOOT_FULLY_UP))
1301             {
1302 
1303                 /* Clear all buffers in the pool */
1304                 for (idx = 0U; idx < ((uint8_t)MAX_BUF_COUNT); idx++)
1305                 {
1306                     contextPtr->buffPool[idx].bufPtr = NULL;
1307                     contextPtr->buffPool[idx].bufType = CY_BT_IPC_HCI_INVALID_BUF;
1308                 }
1309 
1310                 //msgId
1311                 //bootType
1312                 /* point to the start of buffer pool */
1313                 bPtr = (uint8_t*)ptr + sizeof(cy_stc_ipc_msg_init_t);
1314 
1315                 BTIPC_LOG_L0("\nExtract buffers from %p\n",bPtr);
1316 
1317                 for (i = 0; i < bufCount; i++)
1318                 {
1319                     bufDescriptor.bufType = (cy_en_btipc_buftype_t) (*bPtr++);
1320 
1321                     bDptr = (uint8_t*)(&bufDescriptor.bufLen);
1322                     *bDptr++ = *bPtr++;
1323                     *bDptr++ = *bPtr++;
1324 
1325                     bDptr = (uint8_t*)(&bufDescriptor.bufPtr);
1326                     *bDptr++ = *bPtr++;
1327                     *bDptr++ = *bPtr++;
1328                     *bDptr++ = *bPtr++;
1329                     *bDptr++ = *bPtr++;
1330 
1331                     BTIPC_LOG_L0("bufType %x, bufLen %d, bufPtr %p\n",bufDescriptor.bufType, bufDescriptor.bufLen, bufDescriptor.bufPtr);
1332 
1333                     status = Cy_bt_PutBuffer(contextPtr, &bufDescriptor);
1334                     if (((uint32_t)status) != 0UL)
1335                     {
1336                         /* Need to check if some cleaning needed for error condition */
1337                         BTIPC_LOG_L0("Error in putting the buffer to pool\n");
1338                     }
1339                     else
1340                     {
1341                         BTIPC_LOG_L0("Added buf %d\n",i);
1342                     }
1343                 }
1344                 BTIPC_LOG_L0("Bufs add done\n\n");
1345             }
1346             else
1347             {
1348                 BTIPC_LOG_L0("\nInvalid Boot type\n");
1349             }
1350             break;
1351 
1352         case CY_BT_IPC_HPC_HADM:
1353             BTIPC_LOG_L1("HADM Data\n");
1354             /* Add code to handle HADM data */
1355             break;
1356 
1357         default:
1358             /* Invalid long message type */
1359             status = CY_BT_IPC_DRV_ERROR_PARAM;
1360             break;
1361     }
1362     return status;
1363 }
1364 
1365 
Cy_bt_handle_buf_add(cy_stc_ipc_bt_context_t * btIpcContext,uint32_t * msgPtr)1366 cy_en_btipcdrv_status_t Cy_bt_handle_buf_add(cy_stc_ipc_bt_context_t *btIpcContext, uint32_t * msgPtr)
1367 {
1368     cy_stc_ipc_bt_buf_t bufDescriptor;
1369     cy_stc_ipc_msg_alloc_t allocBuf;
1370     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1371     cy_en_btipcdrv_status_t status;
1372 
1373     BTIPC_LOG_L2("Adding buf\n");
1374 
1375     if ((NULL == contextPtr) || (NULL == msgPtr))
1376     {
1377         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
1378     }
1379 
1380     allocBuf = *(cy_stc_ipc_msg_alloc_t*)((void*)msgPtr);
1381     bufDescriptor.bufType = (cy_en_btipc_buftype_t) allocBuf.bufType;
1382     bufDescriptor.bufLen = allocBuf.bufSize;
1383     bufDescriptor.bufPtr = (uint8_t*) allocBuf.bufAddr;
1384 
1385     BTIPC_LOG_L2("bufType 0x%x, bufLen 0x%x, bufPtr %p\n",bufDescriptor.bufType, bufDescriptor.bufLen, bufDescriptor.bufPtr);
1386 #ifdef CY_BTIPC_STATS
1387     if (bufDescriptor.bufType == CY_BT_IPC_HCI_CMD_BUF)
1388     {
1389         contextPtr->ipc_hci_cmd_self_inbuf_count++;
1390     }
1391 #endif
1392     status = Cy_bt_PutBuffer(contextPtr, &bufDescriptor);
1393     if (((uint32_t)status) != 0UL)
1394     {
1395         /* Need to check if some cleaning needed for error condition */
1396         BTIPC_LOG_L0("Error: 0x%x in putting the buffer to pool\n",status);
1397     }
1398     return status;
1399 }
1400 
1401 
1402 CY_IPC_SECTION_BEGIN
Cy_bt_get_buf_type(cy_en_btipc_hcipti_t pti)1403 static cy_en_btipc_buftype_t Cy_bt_get_buf_type(cy_en_btipc_hcipti_t pti)
1404 {
1405     cy_en_btipc_buftype_t bufType;
1406 
1407     /* To be done: Currently returning Control buffer for all PTIs. Need to change it once we have clarity on it */
1408     switch (pti)
1409     {
1410         case CY_BT_IPC_HCI_CMD:
1411             bufType = CY_BT_IPC_HCI_CMD_BUF;
1412             break;
1413         case CY_BT_IPC_HCI_ACL:
1414         /* CY_BT_IPC_HCI_BREDR_BUF if classic BT, or CY_BT_IPC_HCI_BLE_BUF for BLE. 20829 only supports BLE*/
1415             bufType = CY_BT_IPC_HCI_BLE_BUF;
1416             break;
1417         case CY_BT_IPC_HCI_ISO:
1418             bufType = CY_BT_IPC_HCI_ISOC_BUF;
1419             break;
1420         case CY_BT_IPC_HCI_EVT:
1421         /* This will not be sent from MCU. But simulation code needs it */
1422             bufType = CY_BT_IPC_HCI_CMD_BUF;
1423             break;
1424         case CY_BT_IPC_HCI_DIAG:
1425             bufType = CY_BT_IPC_HCI_CMD_BUF;
1426         break;
1427         case CY_BT_IPC_HCI_SCO:
1428         /* SCO is not supported in CYW20829 */
1429         /* Do not have info. Needs to be revisited later */
1430         case CY_BT_IPC_HCI_MPAF:
1431         /* Not Supported */
1432         case CY_BT_IPC_HCI_SLIPH5:
1433         /* Not Supported */
1434         default:
1435             bufType = CY_BT_IPC_HCI_INVALID_BUF;
1436             break;
1437     }
1438     return bufType;
1439 }
1440 CY_IPC_SECTION_END
1441 
1442 CY_IPC_SECTION_BEGIN
Cy_bt_getPLLegnth(cy_en_btipc_hcipti_t pti,uint8_t * bufAddr)1443 static uint32_t Cy_bt_getPLLegnth(cy_en_btipc_hcipti_t pti, uint8_t* bufAddr)
1444 {
1445     uint32_t length;
1446     switch (pti)
1447     {
1448         case CY_BT_IPC_HCI_CMD:
1449             length = (uint32_t)(((BTHCI_CMD_HDR_t*)((void*)bufAddr))->params_len);
1450             length += sizeof(BTHCI_CMD_HDR_t);
1451             break;
1452         case CY_BT_IPC_HCI_ACL:
1453             length = (uint32_t)(((BTHCI_ACL_HDR_t*)((void*)bufAddr))->data_len);
1454             length += sizeof(BTHCI_ACL_HDR_t);
1455             break;
1456         case CY_BT_IPC_HCI_SCO:
1457             length = (uint32_t)(((BTHCI_SCO_HDR_t*)((void*)bufAddr))->data_len);
1458             length += sizeof(BTHCI_SCO_HDR_t);
1459             break;
1460         case CY_BT_IPC_HCI_EVT:
1461             length = (uint32_t)(((BTHCI_EVENT_HDR_t*)((void*)bufAddr))->params_len);
1462             length += sizeof(BTHCI_EVENT_HDR_t);
1463             break;
1464         case CY_BT_IPC_HCI_ISO:
1465             length = (uint32_t)(((BTHCI_ISO_HDR_t*)((void*)bufAddr))->data_len);
1466             length += sizeof(BTHCI_ISO_HDR_t);
1467             break;
1468         case CY_BT_IPC_HCI_DIAG:
1469             length = *bufAddr; /* The first byte of the payload holds the payload length */
1470             break;
1471         /* To be done: Header length for the remaining PTI needs to be updated */
1472         case CY_BT_IPC_HCI_MPAF:
1473             length = 0;
1474             break;
1475         case CY_BT_IPC_HCI_SLIPH5:
1476             length = 0;
1477             break;
1478         default:
1479             length = 0;
1480             break;
1481     }
1482     return length;
1483 }
1484 CY_IPC_SECTION_END
1485 
1486 CY_IPC_SECTION_BEGIN
Cy_bt_isOffsetNeeded(cy_en_btipc_hcipti_t pti)1487 static bool Cy_bt_isOffsetNeeded(cy_en_btipc_hcipti_t pti)
1488 {
1489     bool ret;
1490 
1491     switch (pti)
1492     {
1493         case CY_BT_IPC_HCI_CMD:
1494         case CY_BT_IPC_HCI_SCO:
1495             ret = true;
1496             break;
1497         case CY_BT_IPC_HCI_ACL:
1498         case CY_BT_IPC_HCI_EVT:
1499         case CY_BT_IPC_HCI_ISO:
1500         case CY_BT_IPC_HCI_DIAG:
1501         case CY_BT_IPC_HCI_MPAF:
1502         case CY_BT_IPC_HCI_SLIPH5:
1503         default:
1504             ret = false;
1505             break;
1506     }
1507 
1508     return ret;
1509 }
1510 CY_IPC_SECTION_END
1511 
Cy_BTIPC_HCI_FIFOPut(cy_stc_ipc_bt_context_t * btIpcContext,uint32_t * pMsg)1512 static cy_en_btipcdrv_status_t Cy_BTIPC_HCI_FIFOPut(cy_stc_ipc_bt_context_t *btIpcContext, uint32_t *pMsg)
1513 {
1514     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1515     uint32_t interruptState;
1516 
1517     /* Check if buffer is full */
1518     if (contextPtr->IpcFifo.bufLen == ((uint8_t)MAX_IPC_FIFO_SIZE))
1519     {
1520         return CY_BT_IPC_DRV_ERROR_BUF_FULL;
1521     }
1522 
1523     interruptState = Cy_SysLib_EnterCriticalSection();
1524 
1525     contextPtr->IpcFifo.fifo[contextPtr->IpcFifo.wrIdx].msg[0] = pMsg[0];
1526     contextPtr->IpcFifo.fifo[contextPtr->IpcFifo.wrIdx].msg[1] = pMsg[1];
1527 
1528     contextPtr->IpcFifo.bufLen++;
1529     contextPtr->IpcFifo.wrIdx++;
1530 
1531     /* If at last index in buffer, set writeIndex back to 0 */
1532     if (contextPtr->IpcFifo.wrIdx == ((uint8_t)MAX_IPC_FIFO_SIZE))
1533     {
1534         contextPtr->IpcFifo.wrIdx = 0;
1535     }
1536 
1537     Cy_SysLib_ExitCriticalSection(interruptState);
1538     return CY_BT_IPC_DRV_SUCCESS;
1539 }
1540 
1541 CY_IPC_SECTION_BEGIN
Cy_BTIPC_HCI_FIFOGet(cy_stc_ipc_bt_context_t * btIpcContext,uint32_t ** ppMsg,uint8_t delete)1542 cy_en_btipcdrv_status_t Cy_BTIPC_HCI_FIFOGet(cy_stc_ipc_bt_context_t *btIpcContext, uint32_t **ppMsg, uint8_t delete)
1543 {
1544     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1545     uint32_t interruptState;
1546 
1547     /* Check if buffer is empty */
1548     if (contextPtr->IpcFifo.bufLen == 0U)
1549     {
1550         return CY_BT_IPC_DRV_ERROR_BUF_EMPTY;
1551     }
1552 
1553     interruptState = Cy_SysLib_EnterCriticalSection();
1554     *ppMsg = contextPtr->IpcFifo.fifo[contextPtr->IpcFifo.rdIdx].msg;
1555 
1556     if (delete != 0U)
1557     {
1558         contextPtr->IpcFifo.bufLen--;
1559         contextPtr->IpcFifo.rdIdx++;
1560 
1561         /* If at last index in buffer, set readIndex back to 0 */
1562         if (contextPtr->IpcFifo.rdIdx == ((uint8_t)MAX_IPC_FIFO_SIZE))
1563         {
1564             contextPtr->IpcFifo.rdIdx = 0;
1565         }
1566     }
1567     Cy_SysLib_ExitCriticalSection(interruptState);
1568 
1569     if ((delete != 0UL) && (((uint8_t)MAX_IPC_FIFO_SIZE - 1U) == contextPtr->IpcFifo.bufLen))
1570     {
1571         /* Release the channel as FIFO gets a free location */
1572         (void)Cy_BTIPC_HCI_RelChannel(contextPtr); /* Suppress a compiler warning about unused return value */
1573 #ifdef CY_BTIPC_STATS
1574         contextPtr->ipc_hci_peer_release_count++;
1575 #endif
1576         BTIPC_LOG_L0("Releasing the channel\n");
1577     }
1578     return CY_BT_IPC_DRV_SUCCESS;
1579 }
1580 CY_IPC_SECTION_END
1581 
1582 CY_IPC_SECTION_BEGIN
Cy_BTIPC_HCI_FIFOCount(cy_stc_ipc_bt_context_t * btIpcContext)1583 uint16_t Cy_BTIPC_HCI_FIFOCount(cy_stc_ipc_bt_context_t *btIpcContext)
1584 {
1585     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1586     uint32_t interruptState;
1587     uint16_t count;
1588 
1589     interruptState = Cy_SysLib_EnterCriticalSection();
1590     count = contextPtr->IpcFifo.bufLen;
1591     Cy_SysLib_ExitCriticalSection(interruptState);
1592     return count;
1593 }
1594 CY_IPC_SECTION_END
1595 
Cy_BTIPC_RetrieveContext(cy_stc_ipc_bt_context_t * btIpcContext,cy_stc_ipc_bt_save_ctxt_t * pContextRet)1596 cy_en_btipcdrv_status_t Cy_BTIPC_RetrieveContext(cy_stc_ipc_bt_context_t *btIpcContext, cy_stc_ipc_bt_save_ctxt_t *pContextRet)
1597 {
1598     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1599     uint32_t i;
1600 
1601     if ((NULL == contextPtr) || (NULL == pContextRet))
1602     {
1603         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
1604     }
1605 
1606     for (i = 0U; i < ((uint8_t)MAX_BUF_COUNT); i++)
1607     {
1608         pContextRet->buffPool[i].bufType = (uint16_t) contextPtr->buffPool[i].bufType;
1609         pContextRet->buffPool[i].bufLen = contextPtr->buffPool[i].bufLen;
1610         pContextRet->buffPool[i].bufPtr = contextPtr->buffPool[i].bufPtr;
1611     }
1612     return CY_BT_IPC_DRV_SUCCESS;
1613 }
1614 
Cy_BTIPC_RestoreContext(cy_stc_ipc_bt_context_t * btIpcContext,cy_stc_ipc_bt_save_ctxt_t * pContextRet)1615 cy_en_btipcdrv_status_t Cy_BTIPC_RestoreContext(cy_stc_ipc_bt_context_t *btIpcContext, cy_stc_ipc_bt_save_ctxt_t *pContextRet)
1616 {
1617     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1618     uint32_t i;
1619     if ((NULL == contextPtr) || (NULL == pContextRet))
1620     {
1621         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
1622     }
1623 
1624     for (i = 0U; i < ((uint8_t)MAX_BUF_COUNT); i++)
1625     {
1626         contextPtr->buffPool[i].bufType = (cy_en_btipc_buftype_t) pContextRet->buffPool[i].bufType;
1627         contextPtr->buffPool[i].bufLen = pContextRet->buffPool[i].bufLen;
1628         contextPtr->buffPool[i].bufPtr = pContextRet->buffPool[i].bufPtr;
1629     }
1630     return CY_BT_IPC_DRV_SUCCESS;
1631 }
1632 
1633 #ifdef BTIPC_STATUS
Cy_bt_PrintStatus(cy_stc_ipc_bt_context_t * btIpcContext)1634 cy_en_btipcdrv_status_t Cy_bt_PrintStatus (cy_stc_ipc_bt_context_t *btIpcContext)
1635 {
1636     cy_stc_ipc_bt_context_t *contextPtr = btIpcContext;
1637     uint8_t idx;
1638     uint32_t interruptState;
1639 
1640     if (NULL == contextPtr)
1641     {
1642         return CY_BT_IPC_DRV_ERROR_BAD_HANDLE;
1643     }
1644 
1645     interruptState = Cy_SysLib_EnterCriticalSection();
1646 
1647     printf("\n\nBuf Pool content\n");
1648     for (idx = 0U; idx < ((uint8_t)MAX_BUF_COUNT); idx++)
1649     {
1650 #if defined (__ARMCC_VERSION)
1651         printf("idx %d, bufType 0x%x, bufLen %d, bufPtr 0x%x\n",idx, contextPtr->buffPool[idx].bufType,contextPtr->buffPool[idx].bufLen, (uint32_t)(contextPtr->buffPool[idx].bufPtr));
1652 #else
1653     printf("idx %d, bufType 0x%x, bufLen %d, bufPtr %p\n",idx, contextPtr->buffPool[idx].bufType,contextPtr->buffPool[idx].bufLen, contextPtr->buffPool[idx].bufPtr);
1654 #endif
1655     }
1656 
1657     printf("\nFIFO content\n");
1658     for (idx = 0; idx < MAX_IPC_FIFO_SIZE; idx++)
1659     {
1660 #if defined (__ARMCC_VERSION)
1661         printf("idx %d, msg[0] 0x%x, msg[1] 0x%x\n",idx, contextPtr->IpcFifo.fifo[idx].msg[0], contextPtr->IpcFifo.fifo[idx].msg[1]);
1662 #else
1663         printf("idx %d, msg[0] 0x%lx, msg[1] 0x%lx\n",idx, contextPtr->IpcFifo.fifo[idx].msg[0], contextPtr->IpcFifo.fifo[idx].msg[1]);
1664 #endif
1665     }
1666     printf("rdIdx %d, wrIdx %d, bufLen %d\n",contextPtr->IpcFifo.rdIdx, contextPtr->IpcFifo.wrIdx, contextPtr->IpcFifo.bufLen);
1667 
1668     printf("\nCallbacks registered\n");
1669     for (idx = 0; idx < MAX_BT_IPC_HPC_CB; idx++)
1670     {
1671 #if defined (__ARMCC_VERSION)
1672         printf("idx %d, hpcNotifyCallbackPtr 0x%x, msgType %d\n", idx,
1673                 (uint32_t)(contextPtr->hpcNotifyCallbackParam[idx].hpcNotifyCallbackPtr),
1674                 contextPtr->hpcNotifyCallbackParam[idx].msgType);
1675 #else
1676     printf("idx %d, hpcNotifyCallbackPtr %p, msgType %d\n", idx,
1677             contextPtr->hpcNotifyCallbackParam[idx].hpcNotifyCallbackPtr,
1678             contextPtr->hpcNotifyCallbackParam[idx].msgType);
1679 #endif
1680     }
1681 
1682     Cy_SysLib_ExitCriticalSection(interruptState);
1683     return CY_BT_IPC_DRV_SUCCESS;
1684 }
1685 #endif
1686 CY_MISRA_BLOCK_END('ARRAY_VS_SINGLETON')
1687 #endif
1688