1 /****************************************************************************** 2 * 3 * Copyright (C) 2010-2014 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 20 /****************************************************************************** 21 * 22 * This is the main implementation file for the NFA system manager. 23 * 24 ******************************************************************************/ 25 #include <string.h> 26 #include "nfa_api.h" 27 #include "nfa_sys.h" 28 #include "nfa_sys_int.h" 29 #include "nfa_sys_ptim.h" 30 #include "nfa_dm_int.h" 31 32 /* protocol timer update period, in milliseconds */ 33 #ifndef NFA_SYS_TIMER_PERIOD 34 #define NFA_SYS_TIMER_PERIOD 10 35 #endif 36 37 /* system manager control block definition */ 38 #if NFA_DYNAMIC_MEMORY == FALSE 39 tNFA_SYS_CB nfa_sys_cb = {0}; /* nfa_sys control block. statically initialize 'flags' field to 0 */ 40 #endif 41 42 /******************************************************************************* 43 ** 44 ** Function nfa_sys_init 45 ** 46 ** Description NFA initialization; called from task initialization. 47 ** 48 ** 49 ** Returns void 50 ** 51 *******************************************************************************/ 52 void nfa_sys_init (void) 53 { 54 memset (&nfa_sys_cb, 0, sizeof (tNFA_SYS_CB)); 55 nfa_sys_cb.flags |= NFA_SYS_FL_INITIALIZED; 56 nfa_sys_ptim_init (&nfa_sys_cb.ptim_cb, NFA_SYS_TIMER_PERIOD, p_nfa_sys_cfg->timer); 57 nfa_sys_cb.trace_level = p_nfa_sys_cfg->trace_level; 58 } 59 60 61 62 63 /******************************************************************************* 64 ** 65 ** Function nfa_sys_event 66 ** 67 ** Description BTA event handler; called from task event handler. 68 ** 69 ** 70 ** Returns void 71 ** 72 *******************************************************************************/ 73 void nfa_sys_event (BT_HDR *p_msg) 74 { 75 UINT8 id; 76 BOOLEAN freebuf = TRUE; 77 78 NFA_TRACE_EVENT1 ("NFA got event 0x%04X", p_msg->event); 79 80 /* get subsystem id from event */ 81 id = (UINT8) (p_msg->event >> 8); 82 83 /* verify id and call subsystem event handler */ 84 if ((id < NFA_ID_MAX) && (nfa_sys_cb.is_reg[id])) 85 { 86 freebuf = (*nfa_sys_cb.reg[id]->evt_hdlr) (p_msg); 87 } 88 else 89 { 90 NFA_TRACE_WARNING1 ("NFA got unregistered event id %d", id); 91 } 92 93 if (freebuf) 94 { 95 GKI_freebuf (p_msg); 96 } 97 } 98 99 /******************************************************************************* 100 ** 101 ** Function nfa_sys_timer_update 102 ** 103 ** Description Update the BTA timer list and handle expired timers. 104 ** 105 ** Returns void 106 ** 107 *******************************************************************************/ 108 void nfa_sys_timer_update (void) 109 { 110 if (!nfa_sys_cb.timers_disabled) 111 { 112 nfa_sys_ptim_timer_update (&nfa_sys_cb.ptim_cb); 113 } 114 } 115 116 /******************************************************************************* 117 ** 118 ** Function nfa_sys_register 119 ** 120 ** Description Called by other BTA subsystems to register their event 121 ** handler. 122 ** 123 ** 124 ** Returns void 125 ** 126 *******************************************************************************/ 127 void nfa_sys_register (UINT8 id, const tNFA_SYS_REG *p_reg) 128 { 129 nfa_sys_cb.reg[id] = (tNFA_SYS_REG *) p_reg; 130 nfa_sys_cb.is_reg[id] = TRUE; 131 132 if ((id != NFA_ID_DM) && (id != NFA_ID_SYS)) 133 nfa_sys_cb.enable_cplt_mask |= (0x0001 << id); 134 135 if (id != NFA_ID_SYS) 136 { 137 if (p_reg->proc_nfcc_pwr_mode) 138 nfa_sys_cb.proc_nfcc_pwr_mode_cplt_mask |= (0x0001 << id); 139 } 140 141 NFA_TRACE_DEBUG2 ("nfa_sys_register () id=%i, enable_cplt_mask=0x%x", 142 id, nfa_sys_cb.enable_cplt_mask); 143 } 144 145 146 /******************************************************************************* 147 ** 148 ** Function nfa_sys_check_disabled 149 ** 150 ** Description If all subsystems above DM have been disabled, then 151 ** disable DM. Called during NFA shutdown 152 ** 153 ** Returns void 154 ** 155 *******************************************************************************/ 156 void nfa_sys_check_disabled (void) 157 { 158 UINT8 id; 159 UINT8 done = TRUE; 160 161 /* Check if all subsystems above DM have been disabled. */ 162 for (id = (NFA_ID_DM+1); id < NFA_ID_MAX; id++) 163 { 164 if (nfa_sys_cb.is_reg[id]) 165 { 166 /* as long as one subsystem is not done */ 167 done = FALSE; 168 break; 169 } 170 } 171 172 /* All subsystems disabled. disable DM */ 173 if ((done) && (nfa_sys_cb.is_reg[NFA_ID_DM])) 174 { 175 (*nfa_sys_cb.reg[NFA_ID_DM]->disable) (); 176 } 177 } 178 179 180 /******************************************************************************* 181 ** 182 ** Function nfa_sys_deregister 183 ** 184 ** Description Called by other BTA subsystems to de-register 185 ** handler. 186 ** 187 ** 188 ** Returns void 189 ** 190 *******************************************************************************/ 191 void nfa_sys_deregister (UINT8 id) 192 { 193 NFA_TRACE_DEBUG1 ("nfa_sys: deregistering subsystem %i", id); 194 195 nfa_sys_cb.is_reg[id] = FALSE; 196 197 /* If not deregistering DM, then check if any other subsystems above DM are still */ 198 /* registered. */ 199 if (id != NFA_ID_DM) 200 { 201 /* If all subsystems above NFA_DM have been disabled, then okay to disable DM */ 202 nfa_sys_check_disabled (); 203 } 204 else 205 { 206 /* DM (the final sub-system) is deregistering. Clear pending timer events in nfa_sys. */ 207 nfa_sys_ptim_init (&nfa_sys_cb.ptim_cb, NFA_SYS_TIMER_PERIOD, p_nfa_sys_cfg->timer); 208 } 209 } 210 211 /******************************************************************************* 212 ** 213 ** Function nfa_sys_is_register 214 ** 215 ** Description Called by other BTA subsystems to get registeration 216 ** status. 217 ** 218 ** 219 ** Returns void 220 ** 221 *******************************************************************************/ 222 BOOLEAN nfa_sys_is_register (UINT8 id) 223 { 224 return nfa_sys_cb.is_reg[id]; 225 } 226 227 /******************************************************************************* 228 ** 229 ** Function nfa_sys_is_graceful_disable 230 ** 231 ** Description Called by other BTA subsystems to get disable 232 ** parameter. 233 ** 234 ** 235 ** Returns void 236 ** 237 *******************************************************************************/ 238 BOOLEAN nfa_sys_is_graceful_disable (void) 239 { 240 return nfa_sys_cb.graceful_disable; 241 } 242 243 /******************************************************************************* 244 ** 245 ** Function nfa_sys_enable_subsystems 246 ** 247 ** Description Call on NFA Start up 248 ** 249 ** Returns void 250 ** 251 *******************************************************************************/ 252 void nfa_sys_enable_subsystems (void) 253 { 254 UINT8 id; 255 256 NFA_TRACE_DEBUG0 ("nfa_sys: enabling subsystems"); 257 258 /* Enable all subsystems except SYS */ 259 for (id = NFA_ID_DM; id < NFA_ID_MAX; id++) 260 { 261 if (nfa_sys_cb.is_reg[id]) 262 { 263 if (nfa_sys_cb.reg[id]->enable != NULL) 264 { 265 /* Subsytem has a Disable funciton. Call it now */ 266 (*nfa_sys_cb.reg[id]->enable) (); 267 } 268 else 269 { 270 /* Subsytem does not have a Enable function. Report Enable on behalf of subsystem */ 271 nfa_sys_cback_notify_enable_complete (id); 272 } 273 } 274 } 275 } 276 277 /******************************************************************************* 278 ** 279 ** Function nfa_sys_disable_subsystems 280 ** 281 ** Description Call on NFA shutdown. Disable all subsystems above NFA_DM 282 ** 283 ** Returns void 284 ** 285 *******************************************************************************/ 286 void nfa_sys_disable_subsystems (BOOLEAN graceful) 287 { 288 UINT8 id; 289 BOOLEAN done = TRUE; 290 291 NFA_TRACE_DEBUG1 ("nfa_sys: disabling subsystems:%d", graceful); 292 nfa_sys_cb.graceful_disable = graceful; 293 294 /* Disable all subsystems above NFA_DM. (NFA_DM and NFA_SYS will be disabled last) */ 295 for (id = (NFA_ID_DM+1); id < NFA_ID_MAX; id++) 296 { 297 if (nfa_sys_cb.is_reg[id]) 298 { 299 done = FALSE; 300 if (nfa_sys_cb.reg[id]->disable != NULL) 301 { 302 /* Subsytem has a Disable funciton. Call it now */ 303 (*nfa_sys_cb.reg[id]->disable) (); 304 } 305 else 306 { 307 /* Subsytem does not have a Disable function. Deregister on behalf of subsystem */ 308 nfa_sys_deregister (id); 309 } 310 } 311 } 312 313 /* If All subsystems disabled. disable DM */ 314 if ((done) && (nfa_sys_cb.is_reg[NFA_ID_DM])) 315 { 316 (*nfa_sys_cb.reg[NFA_ID_DM]->disable) (); 317 } 318 } 319 320 /******************************************************************************* 321 ** 322 ** Function nfa_sys_notify_nfcc_power_mode 323 ** 324 ** Description Call to notify NFCC power mode to NFA sub-modules 325 ** 326 ** Returns void 327 ** 328 *******************************************************************************/ 329 void nfa_sys_notify_nfcc_power_mode (UINT8 nfcc_power_mode) 330 { 331 UINT8 id; 332 333 NFA_TRACE_DEBUG1 ("nfa_sys: notify NFCC power mode(%d) to subsystems", nfcc_power_mode); 334 335 /* Notify NFCC power state to all subsystems except NFA_SYS */ 336 for (id = NFA_ID_DM; id < NFA_ID_MAX; id++) 337 { 338 if ((nfa_sys_cb.is_reg[id]) && (nfa_sys_cb.reg[id]->proc_nfcc_pwr_mode)) 339 { 340 /* Subsytem has a funciton for processing NFCC power mode. Call it now */ 341 (*nfa_sys_cb.reg[id]->proc_nfcc_pwr_mode) (nfcc_power_mode); 342 } 343 } 344 } 345 346 /******************************************************************************* 347 ** 348 ** Function nfa_sys_sendmsg 349 ** 350 ** Description Send a GKI message to BTA. This function is designed to 351 ** optimize sending of messages to BTA. It is called by BTA 352 ** API functions and call-in functions. 353 ** 354 ** 355 ** Returns void 356 ** 357 *******************************************************************************/ 358 void nfa_sys_sendmsg (void *p_msg) 359 { 360 GKI_send_msg (NFC_TASK, p_nfa_sys_cfg->mbox, p_msg); 361 } 362 363 /******************************************************************************* 364 ** 365 ** Function nfa_sys_start_timer 366 ** 367 ** Description Start a protocol timer for the specified amount 368 ** of time in milliseconds. 369 ** 370 ** Returns void 371 ** 372 *******************************************************************************/ 373 void nfa_sys_start_timer (TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout) 374 { 375 nfa_sys_ptim_start_timer (&nfa_sys_cb.ptim_cb, p_tle, type, timeout); 376 } 377 378 /******************************************************************************* 379 ** 380 ** Function nfa_sys_stop_timer 381 ** 382 ** Description Stop a BTA timer. 383 ** 384 ** Returns void 385 ** 386 *******************************************************************************/ 387 void nfa_sys_stop_timer (TIMER_LIST_ENT *p_tle) 388 { 389 nfa_sys_ptim_stop_timer (&nfa_sys_cb.ptim_cb, p_tle); 390 } 391 392 393 /******************************************************************************* 394 ** 395 ** Function nfa_sys_disable_timers 396 ** 397 ** Description Disable sys timer event handling 398 ** 399 ** Returns void 400 ** 401 *******************************************************************************/ 402 void nfa_sys_disable_timers (void) 403 { 404 nfa_sys_cb.timers_disabled = TRUE; 405 } 406 407 /******************************************************************************* 408 ** 409 ** Function nfa_sys_set_trace_level 410 ** 411 ** Description Set trace level for BTA 412 ** 413 ** Returns void 414 ** 415 *******************************************************************************/ 416 void nfa_sys_set_trace_level (UINT8 level) 417 { 418 nfa_sys_cb.trace_level = level; 419 } 420