nfc_hal_main.c revision ba4c17ee1d31e1b9f396292711f1414d449dd361
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 *  Functions for handling NFC HAL NCI Transport events
22 *
23 ******************************************************************************/
24#include <string.h>
25#include "nfc_hal_int.h"
26#include "userial.h"
27#include "upio.h"
28
29/****************************************************************************
30** Definitions
31****************************************************************************/
32
33/* Default NFC HAL NCI port configuration  */
34NFC_HAL_TRANS_CFG_QUALIFIER tNFC_HAL_TRANS_CFG nfc_hal_trans_cfg =
35{
36    NFC_HAL_SHARED_TRANSPORT_ENABLED,   /* bSharedTransport */
37    USERIAL_BAUD_115200,                /* Baud rate */
38    USERIAL_FC_HW                       /* Flow control */
39};
40
41/* Control block for NFC HAL NCI transport */
42#if NFC_DYNAMIC_MEMORY == FALSE
43tNFC_HAL_CB nfc_hal_cb;
44#endif
45
46/****************************************************************************
47** Internal function prototypes
48****************************************************************************/
49static void nfc_hal_main_userial_cback (tUSERIAL_PORT port, tUSERIAL_EVT evt, tUSERIAL_EVT_DATA *p_data);
50static void nfc_hal_main_handle_terminate (void);
51
52
53#if (NFC_HAL_DEBUG == TRUE)
54const char * const nfc_hal_init_state_str[] =
55{
56    "IDLE",             /* Initialization is done                */
57    "W4_XTAL_SET",      /* Waiting for crystal setting rsp       */
58    "W4_RESET",         /* Waiting for reset rsp                 */
59    "W4_BUILD_INFO",    /* Waiting for build info rsp            */
60    "W4_PATCH_INFO",    /* Waiting for patch info rsp            */
61    "W4_APP_COMPL",     /* Waiting for complete from application */
62    "W4_POST_INIT",     /* Waiting for complete of post init     */
63    "W4_CONTROL",       /* Waiting for control release           */
64    "W4_PREDISC",       /* Waiting for complete of prediscover   */
65    "CLOSING"           /* Shutting down                         */
66};
67#endif
68
69/*******************************************************************************
70**
71** Function         nfc_hal_main_init
72**
73** Description      This function initializes control block for NFC HAL
74**
75** Returns          nothing
76**
77*******************************************************************************/
78void nfc_hal_main_init (void)
79{
80    /* Clear control block */
81    memset (&nfc_hal_cb, 0, sizeof (tNFC_HAL_CB));
82
83    nfc_hal_cb.ncit_cb.nci_ctrl_size   = NFC_HAL_NCI_INIT_CTRL_PAYLOAD_SIZE;
84    nfc_hal_cb.trace_level             = NFC_HAL_INITIAL_TRACE_LEVEL;
85}
86
87/*******************************************************************************
88**
89** Function         nfc_hal_main_open_transport
90**
91** Description      Open transport and prepare for new incoming message;
92**
93** Returns          nothing
94**
95*******************************************************************************/
96static void nfc_hal_main_open_transport (void)
97{
98    tUSERIAL_OPEN_CFG open_cfg;
99
100    /* Initialize control block */
101    nfc_hal_cb.ncit_cb.rcv_state = NFC_HAL_RCV_IDLE_ST; /* to process packet type */
102
103    if (nfc_hal_cb.ncit_cb.p_rcv_msg)
104    {
105        GKI_freebuf (nfc_hal_cb.ncit_cb.p_rcv_msg);
106        nfc_hal_cb.ncit_cb.p_rcv_msg = NULL;
107    }
108
109    /* open transport */
110    open_cfg.fmt    = (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1);
111    open_cfg.baud   = nfc_hal_trans_cfg.userial_baud;
112    open_cfg.fc     = nfc_hal_trans_cfg.userial_fc;
113    open_cfg.buf    = USERIAL_BUF_BYTE;
114
115    USERIAL_Open (USERIAL_NFC_PORT, &open_cfg, nfc_hal_main_userial_cback);
116
117    /* notify transport openned */
118    nfc_hal_dm_pre_init_nfcc ();
119}
120
121/*******************************************************************************
122**
123** Function         nfc_hal_main_send_error
124**
125** Description      send an Error event to NFC stack
126**
127** Returns          nothing
128**
129*******************************************************************************/
130void nfc_hal_main_send_error (tHAL_NFC_STATUS status)
131{
132    /* Notify stack */
133    nfc_hal_cb.p_stack_cback(HAL_NFC_ERROR_EVT, status);
134}
135
136/*******************************************************************************
137**
138** Function         nfc_hal_main_userial_cback
139**
140** Description      USERIAL callback for NCI transport
141**
142** Returns          nothing
143**
144*******************************************************************************/
145static void nfc_hal_main_userial_cback (tUSERIAL_PORT port, tUSERIAL_EVT evt, tUSERIAL_EVT_DATA *p_data)
146{
147    if (evt == USERIAL_RX_READY_EVT)
148    {
149        /* Notify transport task of serial port event */
150        GKI_send_event (NFC_HAL_TASK, NFC_HAL_TASK_EVT_DATA_RDY);
151    }
152    else if (evt == USERIAL_TX_DONE_EVT)
153    {
154        /* Serial driver has finshed sending data from USERIAL_Write */
155        /* Currently, no action is needed for this event */
156    }
157    else if (evt == USERIAL_ERR_EVT)
158    {
159        NCI_TRACE_ERROR0 ("nfc_hal_main_userial_cback: USERIAL_ERR_EVT. Notifying NFC_TASK of transport error");
160        if (nfc_hal_cb.ncit_cb.nci_wait_rsp != NFC_HAL_WAIT_RSP_NONE)
161        {
162            nfc_hal_main_stop_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer);
163            nfc_hal_nci_cmd_timeout_cback ((void *)&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer);
164        }
165        else
166        {
167            nfc_hal_main_send_error (HAL_NFC_STATUS_ERR_TRANSPORT);
168        }
169    }
170    else if (evt == USERIAL_WAKEUP_EVT)
171    {
172        NCI_TRACE_DEBUG1 ("nfc_hal_main_userial_cback: USERIAL_WAKEUP_EVT: %d", p_data->sigs);
173    }
174    else
175    {
176        NCI_TRACE_DEBUG1 ("nfc_hal_main_userial_cback: unhandled userial evt: %i", evt);
177    }
178}
179
180/*******************************************************************************
181**
182** Function         nfc_hal_main_pre_init_done
183**
184** Description      notify complete of pre-initialization
185**
186** Returns          nothing
187**
188*******************************************************************************/
189void nfc_hal_main_pre_init_done (tHAL_NFC_STATUS status)
190{
191
192    NCI_TRACE_DEBUG1 ("nfc_hal_main_pre_init_done () status = %d", status);
193
194    if (status != HAL_NFC_STATUS_OK)
195    {
196        nfc_hal_main_handle_terminate ();
197
198        /* Close uart */
199        USERIAL_Close (USERIAL_NFC_PORT);
200    }
201
202    /* Notify NFC Task the status of initialization */
203    nfc_hal_cb.p_stack_cback(HAL_NFC_OPEN_CPLT_EVT, status);
204}
205
206/*******************************************************************************
207**
208** Function         nfc_hal_main_timeout_cback
209**
210** Description      callback function for timeout
211**
212** Returns          void
213**
214*******************************************************************************/
215static void nfc_hal_main_timeout_cback (void *p_tle)
216{
217    TIMER_LIST_ENT  *p_tlent = (TIMER_LIST_ENT *) p_tle;
218
219    NCI_TRACE_DEBUG0 ("nfc_hal_main_timeout_cback ()");
220
221    switch (p_tlent->event)
222    {
223    case NFC_HAL_TTYPE_POWER_CYCLE:
224        nfc_hal_main_open_transport ();
225        break;
226
227    default:
228        NCI_TRACE_DEBUG1 ("nfc_hal_main_timeout_cback: unhandled timer event (0x%04x)", p_tlent->event);
229        break;
230    }
231}
232
233/*******************************************************************************
234**
235** Function         nfc_hal_main_handle_terminate
236**
237** Description      Handle NFI transport shutdown
238**
239** Returns          nothing
240**
241*******************************************************************************/
242static void nfc_hal_main_handle_terminate (void)
243{
244    NFC_HDR *p_msg;
245
246    /* dequeue and free buffer */
247    if (nfc_hal_cb.ncit_cb.p_pend_cmd != NULL)
248    {
249        GKI_freebuf (nfc_hal_cb.ncit_cb.p_pend_cmd);
250        nfc_hal_cb.ncit_cb.p_pend_cmd = NULL;
251    }
252
253    /* Free unsent nfc rx buffer */
254    if (nfc_hal_cb.ncit_cb.p_rcv_msg)
255    {
256        GKI_freebuf (nfc_hal_cb.ncit_cb.p_rcv_msg);
257        nfc_hal_cb.ncit_cb.p_rcv_msg  = NULL;
258    }
259
260    /* Free buffer for pending fragmented response/notification */
261    if (nfc_hal_cb.ncit_cb.p_frag_msg)
262    {
263        GKI_freebuf (nfc_hal_cb.ncit_cb.p_frag_msg);
264        nfc_hal_cb.ncit_cb.p_frag_msg = NULL;
265    }
266
267    /* Free buffers in the tx mbox */
268    while ((p_msg = (NFC_HDR *) GKI_read_mbox (NFC_HAL_TASK_MBOX)) != NULL)
269    {
270        GKI_freebuf (p_msg);
271    }
272
273    /* notify closing transport */
274    nfc_hal_dm_shutting_down_nfcc ();
275}
276
277/*******************************************************************************
278**
279** Function         nfc_hal_main_start_quick_timer
280**
281** Description      Start a timer for the specified amount of time.
282**                  NOTE: The timeout resolution depends on including modules.
283**                  QUICK_TIMER_TICKS_PER_SEC should be used to convert from
284**                  time to ticks.
285**
286**
287** Returns          void
288**
289*******************************************************************************/
290void nfc_hal_main_start_quick_timer (TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout)
291{
292    NFC_HDR *p_msg;
293
294    /* if timer list is currently empty, start periodic GKI timer */
295    if (nfc_hal_cb.quick_timer_queue.p_first == NULL)
296    {
297        /* if timer starts on other than NCIT task (script wrapper) */
298        if(GKI_get_taskid () != NFC_HAL_TASK)
299        {
300            /* post event to start timer in NCIT task */
301            if ((p_msg = (NFC_HDR *) GKI_getbuf (NFC_HDR_SIZE)) != NULL)
302            {
303                p_msg->event = NFC_HAL_EVT_TO_START_QUICK_TIMER;
304                GKI_send_msg (NFC_HAL_TASK, NFC_HAL_TASK_MBOX, p_msg);
305            }
306        }
307        else
308        {
309            GKI_start_timer (NFC_HAL_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE);
310        }
311    }
312
313    GKI_remove_from_timer_list (&nfc_hal_cb.quick_timer_queue, p_tle);
314
315    p_tle->event = type;
316    p_tle->ticks = timeout; /* Save the number of ticks for the timer */
317
318    GKI_add_to_timer_list (&nfc_hal_cb.quick_timer_queue, p_tle);
319}
320
321/*******************************************************************************
322**
323** Function         nfc_hal_main_stop_quick_timer
324**
325** Description      Stop a timer.
326**
327** Returns          void
328**
329*******************************************************************************/
330void nfc_hal_main_stop_quick_timer (TIMER_LIST_ENT *p_tle)
331{
332    GKI_remove_from_timer_list (&nfc_hal_cb.quick_timer_queue, p_tle);
333
334    /* if timer list is empty stop periodic GKI timer */
335    if (nfc_hal_cb.quick_timer_queue.p_first == NULL)
336    {
337        GKI_stop_timer (NFC_HAL_QUICK_TIMER_ID);
338    }
339}
340
341/*******************************************************************************
342**
343** Function         nfc_hal_main_process_quick_timer_evt
344**
345** Description      Process quick timer event
346**
347** Returns          void
348**
349*******************************************************************************/
350static void nfc_hal_main_process_quick_timer_evt (void)
351{
352    TIMER_LIST_ENT  *p_tle;
353
354    GKI_update_timer_list (&nfc_hal_cb.quick_timer_queue, 1);
355
356    while ((nfc_hal_cb.quick_timer_queue.p_first) && (!nfc_hal_cb.quick_timer_queue.p_first->ticks))
357    {
358        p_tle = nfc_hal_cb.quick_timer_queue.p_first;
359        GKI_remove_from_timer_list (&nfc_hal_cb.quick_timer_queue, p_tle);
360
361        if (p_tle->p_cback)
362        {
363            (*p_tle->p_cback) (p_tle);
364        }
365    }
366
367    /* if timer list is empty stop periodic GKI timer */
368    if (nfc_hal_cb.quick_timer_queue.p_first == NULL)
369    {
370        GKI_stop_timer (NFC_HAL_QUICK_TIMER_ID);
371    }
372}
373
374/*******************************************************************************
375**
376** Function         nfc_hal_main_send_message
377**
378** Description      This function is calledto send an NCI message.
379**
380** Returns          void
381**
382*******************************************************************************/
383static void nfc_hal_main_send_message (NFC_HDR *p_msg)
384{
385    UINT8   *ps;
386    UINT16  len = p_msg->len;
387#ifdef DISP_NCI
388    UINT8   delta;
389#endif
390
391    NCI_TRACE_DEBUG1 ("nfc_hal_main_send_message() ls:0x%x", p_msg->layer_specific);
392    if (  (p_msg->layer_specific == NFC_HAL_WAIT_RSP_CMD)
393        ||(p_msg->layer_specific == NFC_HAL_WAIT_RSP_VSC)  )
394    {
395        nfc_hal_nci_send_cmd (p_msg);
396    }
397    else
398    {
399        /* NFC task has fragmented the data packet to the appropriate size
400         * and data credit is available; just send it */
401
402        /* add NCI packet type in front of message */
403        nfc_hal_nci_add_nfc_pkt_type (p_msg);
404
405        /* send this packet to transport */
406        ps = (UINT8 *) (p_msg + 1) + p_msg->offset;
407#ifdef DISP_NCI
408        delta = p_msg->len - len;
409        DISP_NCI (ps + delta, (UINT16) (p_msg->len - delta), FALSE);
410#endif
411        USERIAL_Write (USERIAL_NFC_PORT, ps, p_msg->len);
412        GKI_freebuf (p_msg);
413    }
414}
415
416/*******************************************************************************
417**
418** Function         nfc_hal_main_task
419**
420** Description      NFC HAL NCI transport event processing task
421**
422** Returns          0
423**
424*******************************************************************************/
425UINT32 nfc_hal_main_task (UINT32 param)
426{
427    UINT16   event;
428    UINT8    byte;
429    UINT8    num_interfaces;
430    UINT8    *p;
431    NFC_HDR  *p_msg;
432    BOOLEAN  free_msg;
433
434    NCI_TRACE_DEBUG0 ("NFC_HAL_TASK started");
435
436    /* Main loop */
437    while (TRUE)
438    {
439        event = GKI_wait (0xFFFF, 0);
440
441        /* Handle NFC_HAL_TASK_EVT_INITIALIZE (for initializing NCI transport) */
442        if (event & NFC_HAL_TASK_EVT_INITIALIZE)
443        {
444            NCI_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_INITIALIZE signal. Opening NFC transport...");
445
446            nfc_hal_main_open_transport ();
447        }
448
449        /* Check for terminate event */
450        if (event & NFC_HAL_TASK_EVT_TERMINATE)
451        {
452            NCI_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_TERMINATE");
453            nfc_hal_main_handle_terminate ();
454
455            /* Close uart */
456            USERIAL_Close (USERIAL_NFC_PORT);
457
458            nfc_hal_cb.p_stack_cback (HAL_NFC_CLOSE_CPLT_EVT, HAL_NFC_STATUS_OK);
459            nfc_hal_cb.p_stack_cback = NULL;
460            continue;
461        }
462
463        /* Check for power cycle event */
464        if (event & NFC_HAL_TASK_EVT_POWER_CYCLE)
465        {
466            NCI_TRACE_DEBUG0 ("NFC_HAL_TASK got NFC_HAL_TASK_EVT_POWER_CYCLE");
467            nfc_hal_main_handle_terminate ();
468
469            /* Close uart */
470            USERIAL_Close (USERIAL_NFC_PORT);
471
472            /* power cycle timeout */
473            nfc_hal_cb.timer.p_cback = nfc_hal_main_timeout_cback;
474            nfc_hal_main_start_quick_timer (&nfc_hal_cb.timer, NFC_HAL_TTYPE_POWER_CYCLE,
475                                            (NFC_HAL_POWER_CYCLE_DELAY*QUICK_TIMER_TICKS_PER_SEC)/1000);
476            continue;
477        }
478
479        /* NCI message ready to be sent to NFCC */
480        if (event & NFC_HAL_TASK_EVT_MBOX)
481        {
482            while ((p_msg = (NFC_HDR *) GKI_read_mbox (NFC_HAL_TASK_MBOX)) != NULL)
483            {
484                free_msg = TRUE;
485                switch (p_msg->event & NFC_EVT_MASK)
486                {
487                case NFC_HAL_EVT_TO_NFC_NCI:
488                    nfc_hal_main_send_message (p_msg);
489                    /* do not free buffer. NCI VS code may keep it for processing later */
490                    free_msg = FALSE;
491                    break;
492
493                case NFC_HAL_EVT_POST_CORE_RESET:
494                    NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_W4_POST_INIT_DONE);
495
496                    /* set NCI Control packet size from CORE_INIT_RSP */
497                    p = (UINT8 *) (p_msg + 1) + p_msg->offset + NCI_MSG_HDR_SIZE;
498                    p += 5;
499                    STREAM_TO_UINT8 (num_interfaces, p);
500                    p += (num_interfaces + 3);
501                    nfc_hal_cb.ncit_cb.nci_ctrl_size = *p;
502
503                    /* start post initialization */
504                    nfc_hal_cb.dev_cb.next_dm_config = NFC_HAL_DM_CONFIG_LPTD;
505                    nfc_hal_cb.dev_cb.next_startup_vsc = 1;
506
507                    nfc_hal_dm_config_nfcc ();
508                    break;
509
510                case NFC_HAL_EVT_TO_START_QUICK_TIMER:
511                    GKI_start_timer (NFC_HAL_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE);
512                    break;
513
514                case NFC_HAL_EVT_HCI:
515                    nfc_hal_hci_evt_hdlr ((tNFC_HAL_HCI_EVENT_DATA *) p_msg);
516                    break;
517
518
519                case NFC_HAL_EVT_CONTROL_GRANTED:
520                    nfc_hal_dm_send_pend_cmd ();
521                    break;
522
523                default:
524                    break;
525                }
526
527                if (free_msg)
528                    GKI_freebuf (p_msg);
529            }
530        }
531
532        /* Data waiting to be read from serial port */
533        if (event & NFC_HAL_TASK_EVT_DATA_RDY)
534        {
535            while (TRUE)
536            {
537                /* Read one byte to see if there is anything waiting to be read */
538                if (USERIAL_Read (USERIAL_NFC_PORT, &byte, 1) == 0)
539                {
540                    break;
541                }
542
543                if (nfc_hal_nci_receive_msg (byte))
544                {
545                    /* complete of receiving NCI message */
546                    nfc_hal_nci_assemble_nci_msg ();
547                    if (nfc_hal_cb.ncit_cb.p_rcv_msg)
548                    {
549                        if (nfc_hal_nci_preproc_rx_nci_msg (nfc_hal_cb.ncit_cb.p_rcv_msg))
550                        {
551                            /* Send NCI message to the stack */
552                            nfc_hal_cb.p_data_cback(nfc_hal_cb.ncit_cb.p_rcv_msg->len, (UINT8 *)((nfc_hal_cb.ncit_cb.p_rcv_msg + 1)
553                                                             + nfc_hal_cb.ncit_cb.p_rcv_msg->offset));
554
555                        }
556
557                        GKI_freebuf(nfc_hal_cb.ncit_cb.p_rcv_msg);
558                        nfc_hal_cb.ncit_cb.p_rcv_msg = NULL;
559                    }
560                }
561            } /* while (TRUE) */
562        }
563
564        /* Process quick timer tick */
565        if (event & NFC_HAL_QUICK_TIMER_EVT_MASK)
566        {
567            nfc_hal_main_process_quick_timer_evt ();
568        }
569    }
570
571    NCI_TRACE_DEBUG0 ("nfc_hal_main_task terminated");
572
573    GKI_exit_task (GKI_get_taskid ());
574    return 0;
575}
576
577/*******************************************************************************
578**
579** Function         HAL_NfcSetTraceLevel
580**
581** Description      This function sets the trace level for HAL.  If called with
582**                  a value of 0xFF, it simply returns the current trace level.
583**
584** Returns          The new or current trace level
585**
586*******************************************************************************/
587UINT8 HAL_NfcSetTraceLevel (UINT8 new_level)
588{
589    if (new_level != 0xFF)
590        nfc_hal_cb.trace_level = new_level;
591
592    return (nfc_hal_cb.trace_level);
593}
594