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