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