• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
34 NFC_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
43 tNFC_HAL_CB nfc_hal_cb;
44 #endif
45 
46 /****************************************************************************
47 ** Internal function prototypes
48 ****************************************************************************/
49 static void nfc_hal_main_userial_cback (tUSERIAL_PORT port, tUSERIAL_EVT evt, tUSERIAL_EVT_DATA *p_data);
50 static void nfc_hal_main_handle_terminate (void);
51 
52 
53 #if (NFC_HAL_DEBUG == TRUE)
54 const 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     "W4_RE_INIT",       /* Waiting for reset rsp on ReInit       */
66     "CLOSING"           /* Shutting down                         */
67 };
68 #endif
69 
70 /*******************************************************************************
71 **
72 ** Function         nfc_hal_main_init
73 **
74 ** Description      This function initializes control block for NFC HAL
75 **
76 ** Returns          nothing
77 **
78 *******************************************************************************/
nfc_hal_main_init(void)79 void nfc_hal_main_init (void)
80 {
81     /* Clear control block */
82     memset (&nfc_hal_cb, 0, sizeof (tNFC_HAL_CB));
83 
84     nfc_hal_cb.ncit_cb.nci_ctrl_size   = NFC_HAL_NCI_INIT_CTRL_PAYLOAD_SIZE;
85     nfc_hal_cb.trace_level             = NFC_HAL_INITIAL_TRACE_LEVEL;
86 }
87 
88 /*******************************************************************************
89 **
90 ** Function         nfc_hal_main_open_transport
91 **
92 ** Description      Open transport and prepare for new incoming message;
93 **
94 ** Returns          nothing
95 **
96 *******************************************************************************/
nfc_hal_main_open_transport(void)97 static void nfc_hal_main_open_transport (void)
98 {
99     tUSERIAL_OPEN_CFG open_cfg;
100 
101     /* Initialize control block */
102     nfc_hal_cb.ncit_cb.rcv_state = NFC_HAL_RCV_IDLE_ST; /* to process packet type */
103 
104     if (nfc_hal_cb.ncit_cb.p_rcv_msg)
105     {
106         GKI_freebuf (nfc_hal_cb.ncit_cb.p_rcv_msg);
107         nfc_hal_cb.ncit_cb.p_rcv_msg = NULL;
108     }
109 
110     /* open transport */
111     open_cfg.fmt    = (USERIAL_DATABITS_8 | USERIAL_PARITY_NONE | USERIAL_STOPBITS_1);
112     open_cfg.baud   = nfc_hal_trans_cfg.userial_baud;
113     open_cfg.fc     = nfc_hal_trans_cfg.userial_fc;
114     open_cfg.buf    = USERIAL_BUF_BYTE;
115 
116     USERIAL_Open (USERIAL_NFC_PORT, &open_cfg, nfc_hal_main_userial_cback);
117 
118     /* notify transport openned */
119     nfc_hal_dm_pre_init_nfcc ();
120 }
121 
122 /*******************************************************************************
123 **
124 ** Function         nfc_hal_main_send_error
125 **
126 ** Description      send an Error event to NFC stack
127 **
128 ** Returns          nothing
129 **
130 *******************************************************************************/
nfc_hal_main_send_error(tHAL_NFC_STATUS status)131 void nfc_hal_main_send_error (tHAL_NFC_STATUS status)
132 {
133     /* Notify stack */
134     nfc_hal_cb.p_stack_cback(HAL_NFC_ERROR_EVT, status);
135 }
136 
137 /*******************************************************************************
138 **
139 ** Function         nfc_hal_main_userial_cback
140 **
141 ** Description      USERIAL callback for NCI transport
142 **
143 ** Returns          nothing
144 **
145 *******************************************************************************/
nfc_hal_main_userial_cback(tUSERIAL_PORT port,tUSERIAL_EVT evt,tUSERIAL_EVT_DATA * p_data)146 static void nfc_hal_main_userial_cback (tUSERIAL_PORT port, tUSERIAL_EVT evt, tUSERIAL_EVT_DATA *p_data)
147 {
148     if (evt == USERIAL_RX_READY_EVT)
149     {
150         /* Notify transport task of serial port event */
151         GKI_send_event (NFC_HAL_TASK, NFC_HAL_TASK_EVT_DATA_RDY);
152     }
153     else if (evt == USERIAL_TX_DONE_EVT)
154     {
155         /* Serial driver has finshed sending data from USERIAL_Write */
156         /* Currently, no action is needed for this event */
157     }
158     else if (evt == USERIAL_ERR_EVT)
159     {
160         NCI_TRACE_ERROR0 ("nfc_hal_main_userial_cback: USERIAL_ERR_EVT. Notifying NFC_TASK of transport error");
161         if (nfc_hal_cb.ncit_cb.nci_wait_rsp != NFC_HAL_WAIT_RSP_NONE)
162         {
163             nfc_hal_main_stop_quick_timer (&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer);
164             nfc_hal_nci_cmd_timeout_cback ((void *)&nfc_hal_cb.ncit_cb.nci_wait_rsp_timer);
165         }
166         else
167         {
168             nfc_hal_main_send_error (HAL_NFC_STATUS_ERR_TRANSPORT);
169         }
170     }
171     else if (evt == USERIAL_WAKEUP_EVT)
172     {
173         NCI_TRACE_DEBUG1 ("nfc_hal_main_userial_cback: USERIAL_WAKEUP_EVT: %d", p_data->sigs);
174     }
175     else
176     {
177         NCI_TRACE_DEBUG1 ("nfc_hal_main_userial_cback: unhandled userial evt: %i", evt);
178     }
179 }
180 
181 /*******************************************************************************
182 **
183 ** Function         nfc_hal_main_pre_init_done
184 **
185 ** Description      notify complete of pre-initialization
186 **
187 ** Returns          nothing
188 **
189 *******************************************************************************/
nfc_hal_main_pre_init_done(tHAL_NFC_STATUS status)190 void nfc_hal_main_pre_init_done (tHAL_NFC_STATUS status)
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 *******************************************************************************/
nfc_hal_main_timeout_cback(void * p_tle)215 static 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 *******************************************************************************/
nfc_hal_main_handle_terminate(void)242 static 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 *******************************************************************************/
nfc_hal_main_start_quick_timer(TIMER_LIST_ENT * p_tle,UINT16 type,UINT32 timeout)290 void 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 *******************************************************************************/
nfc_hal_main_stop_quick_timer(TIMER_LIST_ENT * p_tle)330 void 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 *******************************************************************************/
nfc_hal_main_process_quick_timer_evt(void)350 static 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 *******************************************************************************/
nfc_hal_main_send_message(NFC_HDR * p_msg)383 static 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 *******************************************************************************/
nfc_hal_main_task(UINT32 param)425 UINT32 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 
558                     if (nfc_hal_cb.ncit_cb.p_rcv_msg)
559                     {
560                         GKI_freebuf(nfc_hal_cb.ncit_cb.p_rcv_msg);
561                         nfc_hal_cb.ncit_cb.p_rcv_msg = NULL;
562                     }
563                 }
564             } /* while (TRUE) */
565         }
566 
567         /* Process quick timer tick */
568         if (event & NFC_HAL_QUICK_TIMER_EVT_MASK)
569         {
570             nfc_hal_main_process_quick_timer_evt ();
571         }
572     }
573 
574     NCI_TRACE_DEBUG0 ("nfc_hal_main_task terminated");
575 
576     GKI_exit_task (GKI_get_taskid ());
577     return 0;
578 }
579 
580 /*******************************************************************************
581 **
582 ** Function         HAL_NfcSetTraceLevel
583 **
584 ** Description      This function sets the trace level for HAL.  If called with
585 **                  a value of 0xFF, it simply returns the current trace level.
586 **
587 ** Returns          The new or current trace level
588 **
589 *******************************************************************************/
HAL_NfcSetTraceLevel(UINT8 new_level)590 UINT8 HAL_NfcSetTraceLevel (UINT8 new_level)
591 {
592     if (new_level != 0xFF)
593         nfc_hal_cb.trace_level = new_level;
594 
595     return (nfc_hal_cb.trace_level);
596 }
597