1/****************************************************************************** 2 * 3 * Copyright (C) 2010-2013 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 39tNFA_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*******************************************************************************/ 52void 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*******************************************************************************/ 73void 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*******************************************************************************/ 108void 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*******************************************************************************/ 127void 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*******************************************************************************/ 156void 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*******************************************************************************/ 191void 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*******************************************************************************/ 222BOOLEAN 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*******************************************************************************/ 238BOOLEAN 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*******************************************************************************/ 252void 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*******************************************************************************/ 286void 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*******************************************************************************/ 329void 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*******************************************************************************/ 358void 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*******************************************************************************/ 373void 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*******************************************************************************/ 387void 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*******************************************************************************/ 402void 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*******************************************************************************/ 416void nfa_sys_set_trace_level (UINT8 level) 417{ 418 nfa_sys_cb.trace_level = level; 419} 420