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