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 38tNFA_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*******************************************************************************/ 51void 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*******************************************************************************/ 72void 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*******************************************************************************/ 107void 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*******************************************************************************/ 126void 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*******************************************************************************/ 155void 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*******************************************************************************/ 190void 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*******************************************************************************/ 221BOOLEAN 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*******************************************************************************/ 237BOOLEAN 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*******************************************************************************/ 251void 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*******************************************************************************/ 285void 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*******************************************************************************/ 328void 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*******************************************************************************/ 357void 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*******************************************************************************/ 372void 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*******************************************************************************/ 386void 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*******************************************************************************/ 401void 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*******************************************************************************/ 415void nfa_sys_set_trace_level (UINT8 level) 416{ 417 nfa_sys_cb.trace_level = level; 418} 419