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 33 using android::base::StringPrintf; 34 35 extern 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 */ 43 tNFA_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 *******************************************************************************/ 56 void 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 *******************************************************************************/ 73 void 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 *******************************************************************************/ 104 void 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 *******************************************************************************/ 121 void 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 *******************************************************************************/ 147 void 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 *******************************************************************************/ 177 void 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 *******************************************************************************/ 209 bool 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 *******************************************************************************/ 222 bool 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 *******************************************************************************/ 233 void 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 *******************************************************************************/ 263 void 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 *******************************************************************************/ 302 void 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 *******************************************************************************/ 329 void 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 *******************************************************************************/ 343 void 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 *******************************************************************************/ 357 void 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 *******************************************************************************/ 370 void nfa_sys_disable_timers(void) { nfa_sys_cb.timers_disabled = true; } 371