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