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