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        case NFC_TTYPE_P2P_PRIO_RESPONSE:
282            nfa_dm_p2p_timer_event ();
283            break;
284        case NFC_TTYPE_P2P_PRIO_LOGIC_CLEANUP:
285            nfa_dm_p2p_prio_logic_cleanup ();
286            break;
287#if (NFC_RW_ONLY == FALSE)
288        case NFC_TTYPE_CE_T4T_UPDATE:
289            ce_t4t_process_timeout (p_tle);
290            break;
291#endif
292        default:
293            NFC_TRACE_DEBUG1 ("nfc_process_quick_timer_evt: unhandled timer event (0x%04x)", p_tle->event);
294            break;
295        }
296    }
297
298    /* if timer list is empty stop periodic GKI timer */
299    if (nfc_cb.quick_timer_queue.p_first == NULL)
300    {
301        GKI_stop_timer (NFC_QUICK_TIMER_ID);
302    }
303}
304
305/*******************************************************************************
306**
307** Function         nfc_task_shutdown_nfcc
308**
309** Description      Handle NFC shutdown
310**
311** Returns          nothing
312**
313*******************************************************************************/
314void nfc_task_shutdown_nfcc (void)
315{
316    BT_HDR        *p_msg;
317
318    /* Free any messages still in the mbox */
319    while ((p_msg = (BT_HDR *) GKI_read_mbox (NFC_MBOX_ID)) != NULL)
320    {
321        GKI_freebuf (p_msg);
322    }
323
324    nfc_gen_cleanup ();
325
326    if (nfc_cb.flags & NFC_FL_POWER_OFF_SLEEP)
327    {
328        nfc_set_state (NFC_STATE_W4_HAL_CLOSE);
329        nfc_cb.p_hal->close();
330    }
331    else if (nfc_cb.flags & NFC_FL_POWER_CYCLE_NFCC)
332    {
333        nfc_set_state (NFC_STATE_W4_HAL_OPEN);
334        nfc_cb.p_hal->power_cycle();
335    }
336    else
337    {
338        nfc_set_state (NFC_STATE_W4_HAL_CLOSE);
339        nfc_cb.p_hal->close();
340
341        /* Perform final clean up */
342        llcp_cleanup ();
343
344        /* Stop the timers */
345        GKI_stop_timer (NFC_TIMER_ID);
346        GKI_stop_timer (NFC_QUICK_TIMER_ID);
347#if (defined (NFA_INCLUDED) && NFA_INCLUDED == TRUE)
348        GKI_stop_timer (NFA_TIMER_ID);
349#endif
350    }
351}
352
353/*******************************************************************************
354**
355** Function         nfc_task
356**
357** Description      NFC event processing task
358**
359** Returns          nothing
360**
361*******************************************************************************/
362UINT32 nfc_task (UINT32 param)
363{
364    UINT16  event;
365    BT_HDR  *p_msg;
366    BOOLEAN free_buf;
367
368    /* Initialize the nfc control block */
369    memset (&nfc_cb, 0, sizeof (tNFC_CB));
370    nfc_cb.trace_level = NFC_INITIAL_TRACE_LEVEL;
371
372    NFC_TRACE_DEBUG0 ("NFC_TASK started.");
373
374    /* main loop */
375    while (TRUE)
376    {
377        event = GKI_wait (0xFFFF, 0);
378
379        /* Handle NFC_TASK_EVT_TRANSPORT_READY from NFC HAL */
380        if (event & NFC_TASK_EVT_TRANSPORT_READY)
381        {
382            NFC_TRACE_DEBUG0 ("NFC_TASK got NFC_TASK_EVT_TRANSPORT_READY.");
383
384            /* Reset the NFC controller. */
385            nfc_set_state (NFC_STATE_CORE_INIT);
386            nci_snd_core_reset (NCI_RESET_TYPE_RESET_CFG);
387        }
388
389        if (event & NFC_MBOX_EVT_MASK)
390        {
391            /* Process all incoming NCI messages */
392            while ((p_msg = (BT_HDR *) GKI_read_mbox (NFC_MBOX_ID)) != NULL)
393            {
394                free_buf = TRUE;
395
396                /* Determine the input message type. */
397                switch (p_msg->event & BT_EVT_MASK)
398                {
399                    case BT_EVT_TO_NFC_NCI:
400                        free_buf = nfc_ncif_process_event (p_msg);
401                        break;
402
403                    case BT_EVT_TO_START_TIMER :
404                        /* Start nfc_task 1-sec resolution timer */
405                        GKI_start_timer (NFC_TIMER_ID, GKI_SECS_TO_TICKS (1), TRUE);
406                        break;
407
408                    case BT_EVT_TO_START_QUICK_TIMER :
409                        /* Quick-timer is required for LLCP */
410                        GKI_start_timer (NFC_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE);
411                        break;
412
413                    case BT_EVT_TO_NFC_MSGS:
414                        nfc_main_handle_hal_evt ((tNFC_HAL_EVT_MSG*)p_msg);
415                        break;
416
417                    default:
418                        NFC_TRACE_DEBUG1 ("nfc_task: unhandle mbox message, event=%04x", p_msg->event);
419                        break;
420                }
421
422                if (free_buf)
423                {
424                    GKI_freebuf (p_msg);
425                }
426            }
427        }
428
429        /* Process gki timer tick */
430        if (event & NFC_TIMER_EVT_MASK)
431        {
432            nfc_process_timer_evt ();
433        }
434
435        /* Process quick timer tick */
436        if (event & NFC_QUICK_TIMER_EVT_MASK)
437        {
438            nfc_process_quick_timer_evt ();
439        }
440
441#if (defined (NFA_INCLUDED) && NFA_INCLUDED == TRUE)
442        if (event & NFA_MBOX_EVT_MASK)
443        {
444            while ((p_msg = (BT_HDR *) GKI_read_mbox (NFA_MBOX_ID)) != NULL)
445            {
446                nfa_sys_event (p_msg);
447            }
448        }
449
450        if (event & NFA_TIMER_EVT_MASK)
451        {
452            nfa_sys_timer_update ();
453        }
454#endif
455
456    }
457
458
459    NFC_TRACE_DEBUG0 ("nfc_task terminated");
460
461    GKI_exit_task (GKI_get_taskid ());
462    return 0;
463}
464
465#endif /* NFC_INCLUDED == TRUE */
466