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