Home | History | Annotate | Download | only in nfc
      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  *  Entry point for NFC_TASK
     22  *
     23  ******************************************************************************/
     24 #include <string.h>
     25 
     26 #include <android-base/stringprintf.h>
     27 #include <base/logging.h>
     28 
     29 #include "nfc_target.h"
     30 
     31 #include "bt_types.h"
     32 #include "ce_int.h"
     33 #include "gki.h"
     34 #include "nci_hmsgs.h"
     35 #include "nfc_int.h"
     36 #include "rw_int.h"
     37 #if (NFC_RW_ONLY == FALSE)
     38 #include "llcp_int.h"
     39 #else
     40 #define llcp_cleanup()
     41 #endif
     42 
     43 #include "nfa_dm_int.h"
     44 
     45 using android::base::StringPrintf;
     46 
     47 extern bool nfc_debug_enabled;
     48 
     49 /*******************************************************************************
     50 **
     51 ** Function         nfc_start_timer
     52 **
     53 ** Description      Start a timer for the specified amount of time.
     54 **                  NOTE: The timeout resolution is in SECONDS! (Even
     55 **                          though the timer structure field is ticks)
     56 **
     57 ** Returns          void
     58 **
     59 *******************************************************************************/
     60 void nfc_start_timer(TIMER_LIST_ENT* p_tle, uint16_t type, uint32_t timeout) {
     61   NFC_HDR* p_msg;
     62 
     63   /* if timer list is currently empty, start periodic GKI timer */
     64   if (nfc_cb.timer_queue.p_first == NULL) {
     65     /* if timer starts on other than NFC task (scritp wrapper) */
     66     if (GKI_get_taskid() != NFC_TASK) {
     67       /* post event to start timer in NFC task */
     68       p_msg = (NFC_HDR*)GKI_getbuf(NFC_HDR_SIZE);
     69       if (p_msg != NULL) {
     70         p_msg->event = BT_EVT_TO_START_TIMER;
     71         GKI_send_msg(NFC_TASK, NFC_MBOX_ID, p_msg);
     72       }
     73     } else {
     74       /* Start nfc_task 1-sec resolution timer */
     75       GKI_start_timer(NFC_TIMER_ID, GKI_SECS_TO_TICKS(1), true);
     76     }
     77   }
     78 
     79   GKI_remove_from_timer_list(&nfc_cb.timer_queue, p_tle);
     80 
     81   p_tle->event = type;
     82   p_tle->ticks = timeout; /* Save the number of seconds for the timer */
     83 
     84   GKI_add_to_timer_list(&nfc_cb.timer_queue, p_tle);
     85 }
     86 
     87 /*******************************************************************************
     88 **
     89 ** Function         nfc_remaining_time
     90 **
     91 ** Description      Return amount of time to expire
     92 **
     93 ** Returns          time in second
     94 **
     95 *******************************************************************************/
     96 uint32_t nfc_remaining_time(TIMER_LIST_ENT* p_tle) {
     97   return (GKI_get_remaining_ticks(&nfc_cb.timer_queue, p_tle));
     98 }
     99 
    100 /*******************************************************************************
    101 **
    102 ** Function         nfc_process_timer_evt
    103 **
    104 ** Description      Process nfc GKI timer event
    105 **
    106 ** Returns          void
    107 **
    108 *******************************************************************************/
    109 void nfc_process_timer_evt(void) {
    110   TIMER_LIST_ENT* p_tle;
    111 
    112   GKI_update_timer_list(&nfc_cb.timer_queue, 1);
    113 
    114   while ((nfc_cb.timer_queue.p_first) && (!nfc_cb.timer_queue.p_first->ticks)) {
    115     p_tle = nfc_cb.timer_queue.p_first;
    116     GKI_remove_from_timer_list(&nfc_cb.timer_queue, p_tle);
    117 
    118     switch (p_tle->event) {
    119       case NFC_TTYPE_NCI_WAIT_RSP:
    120         nfc_ncif_cmd_timeout();
    121         break;
    122 
    123       case NFC_TTYPE_WAIT_2_DEACTIVATE:
    124         nfc_wait_2_deactivate_timeout();
    125         break;
    126       case NFC_TTYPE_WAIT_MODE_SET_NTF:
    127         nfc_mode_set_ntf_timeout();
    128         break;
    129       default:
    130         DLOG_IF(INFO, nfc_debug_enabled)
    131             << StringPrintf("nfc_process_timer_evt: timer:0x%p event (0x%04x)",
    132                             p_tle, p_tle->event);
    133         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    134             "nfc_process_timer_evt: unhandled timer event (0x%04x)",
    135             p_tle->event);
    136     }
    137   }
    138 
    139   /* if timer list is empty stop periodic GKI timer */
    140   if (nfc_cb.timer_queue.p_first == NULL) {
    141     GKI_stop_timer(NFC_TIMER_ID);
    142   }
    143 }
    144 
    145 /*******************************************************************************
    146 **
    147 ** Function         nfc_stop_timer
    148 **
    149 ** Description      Stop a timer.
    150 **
    151 ** Returns          void
    152 **
    153 *******************************************************************************/
    154 void nfc_stop_timer(TIMER_LIST_ENT* p_tle) {
    155   GKI_remove_from_timer_list(&nfc_cb.timer_queue, p_tle);
    156 
    157   /* if timer list is empty stop periodic GKI timer */
    158   if (nfc_cb.timer_queue.p_first == NULL) {
    159     GKI_stop_timer(NFC_TIMER_ID);
    160   }
    161 }
    162 
    163 /*******************************************************************************
    164 **
    165 ** Function         nfc_start_quick_timer
    166 **
    167 ** Description      Start a timer for the specified amount of time.
    168 **                  NOTE: The timeout resolution depends on including modules.
    169 **                  QUICK_TIMER_TICKS_PER_SEC should be used to convert from
    170 **                  time to ticks.
    171 **
    172 **
    173 ** Returns          void
    174 **
    175 *******************************************************************************/
    176 void nfc_start_quick_timer(TIMER_LIST_ENT* p_tle, uint16_t type,
    177                            uint32_t timeout) {
    178   NFC_HDR* p_msg;
    179 
    180   /* if timer list is currently empty, start periodic GKI timer */
    181   if (nfc_cb.quick_timer_queue.p_first == NULL) {
    182     /* if timer starts on other than NFC task (scritp wrapper) */
    183     if (GKI_get_taskid() != NFC_TASK) {
    184       /* post event to start timer in NFC task */
    185       p_msg = (NFC_HDR*)GKI_getbuf(NFC_HDR_SIZE);
    186       if (p_msg != NULL) {
    187         p_msg->event = BT_EVT_TO_START_QUICK_TIMER;
    188         GKI_send_msg(NFC_TASK, NFC_MBOX_ID, p_msg);
    189       }
    190     } else {
    191       /* Quick-timer is required for LLCP */
    192       GKI_start_timer(NFC_QUICK_TIMER_ID,
    193                       ((GKI_SECS_TO_TICKS(1) / QUICK_TIMER_TICKS_PER_SEC)),
    194                       true);
    195     }
    196   }
    197 
    198   GKI_remove_from_timer_list(&nfc_cb.quick_timer_queue, p_tle);
    199 
    200   p_tle->event = type;
    201   p_tle->ticks = timeout; /* Save the number of ticks for the timer */
    202 
    203   GKI_add_to_timer_list(&nfc_cb.quick_timer_queue, p_tle);
    204 }
    205 
    206 /*******************************************************************************
    207 **
    208 ** Function         nfc_stop_quick_timer
    209 **
    210 ** Description      Stop a timer.
    211 **
    212 ** Returns          void
    213 **
    214 *******************************************************************************/
    215 void nfc_stop_quick_timer(TIMER_LIST_ENT* p_tle) {
    216   GKI_remove_from_timer_list(&nfc_cb.quick_timer_queue, p_tle);
    217 
    218   /* if timer list is empty stop periodic GKI timer */
    219   if (nfc_cb.quick_timer_queue.p_first == NULL) {
    220     GKI_stop_timer(NFC_QUICK_TIMER_ID);
    221   }
    222 }
    223 
    224 /*******************************************************************************
    225 **
    226 ** Function         nfc_process_quick_timer_evt
    227 **
    228 ** Description      Process quick timer event
    229 **
    230 ** Returns          void
    231 **
    232 *******************************************************************************/
    233 void nfc_process_quick_timer_evt(void) {
    234   TIMER_LIST_ENT* p_tle;
    235 
    236   GKI_update_timer_list(&nfc_cb.quick_timer_queue, 1);
    237 
    238   while ((nfc_cb.quick_timer_queue.p_first) &&
    239          (!nfc_cb.quick_timer_queue.p_first->ticks)) {
    240     p_tle = nfc_cb.quick_timer_queue.p_first;
    241     GKI_remove_from_timer_list(&nfc_cb.quick_timer_queue, p_tle);
    242 
    243     switch (p_tle->event) {
    244 #if (NFC_RW_ONLY == FALSE)
    245       case NFC_TTYPE_LLCP_LINK_MANAGER:
    246       case NFC_TTYPE_LLCP_LINK_INACT:
    247       case NFC_TTYPE_LLCP_DATA_LINK:
    248       case NFC_TTYPE_LLCP_DELAY_FIRST_PDU:
    249         llcp_process_timeout(p_tle);
    250         break;
    251 #endif
    252       case NFC_TTYPE_RW_T1T_RESPONSE:
    253         rw_t1t_process_timeout(p_tle);
    254         break;
    255       case NFC_TTYPE_RW_T2T_RESPONSE:
    256         rw_t2t_process_timeout();
    257         break;
    258       case NFC_TTYPE_RW_T3T_RESPONSE:
    259         rw_t3t_process_timeout(p_tle);
    260         break;
    261       case NFC_TTYPE_RW_T4T_RESPONSE:
    262         rw_t4t_process_timeout(p_tle);
    263         break;
    264       case NFC_TTYPE_RW_I93_RESPONSE:
    265         rw_i93_process_timeout(p_tle);
    266         break;
    267       case NFC_TTYPE_P2P_PRIO_RESPONSE:
    268         nfa_dm_p2p_timer_event();
    269         break;
    270       case NFC_TTYPE_P2P_PRIO_LOGIC_CLEANUP:
    271         nfa_dm_p2p_prio_logic_cleanup();
    272         break;
    273 #if (NFC_RW_ONLY == FALSE)
    274       case NFC_TTYPE_CE_T4T_UPDATE:
    275         ce_t4t_process_timeout(p_tle);
    276         break;
    277 #endif
    278       default:
    279         DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    280             "nfc_process_quick_timer_evt: unhandled timer event (0x%04x)",
    281             p_tle->event);
    282         break;
    283     }
    284   }
    285 
    286   /* if timer list is empty stop periodic GKI timer */
    287   if (nfc_cb.quick_timer_queue.p_first == NULL) {
    288     GKI_stop_timer(NFC_QUICK_TIMER_ID);
    289   }
    290 }
    291 
    292 /*******************************************************************************
    293 **
    294 ** Function         nfc_task_shutdown_nfcc
    295 **
    296 ** Description      Handle NFC shutdown
    297 **
    298 ** Returns          nothing
    299 **
    300 *******************************************************************************/
    301 void nfc_task_shutdown_nfcc(void) {
    302   NFC_HDR* p_msg;
    303 
    304   /* Free any messages still in the mbox */
    305   while ((p_msg = (NFC_HDR*)GKI_read_mbox(NFC_MBOX_ID)) != NULL) {
    306     GKI_freebuf(p_msg);
    307   }
    308 
    309   nfc_gen_cleanup();
    310 
    311   if (nfc_cb.flags & NFC_FL_POWER_OFF_SLEEP) {
    312     nfc_set_state(NFC_STATE_W4_HAL_CLOSE);
    313     nfc_cb.p_hal->close();
    314   } else if (nfc_cb.flags & NFC_FL_POWER_CYCLE_NFCC) {
    315     nfc_set_state(NFC_STATE_W4_HAL_OPEN);
    316     nfc_cb.p_hal->power_cycle();
    317   } else {
    318     nfc_set_state(NFC_STATE_W4_HAL_CLOSE);
    319     nfc_cb.p_hal->close();
    320 
    321     /* Perform final clean up */
    322     llcp_cleanup();
    323 
    324     /* Stop the timers */
    325     GKI_stop_timer(NFC_TIMER_ID);
    326     GKI_stop_timer(NFC_QUICK_TIMER_ID);
    327     GKI_stop_timer(NFA_TIMER_ID);
    328   }
    329 }
    330 
    331 /*******************************************************************************
    332 **
    333 ** Function         nfc_task
    334 **
    335 ** Description      NFC event processing task
    336 **
    337 ** Returns          nothing
    338 **
    339 *******************************************************************************/
    340 uint32_t nfc_task(__attribute__((unused)) uint32_t arg) {
    341   uint16_t event;
    342   NFC_HDR* p_msg;
    343   bool free_buf;
    344 
    345   /* Initialize the nfc control block */
    346   memset(&nfc_cb, 0, sizeof(tNFC_CB));
    347 
    348   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("NFC_TASK started.");
    349 
    350   /* main loop */
    351   while (true) {
    352     event = GKI_wait(0xFFFF, 0);
    353     if (event == EVENT_MASK(GKI_SHUTDOWN_EVT)) {
    354       break;
    355     }
    356     /* Handle NFC_TASK_EVT_TRANSPORT_READY from NFC HAL */
    357     if (event & NFC_TASK_EVT_TRANSPORT_READY) {
    358       DLOG_IF(INFO, nfc_debug_enabled)
    359           << StringPrintf("NFC_TASK got NFC_TASK_EVT_TRANSPORT_READY.");
    360 
    361       /* Reset the NFC controller. */
    362       nfc_set_state(NFC_STATE_CORE_INIT);
    363       nci_snd_core_reset(NCI_RESET_TYPE_RESET_CFG);
    364     }
    365 
    366     if (event & NFC_MBOX_EVT_MASK) {
    367       /* Process all incoming NCI messages */
    368       while ((p_msg = (NFC_HDR*)GKI_read_mbox(NFC_MBOX_ID)) != NULL) {
    369         free_buf = true;
    370 
    371         /* Determine the input message type. */
    372         switch (p_msg->event & NFC_EVT_MASK) {
    373           case BT_EVT_TO_NFC_NCI:
    374             free_buf = nfc_ncif_process_event(p_msg);
    375             break;
    376 
    377           case BT_EVT_TO_START_TIMER:
    378             /* Start nfc_task 1-sec resolution timer */
    379             GKI_start_timer(NFC_TIMER_ID, GKI_SECS_TO_TICKS(1), true);
    380             break;
    381 
    382           case BT_EVT_TO_START_QUICK_TIMER:
    383             /* Quick-timer is required for LLCP */
    384             GKI_start_timer(
    385                 NFC_QUICK_TIMER_ID,
    386                 ((GKI_SECS_TO_TICKS(1) / QUICK_TIMER_TICKS_PER_SEC)), true);
    387             break;
    388 
    389           case BT_EVT_TO_NFC_MSGS:
    390             nfc_main_handle_hal_evt((tNFC_HAL_EVT_MSG*)p_msg);
    391             break;
    392 
    393           default:
    394             DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
    395                 "nfc_task: unhandle mbox message, event=%04x", p_msg->event);
    396             break;
    397         }
    398 
    399         if (free_buf) {
    400           GKI_freebuf(p_msg);
    401         }
    402       }
    403     }
    404 
    405     /* Process gki timer tick */
    406     if (event & NFC_TIMER_EVT_MASK) {
    407       nfc_process_timer_evt();
    408     }
    409 
    410     /* Process quick timer tick */
    411     if (event & NFC_QUICK_TIMER_EVT_MASK) {
    412       nfc_process_quick_timer_evt();
    413     }
    414 
    415     if (event & NFA_MBOX_EVT_MASK) {
    416       while ((p_msg = (NFC_HDR*)GKI_read_mbox(NFA_MBOX_ID)) != NULL) {
    417         nfa_sys_event(p_msg);
    418       }
    419     }
    420 
    421     if (event & NFA_TIMER_EVT_MASK) {
    422       nfa_sys_timer_update();
    423     }
    424   }
    425 
    426   DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("nfc_task terminated");
    427 
    428   GKI_exit_task(GKI_get_taskid());
    429   return 0;
    430 }
    431