1 /*******************************************************************************
2 * \file cybt_platform_main.c
3 *
4 * \brief
5 * This file provides functions for WICED BT stack initialization.
6 *
7 ********************************************************************************
8 * \copyright
9 * Copyright 2018-2019 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24
25 #include "wiced_bt_dev.h"
26 #include "wiced_bt_cfg.h"
27 #include "wiced_bt_stack_platform.h"
28 #include "wiced_bt_stack.h"
29 #include "wiced_bt_gatt.h"
30
31 #include "cybt_platform_task.h"
32 #include "cybt_platform_trace.h"
33 #include "cybt_platform_config.h"
34 #include "cybt_platform_interface.h"
35 #include "cybt_platform_util.h"
36 #include "cybt_platform_internal.h"
37
38 /******************************************************************************
39 * Constants
40 ******************************************************************************/
41 #define HCI_VSC_WRITE_SLEEP_MODE (0xFC27)
42 #define HCI_VSC_WRITE_SLEEP_MODE_LENGTH (12)
43
44 #define BT_SLEEP_MODE_ENABLE (1)
45 #define BT_SLEEP_THRESHOLD_HOST (1)
46 #define BT_SLEEP_THRESHOLD_HOST_CONTROLLER (1)
47 #define BT_SLEEP_ALLOW_HOST_SLEEP_DURING_SCO (1)
48 #define BT_SLEEP_COMBINE_SLEEP_MODE_AND_LPM (1)
49 #define BT_SLEEP_ENABLE_UART_TXD_TRISTATE (0)
50 #define BT_SLEEP_PULSED_HOST_WAKE (0)
51 #define BT_SLEEP_SLEEP_GUARD_TIME (0)
52 #define BT_SLEEP_WAKEUP_GUARD_TIME (0)
53 #define BT_SLEEP_TXD_CONFIG (1)
54 #define BT_SLEEP_BT_WAKE_IDLE_TIME (50)
55
56 #define HCI_EVT_COREDUMPTYPE_END (0xFF) // Value for 'Core Dump End'
57 #define HCI_EVT_COREDUMPTYPE_INDEX (6) // Index for CoreDumpType
58
59 #ifdef RESET_LOCAL_SUPPORT_FEATURE
60 #define CONNECTION_PARAMETER_REQUEST_PROCEDURE (1) // Feature bit position for Connection Parameters Request Procedure
61 #endif
62
63 /*****************************************************************************
64 * Type Definitions
65 *****************************************************************************/
66 typedef struct
67 {
68 wiced_bt_management_cback_t *p_app_management_callback;
69 const cybt_platform_config_t *p_bt_platform_cfg;
70 bool is_sleep_mode_enabled;
71 } cybt_platform_main_cb_t;
72
73 /******************************************************************************
74 * Variables Definitions
75 ******************************************************************************/
76 cybt_platform_main_cb_t cybt_main_cb = {0};
77
78
79 /******************************************************************************
80 * Function Declarations
81 ******************************************************************************/
82 extern void host_stack_platform_interface_init(void);
83 #ifdef ENABLE_DEBUG_UART
84 extern cybt_result_t cybt_send_coredump_hci_trace (uint16_t data_size, uint8_t *p_data);
85 #endif
86
87 #ifdef RESET_LOCAL_SUPPORT_FEATURE
88 extern void wiced_bt_btm_ble_reset_local_supported_features(uint32_t feature);
89 #endif
90
91 wiced_result_t cybt_core_management_cback( wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t *p_event_data );
92 /******************************************************************************
93 * Function Definitions
94 ******************************************************************************/
bt_sleep_status_cback(wiced_bt_dev_vendor_specific_command_complete_params_t * p_command_complete_params)95 void bt_sleep_status_cback (wiced_bt_dev_vendor_specific_command_complete_params_t *p_command_complete_params)
96 {
97 MAIN_TRACE_DEBUG("bt_sleep_status_cback(): status = 0x%x",
98 p_command_complete_params->p_param_buf[0]
99 );
100
101 if(HCI_SUCCESS == p_command_complete_params->p_param_buf[0])
102 {
103 cybt_main_cb.is_sleep_mode_enabled = true;
104 }
105 else
106 {
107 cybt_main_cb.is_sleep_mode_enabled = false;
108 }
109 }
110
bt_enable_sleep_mode(void)111 bool bt_enable_sleep_mode(void)
112 {
113 wiced_result_t result;
114 uint8_t sleep_vsc[HCI_VSC_WRITE_SLEEP_MODE_LENGTH] = { 0 };
115 const cybt_platform_config_t *p_bt_platform_cfg = cybt_platform_get_config();
116
117 MAIN_TRACE_DEBUG("bt_enable_sleep_mode()");
118
119 if( CYBT_HCI_UART == p_bt_platform_cfg->hci_config.hci_transport )
120 {
121 sleep_vsc[0] = BT_SLEEP_MODE_ENABLE;
122 sleep_vsc[1] = BT_SLEEP_THRESHOLD_HOST;
123 sleep_vsc[2] = BT_SLEEP_THRESHOLD_HOST_CONTROLLER;
124 sleep_vsc[3] = cybt_main_cb.p_bt_platform_cfg->controller_config.sleep_mode.device_wake_polarity;
125 sleep_vsc[4] = cybt_main_cb.p_bt_platform_cfg->controller_config.sleep_mode.host_wake_polarity;
126 sleep_vsc[5] = BT_SLEEP_ALLOW_HOST_SLEEP_DURING_SCO;
127 sleep_vsc[6] = BT_SLEEP_COMBINE_SLEEP_MODE_AND_LPM;
128 sleep_vsc[7] = BT_SLEEP_ENABLE_UART_TXD_TRISTATE;
129 sleep_vsc[8] = 0;
130 sleep_vsc[9] = 0;
131 sleep_vsc[10] = 0;
132 sleep_vsc[11] = BT_SLEEP_PULSED_HOST_WAKE;
133 }
134 else
135 {
136 memset(sleep_vsc, 0, sizeof(sleep_vsc));
137 sleep_vsc[0] = BT_SLEEP_MODE_ENABLE;
138 }
139
140 result = wiced_bt_dev_vendor_specific_command(HCI_VSC_WRITE_SLEEP_MODE,
141 HCI_VSC_WRITE_SLEEP_MODE_LENGTH,
142 sleep_vsc,
143 bt_sleep_status_cback
144 );
145 if(WICED_BT_PENDING != result)
146 {
147 MAIN_TRACE_DEBUG("bt_enable_sleep_mode(): Fail to send vsc (0x%x)", result);
148 return false;
149 }
150
151 return true;
152 }
153
154 /*
155 * On stack initalization complete this call back gets called
156 */
wiced_post_stack_init_cback(void)157 void wiced_post_stack_init_cback( void )
158 {
159 wiced_bt_management_evt_data_t event_data;
160 const cybt_platform_config_t *p_bt_platform_cfg = cybt_platform_get_config();
161 cybt_controller_sleep_config_t *p_sleep_config =
162 &(((cybt_platform_config_t *)cybt_main_cb.p_bt_platform_cfg)->controller_config.sleep_mode);
163
164 MAIN_TRACE_DEBUG("wiced_post_stack_init_cback");
165
166 memset(&event_data, 0, sizeof(wiced_bt_management_evt_t));
167 event_data.enabled.status = WICED_BT_SUCCESS;
168
169 cybt_core_management_cback(BTM_ENABLED_EVT, &event_data);
170 #ifdef RESET_LOCAL_SUPPORT_FEATURE
171 wiced_bt_btm_ble_reset_local_supported_features(CONNECTION_PARAMETER_REQUEST_PROCEDURE);
172 #endif
173
174 if(CYBT_SLEEP_MODE_ENABLED == p_sleep_config->sleep_mode_enabled)
175 {
176 bool status = false;
177 if( CYBT_HCI_UART == p_bt_platform_cfg->hci_config.hci_transport )
178 {
179 if((NC != p_sleep_config->device_wakeup_pin) && (NC != p_sleep_config->host_wakeup_pin))
180
181 {
182 status = ENABLE_SLEEP_MODE();
183 }
184 else
185 {
186 MAIN_TRACE_ERROR("wiced_post_stack_init_cback(): BT sleep mode is NOT enabled");
187 return;
188 }
189 }
190 else
191 {
192 status = ENABLE_SLEEP_MODE();
193 }
194
195 if(false == status)
196 {
197 MAIN_TRACE_ERROR("wiced_post_stack_init_cback(): Fail to init sleep mode");
198 }
199 }
200 else
201 {
202 MAIN_TRACE_ERROR("wiced_post_stack_init_cback(): BT sleep mode is NOT enabled");
203 }
204 }
205
206 /*
207 * This call back gets called for each HCI event.
208 */
wiced_stack_event_handler_cback(uint8_t * p_event)209 wiced_bool_t wiced_stack_event_handler_cback (uint8_t *p_event)
210 {
211 return WICED_FALSE;
212 }
213
214
215
216 #if (defined(BTSTACK_VER) && (BTSTACK_VER >= 0x03070000))
init_layers(void)217 static wiced_result_t init_layers(void)
218 {
219 /* handle in porting layer */
220 return wiced_bt_smp_module_init();
221 }
222
223 #if (defined(__GNUC__) || defined(__ARMCC_VERSION))
app_initialize_btstack_modules(void)224 extern __attribute__((weak)) wiced_result_t app_initialize_btstack_modules(void)
225 {
226 return init_layers();
227 }
228 #endif
229
230 #if defined(__ICCARM__)
231 extern wiced_result_t app_initialize_btstack_modules(void);
232 #pragma weak app_initialize_btstack_modules=init_layers
233
234 #endif
235 #endif // BTSTACK_VER
236
cybt_core_management_cback(wiced_bt_management_evt_t event,wiced_bt_management_evt_data_t * p_event_data)237 wiced_result_t cybt_core_management_cback( wiced_bt_management_evt_t event, wiced_bt_management_evt_data_t *p_event_data )
238 {
239 wiced_result_t result = WICED_BT_SUCCESS;
240 int send_to_app = 1;
241
242 #if (defined(BTSTACK_VER) && (BTSTACK_VER >= 0x03070000))
243 switch(event)
244 {
245 case BTM_ENABLED_EVT:
246 #ifndef DISABLE_DEFAULT_BTSTACK_INIT
247 app_initialize_btstack_modules();
248 #endif
249
250 wiced_bt_init_resolution(); /* to be removed subsequently. only required for non-privacy controllers */
251 break;
252 }
253 #endif // BTSTACK_VER
254
255 if(send_to_app && cybt_main_cb.p_app_management_callback)
256 {
257 result = cybt_main_cb.p_app_management_callback(event, p_event_data);
258 }
259
260 return result;
261 }
262
cybt_core_stack_init(void)263 void cybt_core_stack_init(void)
264 {
265 /* Start the stack */
266 wiced_bt_stack_init_internal(cybt_core_management_cback,
267 wiced_post_stack_init_cback,
268 wiced_stack_event_handler_cback
269 );
270 }
271
wiced_bt_stack_init(wiced_bt_management_cback_t * p_bt_management_cback,const wiced_bt_cfg_settings_t * p_bt_cfg_settings)272 wiced_result_t wiced_bt_stack_init(wiced_bt_management_cback_t *p_bt_management_cback,
273 const wiced_bt_cfg_settings_t *p_bt_cfg_settings
274 )
275 {
276 MAIN_TRACE_DEBUG("wiced_bt_stack_init()");
277
278 cybt_main_cb.is_sleep_mode_enabled = false;
279
280 cybt_platform_init();
281
282 cybt_main_cb.p_app_management_callback = p_bt_management_cback;
283
284 host_stack_platform_interface_init();
285
286 /* Configure the stack */
287 if (0 == wiced_bt_set_stack_config(p_bt_cfg_settings))
288 {
289 MAIN_TRACE_ERROR("wiced_bt_set_stack_config(): Failed\n");
290 }
291
292 cybt_platform_task_init((void *)p_bt_cfg_settings);
293
294 return WICED_BT_SUCCESS;
295 }
296
wiced_bt_stack_deinit(void)297 wiced_result_t wiced_bt_stack_deinit( void )
298 {
299 cybt_platform_task_deinit();
300
301 cybt_platform_deinit();
302
303 return WICED_BT_SUCCESS;
304 }
305
cybt_platform_config_init(const cybt_platform_config_t * p_bt_platform_cfg)306 void cybt_platform_config_init(const cybt_platform_config_t *p_bt_platform_cfg)
307 {
308 MAIN_TRACE_DEBUG("cybt_platform_config_init()");
309
310 cybt_main_cb.p_bt_platform_cfg = p_bt_platform_cfg;
311 }
312
cybt_platform_get_sleep_mode_status(void)313 bool cybt_platform_get_sleep_mode_status(void)
314 {
315 return cybt_main_cb.is_sleep_mode_enabled;
316 }
317
cybt_platform_get_config(void)318 const cybt_platform_config_t* cybt_platform_get_config(void)
319 {
320 return cybt_main_cb.p_bt_platform_cfg;
321 }
322
trace_exception(cybt_exception_t error,uint8_t * info,uint32_t length)323 static void trace_exception(cybt_exception_t error, uint8_t *info, uint32_t length)
324 {
325 switch (error)
326 {
327 case CYBT_HCI_IPC_REL_BUFFER:
328 MAIN_TRACE_ERROR("Exception: case: IPC release buffer failed, reason:0x%x", *(uint32_t *)info);
329 break;
330 case CYBT_CONTROLLER_RESTARTED:
331 MAIN_TRACE_ERROR("Exception: case: BT restarted again");
332 break;
333 case CYBT_CONTROLLER_CORE_DUMP:
334 MAIN_TRACE_ERROR("Exception: case: %x [CoreDump], len:%d reason:0x%x", error, length, *(uint32_t *)info);
335
336 #ifdef ENABLE_DEBUG_UART
337 cybt_send_coredump_hci_trace(length, &info[0]);
338 #else
339 for (uint32_t i = 0; i < length; i++)
340 {
341 MAIN_TRACE_ERROR("%x ", *(uint8_t *)(info + i));
342 }
343 #endif
344
345 if(HCI_EVT_COREDUMPTYPE_END == *(uint8_t *)(info + HCI_EVT_COREDUMPTYPE_INDEX))
346 {
347 MAIN_TRACE_ERROR("End of CoreDump. Going to Assert ");
348 cy_rtos_delay_milliseconds(10);
349 CY_ASSERT(0);
350 }
351 break;
352 default:
353 MAIN_TRACE_ERROR("Exception: case: %x [unknown]", error);
354 break;
355 }
356 }
357
cybt_platform_exception_handler(cybt_exception_t error,uint8_t * info,uint32_t length)358 void cybt_platform_exception_handler(cybt_exception_t error, uint8_t *info, uint32_t length)
359 {
360 trace_exception(error, info, length);
361
362 #if 0 // Todo: register handler from app then enable this code
363 /* If app callback is not registered on exception, trigger assert */
364 if ( NULL == exception_cb )
365 {
366 CY_ASSERT(0);
367 }
368
369 /* If app not handled on exception, trigger assert */
370 if( false == exception_cb(error, info, length) )
371 {
372 CY_ASSERT(0);
373 }
374 #else
375 /* We might get more core dump packets. Do not assert from here. */
376 if(CYBT_CONTROLLER_CORE_DUMP != error)
377 CY_ASSERT(0);
378 #endif
379 return;
380 }
381
382