nfa_hci_main.c revision a24be4f06674b2707b57904deaa0dff5a95823bd
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 *  This is the main implementation file for the NFA HCI.
23 *
24 ******************************************************************************/
25#include <string.h>
26#include "nfc_api.h"
27#include "nfa_sys.h"
28#include "nfa_sys_int.h"
29#include "nfa_dm_int.h"
30#include "nfa_hci_api.h"
31#include "nfa_hci_int.h"
32#include "nfa_ee_api.h"
33#include "nfa_ee_int.h"
34#include "nfa_nv_co.h"
35#include "nfa_mem_co.h"
36#include "nfa_hci_defs.h"
37#include "trace_api.h"
38
39
40/*****************************************************************************
41**  Global Variables
42*****************************************************************************/
43
44tNFA_HCI_CB nfa_hci_cb;
45
46#ifndef NFA_HCI_NV_READ_TIMEOUT_VAL
47#define NFA_HCI_NV_READ_TIMEOUT_VAL    1000
48#endif
49
50#ifndef NFA_HCI_CON_CREATE_TIMEOUT_VAL
51#define NFA_HCI_CON_CREATE_TIMEOUT_VAL 1000
52#endif
53
54/*****************************************************************************
55**  Static Functions
56*****************************************************************************/
57
58/* event handler function type */
59static BOOLEAN nfa_hci_evt_hdlr (BT_HDR *p_msg);
60
61static void nfa_hci_sys_enable (void);
62static void nfa_hci_sys_disable (void);
63static void nfa_hci_rsp_timeout (tNFA_HCI_EVENT_DATA *p_evt_data);
64static void nfa_hci_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data);
65static void nfa_hci_set_receive_buf (UINT8 pipe);
66static void nfa_hci_assemble_msg (UINT8 *p_data, UINT16 data_len);
67static void nfa_hci_handle_nv_read (UINT8 block, tNFA_STATUS status);
68
69/*****************************************************************************
70**  Constants
71*****************************************************************************/
72static const tNFA_SYS_REG nfa_hci_sys_reg =
73{
74    nfa_hci_sys_enable,
75    nfa_hci_evt_hdlr,
76    nfa_hci_sys_disable,
77    nfa_hci_proc_nfcc_power_mode
78};
79
80/*******************************************************************************
81**
82** Function         nfa_hci_ee_info_cback
83**
84** Description      Callback function
85**
86** Returns          None
87**
88*******************************************************************************/
89void nfa_hci_ee_info_cback (tNFA_EE_DISC_STS status)
90{
91    UINT8           num_nfcee = 3;
92    tNFA_EE_INFO    ee_info[3];
93
94    NFA_TRACE_DEBUG1 ("nfa_hci_ee_info_cback (): %d", status);
95
96    switch (status)
97    {
98    case NFA_EE_DISC_STS_ON:
99        if (  (!nfa_hci_cb.ee_disc_cmplt)
100            &&((nfa_hci_cb.hci_state == NFA_HCI_STATE_STARTUP) || (nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE))  )
101        {
102        /* NFCEE Discovery is in progress */
103        nfa_hci_cb.ee_disc_cmplt      = TRUE;
104        nfa_hci_cb.num_ee_dis_req_ntf = 0;
105        nfa_hci_cb.num_hot_plug_evts  = 0;
106        nfa_hci_cb.conn_id            = 0;
107        nfa_hci_startup ();
108        }
109        break;
110
111    case NFA_EE_DISC_STS_OFF:
112        if (nfa_hci_cb.ee_disable_disc)
113            break;
114        nfa_hci_cb.ee_disable_disc  = TRUE;
115        /* Discovery operation is complete, retrieve discovery result */
116        NFA_EeGetInfo (&num_nfcee, ee_info);
117        nfa_hci_cb.num_nfcee        = num_nfcee;
118
119        if (  (nfa_hci_cb.hci_state == NFA_HCI_STATE_WAIT_NETWK_ENABLE)
120            ||(nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE_NETWK_ENABLE)  )
121        {
122            if (  (nfa_hci_cb.num_nfcee <= 1)
123                ||(nfa_hci_cb.num_ee_dis_req_ntf == (nfa_hci_cb.num_nfcee - 1))
124                ||(nfa_hci_cb.num_hot_plug_evts  == (nfa_hci_cb.num_nfcee - 1))  )
125            {
126                /* No UICC Host is detected or
127                 * HOT_PLUG_EVT(s) and or EE DISC REQ Ntf(s) are already received
128                 * Get Host list and notify SYS on Initialization complete */
129                nfa_sys_stop_timer (&nfa_hci_cb.timer);
130                if (  (nfa_hci_cb.num_nfcee > 1)
131                    &&(nfa_hci_cb.num_ee_dis_req_ntf != (nfa_hci_cb.num_nfcee - 1))  )
132                {
133                    /* Received HOT PLUG EVT, we will also wait for EE DISC REQ Ntf(s) */
134                    nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, p_nfa_hci_cfg->hci_netwk_enable_timeout);
135                }
136                else
137                {
138                    nfa_hci_cb.w4_hci_netwk_init = FALSE;
139                    nfa_hciu_send_get_param_cmd (NFA_HCI_ADMIN_PIPE, NFA_HCI_HOST_LIST_INDEX);
140                }
141            }
142        }
143        else if (nfa_hci_cb.num_nfcee <= 1)
144        {
145            /* No UICC Host is detected, HCI NETWORK is enabled */
146            nfa_hci_cb.w4_hci_netwk_init = FALSE;
147        }
148        break;
149
150    case NFA_EE_DISC_STS_REQ:
151        nfa_hci_cb.num_ee_dis_req_ntf++;
152
153        if (nfa_hci_cb.ee_disable_disc)
154        {
155            /* Already received Discovery Ntf */
156            if (  (nfa_hci_cb.hci_state == NFA_HCI_STATE_WAIT_NETWK_ENABLE)
157                ||(nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE_NETWK_ENABLE)  )
158            {
159                /* Received DISC REQ Ntf while waiting for other Host in the network to bootup after DH host bootup is complete */
160                if (nfa_hci_cb.num_ee_dis_req_ntf == (nfa_hci_cb.num_nfcee - 1))
161                {
162                    /* Received expected number of EE DISC REQ Ntf(s) */
163                    nfa_sys_stop_timer (&nfa_hci_cb.timer);
164                    nfa_hci_cb.w4_hci_netwk_init = FALSE;
165                    nfa_hciu_send_get_param_cmd (NFA_HCI_ADMIN_PIPE, NFA_HCI_HOST_LIST_INDEX);
166                }
167            }
168            else if (  (nfa_hci_cb.hci_state == NFA_HCI_STATE_STARTUP)
169                     ||(nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE)  )
170            {
171                /* Received DISC REQ Ntf during DH host bootup */
172                if (nfa_hci_cb.num_ee_dis_req_ntf == (nfa_hci_cb.num_nfcee - 1))
173                {
174                    /* Received expected number of EE DISC REQ Ntf(s) */
175                    nfa_hci_cb.w4_hci_netwk_init = FALSE;
176                }
177            }
178        }
179        break;
180    }
181}
182
183/*******************************************************************************
184**
185** Function         nfa_hci_init
186**
187** Description      Initialize NFA HCI
188**
189** Returns          None
190**
191*******************************************************************************/
192void nfa_hci_init (void)
193{
194    NFA_TRACE_DEBUG0 ("nfa_hci_init ()");
195
196    /* initialize control block */
197    memset (&nfa_hci_cb, 0, sizeof (tNFA_HCI_CB));
198
199    nfa_hci_cb.hci_state = NFA_HCI_STATE_STARTUP;
200
201    /* register message handler on NFA SYS */
202    nfa_sys_register (NFA_ID_HCI, &nfa_hci_sys_reg);
203}
204
205/*******************************************************************************
206**
207** Function         nfa_hci_is_valid_cfg
208**
209** Description      Validate hci control block config parameters
210**
211** Returns          None
212**
213*******************************************************************************/
214BOOLEAN nfa_hci_is_valid_cfg (void)
215{
216    UINT8       xx,yy,zz;
217    tNFA_HANDLE reg_app[NFA_HCI_MAX_APP_CB];
218    UINT8       valid_gate[NFA_HCI_MAX_GATE_CB];
219    UINT8       app_count       = 0;
220    UINT8       gate_count      = 0;
221    UINT32      pipe_inx_mask   = 0;
222
223    /* First, see if valid values are stored in app names, send connectivity events flag */
224    for (xx = 0; xx < NFA_HCI_MAX_APP_CB; xx++)
225    {
226        /* Check if app name is valid with null terminated string */
227        if (strlen (&nfa_hci_cb.cfg.reg_app_names[xx][0]) > NFA_MAX_HCI_APP_NAME_LEN)
228            return FALSE;
229
230        /* Send Connectivity event flag can be either TRUE or FALSE */
231        if (  (nfa_hci_cb.cfg.b_send_conn_evts[xx] != TRUE)
232            &&(nfa_hci_cb.cfg.b_send_conn_evts[xx] != FALSE))
233            return FALSE;
234
235        if (nfa_hci_cb.cfg.reg_app_names[xx][0] != 0)
236        {
237            /* Check if the app name is present more than one time in the control block */
238            for (yy = xx + 1; yy < NFA_HCI_MAX_APP_CB; yy++)
239            {
240                if (  (nfa_hci_cb.cfg.reg_app_names[yy][0] != 0)
241                    &&(!strncmp (&nfa_hci_cb.cfg.reg_app_names[xx][0], &nfa_hci_cb.cfg.reg_app_names[yy][0], strlen (nfa_hci_cb.cfg.reg_app_names[xx]))) )
242                {
243                    /* Two app cannot have the same name , NVRAM is corrupted */
244                    NFA_TRACE_EVENT2 ("nfa_hci_is_valid_cfg (%s)  Reusing: %u", &nfa_hci_cb.cfg.reg_app_names[xx][0], xx);
245                    return FALSE;
246                }
247            }
248            /* Collect list of hci handle */
249            reg_app[app_count++] = (tNFA_HANDLE) (xx | NFA_HANDLE_GROUP_HCI);
250        }
251    }
252
253    /* Validate Gate Control block */
254    for (xx = 0; xx < NFA_HCI_MAX_GATE_CB; xx++)
255    {
256        if (nfa_hci_cb.cfg.dyn_gates[xx].gate_id != 0)
257        {
258            if (  (  (nfa_hci_cb.cfg.dyn_gates[xx].gate_id != NFA_HCI_LOOP_BACK_GATE)
259                   &&(nfa_hci_cb.cfg.dyn_gates[xx].gate_id != NFA_HCI_IDENTITY_MANAGEMENT_GATE)
260                   &&(nfa_hci_cb.cfg.dyn_gates[xx].gate_id < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE))
261                ||(nfa_hci_cb.cfg.dyn_gates[xx].gate_id > NFA_HCI_LAST_PROP_GATE))
262                return FALSE;
263
264            /* Check if the same gate id is present more than once in the control block */
265            for (yy = xx + 1; yy < NFA_HCI_MAX_GATE_CB; yy++)
266            {
267                if (  (nfa_hci_cb.cfg.dyn_gates[yy].gate_id != 0)
268                    &&(nfa_hci_cb.cfg.dyn_gates[xx].gate_id == nfa_hci_cb.cfg.dyn_gates[yy].gate_id) )
269                {
270                    NFA_TRACE_EVENT1 ("nfa_hci_is_valid_cfg  Reusing: %u", nfa_hci_cb.cfg.dyn_gates[xx].gate_id);
271                    return FALSE;
272                }
273            }
274            if ((nfa_hci_cb.cfg.dyn_gates[xx].gate_owner & (~NFA_HANDLE_GROUP_HCI)) >= NFA_HCI_MAX_APP_CB)
275            {
276                NFA_TRACE_EVENT1 ("nfa_hci_is_valid_cfg  Invalid Gate owner: %u", nfa_hci_cb.cfg.dyn_gates[xx].gate_owner);
277                return FALSE;
278            }
279            if (nfa_hci_cb.cfg.dyn_gates[xx].gate_id != NFA_HCI_CONNECTIVITY_GATE)
280            {
281                /* The gate owner should be one of the registered application */
282                for (zz = 0; zz < app_count; zz++)
283                {
284                    if (nfa_hci_cb.cfg.dyn_gates[xx].gate_owner == reg_app[zz])
285                        break;
286                }
287                if (zz == app_count)
288                {
289                    NFA_TRACE_EVENT1 ("nfa_hci_is_valid_cfg  Invalid Gate owner: %u", nfa_hci_cb.cfg.dyn_gates[xx].gate_owner);
290                    return FALSE;
291                }
292            }
293            /* Collect list of allocated gates */
294            valid_gate[gate_count++] = nfa_hci_cb.cfg.dyn_gates[xx].gate_id;
295
296            /* No two gates can own a same pipe */
297            if ((pipe_inx_mask & nfa_hci_cb.cfg.dyn_gates[xx].pipe_inx_mask) != 0)
298                return FALSE;
299            /* Collect the list of pipes on this gate */
300            pipe_inx_mask |= nfa_hci_cb.cfg.dyn_gates[xx].pipe_inx_mask;
301        }
302    }
303
304    for (xx = 0; (pipe_inx_mask && (xx < NFA_HCI_MAX_PIPE_CB)); xx++,pipe_inx_mask >>= 1)
305    {
306        /* Every bit set in pipe increment mask indicates a valid pipe */
307        if (pipe_inx_mask & 1)
308        {
309            /* Check if the pipe is valid one */
310            if (nfa_hci_cb.cfg.dyn_pipes[xx].pipe_id < NFA_HCI_FIRST_DYNAMIC_PIPE)
311                return FALSE;
312        }
313    }
314
315    if (xx == NFA_HCI_MAX_PIPE_CB)
316        return FALSE;
317
318    /* Validate Gate Control block */
319    for (xx = 0; xx < NFA_HCI_MAX_PIPE_CB; xx++)
320    {
321        if (nfa_hci_cb.cfg.dyn_pipes[xx].pipe_id != 0)
322        {
323            /* Check if pipe id is valid */
324            if (nfa_hci_cb.cfg.dyn_pipes[xx].pipe_id < NFA_HCI_FIRST_DYNAMIC_PIPE)
325                return FALSE;
326
327            /* Check if pipe state is valid */
328            if (  (nfa_hci_cb.cfg.dyn_pipes[xx].pipe_state != NFA_HCI_PIPE_OPENED)
329                &&(nfa_hci_cb.cfg.dyn_pipes[xx].pipe_state != NFA_HCI_PIPE_CLOSED))
330                return FALSE;
331
332            /* Check if local gate on which the pipe is created is valid */
333            if (  (((nfa_hci_cb.cfg.dyn_pipes[xx].local_gate != NFA_HCI_LOOP_BACK_GATE) && (nfa_hci_cb.cfg.dyn_pipes[xx].local_gate != NFA_HCI_IDENTITY_MANAGEMENT_GATE)) && (nfa_hci_cb.cfg.dyn_pipes[xx].local_gate < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE))
334                ||(nfa_hci_cb.cfg.dyn_pipes[xx].local_gate > NFA_HCI_LAST_PROP_GATE))
335                return FALSE;
336
337            /* Check if the peer gate on which the pipe is created is valid */
338            if (  (((nfa_hci_cb.cfg.dyn_pipes[xx].dest_gate != NFA_HCI_LOOP_BACK_GATE) && (nfa_hci_cb.cfg.dyn_pipes[xx].dest_gate != NFA_HCI_IDENTITY_MANAGEMENT_GATE)) && (nfa_hci_cb.cfg.dyn_pipes[xx].dest_gate < NFA_HCI_FIRST_HOST_SPECIFIC_GENERIC_GATE))
339                ||(nfa_hci_cb.cfg.dyn_pipes[xx].dest_gate > NFA_HCI_LAST_PROP_GATE))
340                return FALSE;
341
342            /* Check if the same pipe is present more than once in the control block */
343            for (yy = xx + 1; yy < NFA_HCI_MAX_PIPE_CB; yy++)
344            {
345                if (  (nfa_hci_cb.cfg.dyn_pipes[yy].pipe_id != 0)
346                    &&(nfa_hci_cb.cfg.dyn_pipes[xx].pipe_id == nfa_hci_cb.cfg.dyn_pipes[yy].pipe_id) )
347                {
348                    NFA_TRACE_EVENT1 ("nfa_hci_is_valid_cfg  Reusing: %u", nfa_hci_cb.cfg.dyn_pipes[xx].pipe_id);
349                    return FALSE;
350                }
351            }
352            /* The local gate should be one of the element in gate control block */
353            for (zz = 0; zz < gate_count; zz++)
354            {
355                if (nfa_hci_cb.cfg.dyn_pipes[xx].local_gate == valid_gate[zz])
356                    break;
357            }
358            if (zz == gate_count)
359            {
360                NFA_TRACE_EVENT1 ("nfa_hci_is_valid_cfg  Invalid Gate: %u", nfa_hci_cb.cfg.dyn_pipes[xx].local_gate);
361                return FALSE;
362            }
363        }
364    }
365
366    /* Check if admin pipe state is valid */
367    if (  (nfa_hci_cb.cfg.admin_gate.pipe01_state != NFA_HCI_PIPE_OPENED)
368        &&(nfa_hci_cb.cfg.admin_gate.pipe01_state != NFA_HCI_PIPE_CLOSED))
369        return FALSE;
370
371    /* Check if link management pipe state is valid */
372    if (  (nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state != NFA_HCI_PIPE_OPENED)
373        &&(nfa_hci_cb.cfg.link_mgmt_gate.pipe00_state != NFA_HCI_PIPE_CLOSED))
374        return FALSE;
375
376    pipe_inx_mask = nfa_hci_cb.cfg.id_mgmt_gate.pipe_inx_mask;
377    for (xx = 0; (pipe_inx_mask && (xx < NFA_HCI_MAX_PIPE_CB)); xx++,pipe_inx_mask >>= 1)
378    {
379        /* Every bit set in pipe increment mask indicates a valid pipe */
380        if (pipe_inx_mask & 1)
381        {
382            /* Check if the pipe is valid one */
383            if (nfa_hci_cb.cfg.dyn_pipes[xx].pipe_id < NFA_HCI_FIRST_DYNAMIC_PIPE)
384                return FALSE;
385            /* Check if the pipe is connected to Identity management gate */
386            if (nfa_hci_cb.cfg.dyn_pipes[xx].local_gate != NFA_HCI_IDENTITY_MANAGEMENT_GATE)
387                return FALSE;
388        }
389    }
390    if (xx == NFA_HCI_MAX_PIPE_CB)
391        return FALSE;
392
393    return TRUE;
394}
395
396/*******************************************************************************
397**
398** Function         nfa_hci_cfg_default
399**
400** Description      Configure default values for hci control block
401**
402** Returns          None
403**
404*******************************************************************************/
405void nfa_hci_restore_default_config (UINT8 *p_session_id)
406{
407    memset (&nfa_hci_cb.cfg, 0, sizeof (nfa_hci_cb.cfg));
408    memcpy (nfa_hci_cb.cfg.admin_gate.session_id, p_session_id, NFA_HCI_SESSION_ID_LEN);
409    nfa_hci_cb.nv_write_needed = TRUE;
410}
411
412/*******************************************************************************
413**
414** Function         nfa_hci_proc_nfcc_power_mode
415**
416** Description      Restore NFA HCI sub-module
417**
418** Returns          None
419**
420*******************************************************************************/
421void nfa_hci_proc_nfcc_power_mode (UINT8 nfcc_power_mode)
422{
423    NFA_TRACE_DEBUG1 ("nfa_hci_proc_nfcc_power_mode () nfcc_power_mode=%d", nfcc_power_mode);
424
425    /* if NFCC power mode is change to full power */
426    if (nfcc_power_mode == NFA_DM_PWR_MODE_FULL)
427    {
428        nfa_hci_cb.b_low_power_mode = FALSE;
429        if (nfa_hci_cb.hci_state == NFA_HCI_STATE_IDLE)
430        {
431            nfa_hci_cb.hci_state          = NFA_HCI_STATE_RESTORE;
432            nfa_hci_cb.ee_disc_cmplt      = FALSE;
433            nfa_hci_cb.ee_disable_disc    = TRUE;
434            if (nfa_hci_cb.num_nfcee > 1)
435                nfa_hci_cb.w4_hci_netwk_init  = TRUE;
436            else
437                nfa_hci_cb.w4_hci_netwk_init  = FALSE;
438            nfa_hci_cb.conn_id            = 0;
439            nfa_hci_cb.num_ee_dis_req_ntf = 0;
440            nfa_hci_cb.num_hot_plug_evts  = 0;
441        }
442        else
443        {
444            NFA_TRACE_ERROR0 ("nfa_hci_proc_nfcc_power_mode (): Cannot restore now");
445            nfa_sys_cback_notify_nfcc_power_mode_proc_complete (NFA_ID_HCI);
446        }
447    }
448    else
449    {
450        nfa_hci_cb.hci_state     = NFA_HCI_STATE_IDLE;
451        nfa_hci_cb.w4_rsp_evt    = FALSE;
452        nfa_hci_cb.conn_id       = 0;
453        nfa_sys_stop_timer (&nfa_hci_cb.timer);
454        nfa_hci_cb.b_low_power_mode = TRUE;
455        nfa_sys_cback_notify_nfcc_power_mode_proc_complete (NFA_ID_HCI);
456    }
457}
458
459/*******************************************************************************
460**
461** Function         nfa_hci_dh_startup_complete
462**
463** Description      Initialization of terminal host in HCI Network is completed
464**                  Wait for other host in the network to initialize
465**
466** Returns          None
467**
468*******************************************************************************/
469void nfa_hci_dh_startup_complete (void)
470{
471    if (nfa_hci_cb.w4_hci_netwk_init)
472    {
473        if (nfa_hci_cb.hci_state == NFA_HCI_STATE_STARTUP)
474        {
475            nfa_hci_cb.hci_state = NFA_HCI_STATE_WAIT_NETWK_ENABLE;
476            /* Wait for EE Discovery to complete */
477            nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, NFA_EE_DISCV_TIMEOUT_VAL);
478        }
479        else if (nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE)
480        {
481            nfa_hci_cb.hci_state = NFA_HCI_STATE_RESTORE_NETWK_ENABLE;
482            /* No HCP packet to DH for a specified period of time indicates all host in the network is initialized */
483            nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, p_nfa_hci_cfg->hci_netwk_enable_timeout);
484        }
485    }
486    else if (  (nfa_hci_cb.num_nfcee > 1)
487             &&(nfa_hci_cb.num_ee_dis_req_ntf != (nfa_hci_cb.num_nfcee - 1))  )
488    {
489        if (nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE)
490            nfa_hci_cb.ee_disable_disc  = TRUE;
491        /* Received HOT PLUG EVT, we will also wait for EE DISC REQ Ntf(s) */
492        nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, p_nfa_hci_cfg->hci_netwk_enable_timeout);
493    }
494    else
495    {
496        /* Received EE DISC REQ Ntf(s) */
497        nfa_hciu_send_get_param_cmd (NFA_HCI_ADMIN_PIPE, NFA_HCI_HOST_LIST_INDEX);
498    }
499}
500
501/*******************************************************************************
502**
503** Function         nfa_hci_startup_complete
504**
505** Description      HCI network initialization is completed
506**
507** Returns          None
508**
509*******************************************************************************/
510void nfa_hci_startup_complete (tNFA_STATUS status)
511{
512    tNFA_HCI_EVT_DATA   evt_data;
513
514    NFA_TRACE_EVENT1 ("nfa_hci_startup_complete (): Status: %u", status);
515
516    nfa_sys_stop_timer (&nfa_hci_cb.timer);
517
518    if (  (nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE)
519        ||(nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE_NETWK_ENABLE)  )
520    {
521        nfa_ee_proc_hci_info_cback ();
522        nfa_sys_cback_notify_nfcc_power_mode_proc_complete (NFA_ID_HCI);
523    }
524    else
525    {
526        evt_data.hci_init.status = status;
527
528        nfa_hciu_send_to_all_apps (NFA_HCI_INIT_EVT, &evt_data);
529        nfa_sys_cback_notify_enable_complete (NFA_ID_HCI);
530    }
531
532    if (status == NFA_STATUS_OK)
533        nfa_hci_cb.hci_state = NFA_HCI_STATE_IDLE;
534
535    else
536        nfa_hci_cb.hci_state = NFA_HCI_STATE_DISABLED;
537}
538
539/*******************************************************************************
540**
541** Function         nfa_hci_startup
542**
543** Description      Perform HCI startup
544**
545** Returns          None
546**
547*******************************************************************************/
548void nfa_hci_startup (void)
549{
550    tNFA_STATUS     status = NFA_STATUS_FAILED;
551    tNFA_EE_INFO    ee_info[2];
552    UINT8           num_nfcee = 2;
553    UINT8           target_handle;
554    UINT8           count = 0;
555    BOOLEAN         found = FALSE;
556
557    if (HCI_LOOPBACK_DEBUG)
558    {
559        /* First step in initialization is to open the admin pipe */
560        nfa_hciu_send_open_pipe_cmd (NFA_HCI_ADMIN_PIPE);
561        return;
562    }
563
564    /* We can only start up if NV Ram is read and EE discovery is complete */
565    if (nfa_hci_cb.nv_read_cmplt && nfa_hci_cb.ee_disc_cmplt && (nfa_hci_cb.conn_id == 0))
566    {
567        NFA_EeGetInfo (&num_nfcee, ee_info);
568
569        while ((count < num_nfcee) && (!found))
570        {
571            target_handle = (UINT8) ee_info[count].ee_handle;
572
573            if(ee_info[count].ee_interface[0] == NFA_EE_INTERFACE_HCI_ACCESS)
574            {
575                found = TRUE;
576
577                if (ee_info[count].ee_status == NFA_EE_STATUS_INACTIVE)
578                {
579                    NFC_NfceeModeSet (target_handle, NFC_MODE_ACTIVATE);
580                }
581                if ((status = NFC_ConnCreate (NCI_DEST_TYPE_NFCEE, target_handle, NFA_EE_INTERFACE_HCI_ACCESS, nfa_hci_conn_cback)) == NFA_STATUS_OK)
582                    nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, NFA_HCI_CON_CREATE_TIMEOUT_VAL);
583                else
584                {
585                    nfa_hci_cb.hci_state = NFA_HCI_STATE_DISABLED;
586                    NFA_TRACE_ERROR0 ("nfa_hci_startup - Failed to Create Logical connection. HCI Initialization/Restore failed");
587                    nfa_hci_startup_complete (NFA_STATUS_FAILED);
588                }
589            }
590            count++;
591        }
592        if (!found)
593        {
594            NFA_TRACE_ERROR0 ("nfa_hci_startup - HCI ACCESS Interface not discovered. HCI Initialization/Restore failed");
595            nfa_hci_startup_complete (NFA_STATUS_FAILED);
596        }
597    }
598}
599
600/*******************************************************************************
601**
602** Function         nfa_hci_sys_enable
603**
604** Description      Enable NFA HCI
605**
606** Returns          None
607**
608*******************************************************************************/
609static void nfa_hci_sys_enable (void)
610{
611    NFA_TRACE_DEBUG0 ("nfa_hci_sys_enable ()");
612    nfa_ee_reg_cback_enable_done (&nfa_hci_ee_info_cback);
613
614    nfa_nv_co_read ((UINT8 *)&nfa_hci_cb.cfg, sizeof (nfa_hci_cb.cfg),DH_NV_BLOCK);
615    nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, NFA_HCI_NV_READ_TIMEOUT_VAL);
616}
617
618/*******************************************************************************
619**
620** Function         nfa_hci_sys_disable
621**
622** Description      Disable NFA HCI
623**
624** Returns          None
625**
626*******************************************************************************/
627static void nfa_hci_sys_disable (void)
628{
629    tNFA_HCI_EVT_DATA   evt_data;
630
631    nfa_sys_stop_timer (&nfa_hci_cb.timer);
632
633    if (nfa_hci_cb.conn_id)
634    {
635        if (nfa_sys_is_graceful_disable ())
636        {
637            /* Tell all applications stack is down */
638            nfa_hciu_send_to_all_apps (NFA_HCI_EXIT_EVT, &evt_data);
639            NFC_ConnClose (nfa_hci_cb.conn_id);
640            return;
641        }
642        nfa_hci_cb.conn_id = 0;
643    }
644
645    nfa_hci_cb.hci_state = NFA_HCI_STATE_DISABLED;
646    /* deregister message handler on NFA SYS */
647    nfa_sys_deregister (NFA_ID_HCI);
648}
649
650/*******************************************************************************
651**
652** Function         nfa_hci_conn_cback
653**
654** Description      This function Process event from NCI
655**
656** Returns          None
657**
658*******************************************************************************/
659static void nfa_hci_conn_cback (UINT8 conn_id, tNFC_CONN_EVT event, tNFC_CONN *p_data)
660{
661    UINT8   *p;
662    BT_HDR  *p_pkt = (BT_HDR *) p_data->data.p_data;
663    UINT8   chaining_bit;
664    UINT8   pipe;
665    UINT16  pkt_len;
666#if (BT_TRACE_VERBOSE == TRUE)
667    char    buff[100];
668#endif
669
670    if (event == NFC_CONN_CREATE_CEVT)
671    {
672        nfa_hci_cb.conn_id   = conn_id;
673        nfa_hci_cb.buff_size = p_data->conn_create.buff_size;
674
675        if (nfa_hci_cb.hci_state == NFA_HCI_STATE_STARTUP)
676        {
677            nfa_hci_cb.w4_hci_netwk_init = TRUE;
678            nfa_hciu_alloc_gate (NFA_HCI_CONNECTIVITY_GATE,0);
679        }
680
681        if (nfa_hci_cb.cfg.admin_gate.pipe01_state == NFA_HCI_PIPE_CLOSED)
682        {
683            /* First step in initialization/restore is to open the admin pipe */
684            nfa_hciu_send_open_pipe_cmd (NFA_HCI_ADMIN_PIPE);
685        }
686        else
687        {
688            /* Read session id, to know DH session id is correct */
689            nfa_hciu_send_get_param_cmd (NFA_HCI_ADMIN_PIPE, NFA_HCI_SESSION_IDENTITY_INDEX);
690        }
691    }
692    else if (event == NFC_CONN_CLOSE_CEVT)
693    {
694        nfa_hci_cb.conn_id   = 0;
695        nfa_hci_cb.hci_state = NFA_HCI_STATE_DISABLED;
696        /* deregister message handler on NFA SYS */
697        nfa_sys_deregister (NFA_ID_HCI);
698    }
699
700    if ((event != NFC_DATA_CEVT) || (p_pkt == NULL))
701            return;
702
703    if (  (nfa_hci_cb.hci_state == NFA_HCI_STATE_WAIT_NETWK_ENABLE)
704        ||(nfa_hci_cb.hci_state == NFA_HCI_STATE_RESTORE_NETWK_ENABLE)  )
705    {
706        /* Received HCP Packet before timeout, Other Host initialization is not complete */
707        nfa_sys_stop_timer (&nfa_hci_cb.timer);
708        if (nfa_hci_cb.w4_hci_netwk_init)
709            nfa_sys_start_timer (&nfa_hci_cb.timer, NFA_HCI_RSP_TIMEOUT_EVT, p_nfa_hci_cfg->hci_netwk_enable_timeout);
710    }
711
712    p       = (UINT8 *) (p_pkt + 1) + p_pkt->offset;
713    pkt_len = p_pkt->len;
714
715#if (BT_TRACE_PROTOCOL == TRUE)
716    DispHcp (p, pkt_len, TRUE, (BOOLEAN) !nfa_hci_cb.assembling);
717#endif
718
719    chaining_bit = ((*p) >> 0x07) & 0x01;
720    pipe = (*p++) & 0x7F;
721    if (pkt_len != 0)
722        pkt_len--;
723
724    if (nfa_hci_cb.assembling == FALSE)
725    {
726        /* First Segment of a packet */
727        nfa_hci_cb.type            = ((*p) >> 0x06) & 0x03;
728        nfa_hci_cb.inst            = (*p++ & 0x3F);
729        if (pkt_len != 0)
730            pkt_len--;
731        nfa_hci_cb.assembly_failed = FALSE;
732        nfa_hci_cb.msg_len         = 0;
733
734        if (chaining_bit == NFA_HCI_MESSAGE_FRAGMENTATION)
735        {
736            nfa_hci_cb.assembling = TRUE;
737            nfa_hci_set_receive_buf (pipe);
738            nfa_hci_assemble_msg (p, pkt_len);
739        }
740        else
741        {
742            if ((pipe >= NFA_HCI_FIRST_DYNAMIC_PIPE) && (nfa_hci_cb.type == NFA_HCI_EVENT_TYPE))
743            {
744                nfa_hci_set_receive_buf (pipe);
745                nfa_hci_assemble_msg (p, pkt_len);
746                p = nfa_hci_cb.p_msg_data;
747            }
748        }
749    }
750    else
751    {
752        if (nfa_hci_cb.assembly_failed)
753        {
754            /* If Reassembly failed because of insufficient buffer, just drop the new segmented packets */
755            NFA_TRACE_ERROR1 ("nfa_hci_conn_cback (): Insufficient buffer to Reassemble HCP packet! Dropping :%u bytes", pkt_len);
756        }
757        else
758        {
759            /* Reassemble the packet */
760            nfa_hci_assemble_msg (p, pkt_len);
761        }
762
763        if (chaining_bit == NFA_HCI_NO_MESSAGE_FRAGMENTATION)
764        {
765            /* Just added the last segment in the chain. Reset pointers */
766            nfa_hci_cb.assembling = FALSE;
767            p                     = nfa_hci_cb.p_msg_data;
768            pkt_len               = nfa_hci_cb.msg_len;
769        }
770    }
771
772#if (BT_TRACE_VERBOSE == TRUE)
773    NFA_TRACE_EVENT5 ("nfa_hci_conn_cback Recvd data pipe:%d  %s  chain:%d  assmbl:%d  len:%d",
774                      (UINT8)pipe, nfa_hciu_get_type_inst_names (pipe, nfa_hci_cb.type, nfa_hci_cb.inst, buff),
775                      (UINT8)chaining_bit, (UINT8)nfa_hci_cb.assembling, p_pkt->len);
776#else
777    NFA_TRACE_EVENT6 ("nfa_hci_conn_cback Recvd data pipe:%d  Type: %u  Inst: %u  chain:%d reassm:%d len:%d",
778                      pipe, nfa_hci_cb.type, nfa_hci_cb.inst, chaining_bit, nfa_hci_cb.assembling, p_pkt->len);
779#endif
780
781
782    /* If still reassembling fragments, just return */
783    if (nfa_hci_cb.assembling)
784    {
785        /* if not last packet, release GKI buffer */
786        GKI_freebuf (p_pkt);
787        return;
788    }
789
790    /* If we got a response, cancel the response timer. Also, if waiting for */
791    /* a single response, we can go back to idle state                       */
792    if (  (nfa_hci_cb.hci_state == NFA_HCI_STATE_WAIT_RSP)
793        &&((nfa_hci_cb.type == NFA_HCI_RESPONSE_TYPE) || (nfa_hci_cb.w4_rsp_evt && (nfa_hci_cb.type == NFA_HCI_EVENT_TYPE)))  )
794    {
795        nfa_sys_stop_timer (&nfa_hci_cb.timer);
796        nfa_hci_cb.hci_state  = NFA_HCI_STATE_IDLE;
797    }
798
799    switch (pipe)
800    {
801    case NFA_HCI_ADMIN_PIPE:
802        /* Check if data packet is a command, response or event */
803        if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE)
804        {
805            nfa_hci_handle_admin_gate_cmd (p);
806        }
807            else if (nfa_hci_cb.type == NFA_HCI_RESPONSE_TYPE)
808        {
809            nfa_hci_handle_admin_gate_rsp (p, (UINT8) pkt_len);
810        }
811        else if (nfa_hci_cb.type == NFA_HCI_EVENT_TYPE)
812        {
813            nfa_hci_handle_admin_gate_evt (p);
814        }
815        break;
816
817    case NFA_HCI_LINK_MANAGEMENT_PIPE:
818        /* We don't send Link Management commands, we only get them */
819        if (nfa_hci_cb.type == NFA_HCI_COMMAND_TYPE)
820            nfa_hci_handle_link_mgm_gate_cmd (p);
821        break;
822
823    default:
824        if (pipe >= NFA_HCI_FIRST_DYNAMIC_PIPE)
825            nfa_hci_handle_dyn_pipe_pkt (pipe, p, pkt_len);
826        break;
827    }
828
829    if ((nfa_hci_cb.type == NFA_HCI_RESPONSE_TYPE) || (nfa_hci_cb.w4_rsp_evt && (nfa_hci_cb.type == NFA_HCI_EVENT_TYPE)))
830    {
831        nfa_hci_cb.w4_rsp_evt = FALSE;
832    }
833
834    /* Send a message to ouselves to check for anything to do */
835    p_pkt->event = NFA_HCI_CHECK_QUEUE_EVT;
836    p_pkt->len   = 0;
837    nfa_sys_sendmsg (p_pkt);
838}
839
840/*******************************************************************************
841**
842** Function         nfa_hci_handle_nv_read
843**
844** Description      handler function for nv read complete event
845**
846** Returns          None
847**
848*******************************************************************************/
849void nfa_hci_handle_nv_read (UINT8 block, tNFA_STATUS status)
850{
851    UINT8   session_id[NFA_HCI_SESSION_ID_LEN];
852    UINT8   default_session[NFA_HCI_SESSION_ID_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
853    UINT8   reset_session[NFA_HCI_SESSION_ID_LEN]   = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
854    UINT32  os_tick;
855
856    if (block == DH_NV_BLOCK)
857    {
858        /* Stop timer as NVDATA Read Completed */
859        nfa_sys_stop_timer (&nfa_hci_cb.timer);
860        nfa_hci_cb.nv_read_cmplt = TRUE;
861        if (  (status != NFA_STATUS_OK)
862            ||(!nfa_hci_is_valid_cfg ())
863            ||(!(memcmp (nfa_hci_cb.cfg.admin_gate.session_id, default_session, NFA_HCI_SESSION_ID_LEN)))
864            ||(!(memcmp (nfa_hci_cb.cfg.admin_gate.session_id, reset_session, NFA_HCI_SESSION_ID_LEN)))  )
865        {
866            nfa_hci_cb.b_hci_netwk_reset = TRUE;
867            /* Set a new session id so that we clear all pipes later after seeing a difference with the HC Session ID */
868            memcpy (&session_id[(NFA_HCI_SESSION_ID_LEN / 2)], nfa_hci_cb.cfg.admin_gate.session_id, (NFA_HCI_SESSION_ID_LEN / 2));
869            os_tick = GKI_get_os_tick_count ();
870            memcpy (session_id, (UINT8 *)&os_tick, (NFA_HCI_SESSION_ID_LEN / 2));
871            nfa_hci_restore_default_config (session_id);
872        }
873        nfa_hci_startup ();
874    }
875}
876
877/*******************************************************************************
878**
879** Function         nfa_hci_rsp_timeout
880**
881** Description      action function to process timeout
882**
883** Returns          None
884**
885*******************************************************************************/
886void nfa_hci_rsp_timeout (tNFA_HCI_EVENT_DATA *p_evt_data)
887{
888    tNFA_HCI_EVT        evt = 0;
889    tNFA_HCI_EVT_DATA   evt_data;
890    UINT8               delete_pipe;
891
892    NFA_TRACE_EVENT2 ("nfa_hci_rsp_timeout () State: %u  Cmd: %u", nfa_hci_cb.hci_state, nfa_hci_cb.cmd_sent);
893
894    evt_data.status      = NFA_STATUS_FAILED;
895
896    switch (nfa_hci_cb.hci_state)
897    {
898    case NFA_HCI_STATE_STARTUP:
899    case NFA_HCI_STATE_RESTORE:
900        NFA_TRACE_ERROR0 ("nfa_hci_rsp_timeout - Initialization failed!");
901        nfa_hci_startup_complete (NFA_STATUS_TIMEOUT);
902        break;
903
904    case NFA_HCI_STATE_WAIT_NETWK_ENABLE:
905    case NFA_HCI_STATE_RESTORE_NETWK_ENABLE:
906
907        if (nfa_hci_cb.w4_hci_netwk_init)
908        {
909            /* HCI Network is enabled */
910            nfa_hci_cb.w4_hci_netwk_init = FALSE;
911            nfa_hciu_send_get_param_cmd (NFA_HCI_ADMIN_PIPE, NFA_HCI_HOST_LIST_INDEX);
912        }
913        else
914        {
915            nfa_hci_startup_complete (NFA_STATUS_FAILED);
916        }
917        break;
918
919    case NFA_HCI_STATE_REMOVE_GATE:
920        /* Something wrong, NVRAM data could be corrupt */
921        if (nfa_hci_cb.cmd_sent == NFA_HCI_ADM_DELETE_PIPE)
922        {
923            nfa_hciu_send_clear_all_pipe_cmd ();
924        }
925        else
926        {
927            nfa_hciu_remove_all_pipes_from_host (0);
928            nfa_hci_api_dealloc_gate (NULL);
929        }
930        break;
931
932    case NFA_HCI_STATE_APP_DEREGISTER:
933        /* Something wrong, NVRAM data could be corrupt */
934        if (nfa_hci_cb.cmd_sent == NFA_HCI_ADM_DELETE_PIPE)
935        {
936            nfa_hciu_send_clear_all_pipe_cmd ();
937        }
938        else
939        {
940            nfa_hciu_remove_all_pipes_from_host (0);
941            nfa_hci_api_deregister (NULL);
942        }
943        break;
944
945    case NFA_HCI_STATE_WAIT_RSP:
946        nfa_hci_cb.hci_state = NFA_HCI_STATE_IDLE;
947
948        if (nfa_hci_cb.w4_rsp_evt)
949        {
950            nfa_hci_cb.w4_rsp_evt       = FALSE;
951            evt                         = NFA_HCI_EVENT_RCVD_EVT;
952            evt_data.rcvd_evt.pipe      = nfa_hci_cb.pipe_in_use;
953            evt_data.rcvd_evt.evt_code  = 0;
954            evt_data.rcvd_evt.evt_len   = 0;
955            evt_data.rcvd_evt.p_evt_buf = NULL;
956            nfa_hci_cb.rsp_buf_size     = 0;
957            nfa_hci_cb.p_rsp_buf        = NULL;
958
959            break;
960        }
961
962        delete_pipe          = 0;
963        switch (nfa_hci_cb.cmd_sent)
964        {
965        case NFA_HCI_ANY_SET_PARAMETER:
966            /*
967             * As no response to the command sent on this pipe, we may assume the pipe is
968             * deleted already and release the pipe. But still send delete pipe command to be safe.
969             */
970            delete_pipe                = nfa_hci_cb.pipe_in_use;
971            evt_data.registry.pipe     = nfa_hci_cb.pipe_in_use;
972            evt_data.registry.data_len = 0;
973            evt_data.registry.index    = nfa_hci_cb.param_in_use;
974            evt                        = NFA_HCI_SET_REG_RSP_EVT;
975            break;
976
977        case NFA_HCI_ANY_GET_PARAMETER:
978            /*
979             * As no response to the command sent on this pipe, we may assume the pipe is
980             * deleted already and release the pipe. But still send delete pipe command to be safe.
981             */
982            delete_pipe                = nfa_hci_cb.pipe_in_use;
983            evt_data.registry.pipe     = nfa_hci_cb.pipe_in_use;
984            evt_data.registry.data_len = 0;
985            evt_data.registry.index    = nfa_hci_cb.param_in_use;
986            evt                        = NFA_HCI_GET_REG_RSP_EVT;
987            break;
988
989        case NFA_HCI_ANY_OPEN_PIPE:
990            /*
991             * As no response to the command sent on this pipe, we may assume the pipe is
992             * deleted already and release the pipe. But still send delete pipe command to be safe.
993             */
994            delete_pipe          = nfa_hci_cb.pipe_in_use;
995            evt_data.opened.pipe = nfa_hci_cb.pipe_in_use;
996            evt                  = NFA_HCI_OPEN_PIPE_EVT;
997            break;
998
999        case NFA_HCI_ANY_CLOSE_PIPE:
1000            /*
1001             * As no response to the command sent on this pipe, we may assume the pipe is
1002             * deleted already and release the pipe. But still send delete pipe command to be safe.
1003             */
1004            delete_pipe          = nfa_hci_cb.pipe_in_use;
1005            evt_data.closed.pipe = nfa_hci_cb.pipe_in_use;
1006            evt                  = NFA_HCI_CLOSE_PIPE_EVT;
1007            break;
1008
1009        case NFA_HCI_ADM_CREATE_PIPE:
1010            evt_data.created.pipe        = nfa_hci_cb.pipe_in_use;
1011            evt_data.created.source_gate = nfa_hci_cb.local_gate_in_use;
1012            evt_data.created.dest_host   = nfa_hci_cb.remote_host_in_use;
1013            evt_data.created.dest_gate   = nfa_hci_cb.remote_gate_in_use;
1014            evt                          = NFA_HCI_CREATE_PIPE_EVT;
1015            break;
1016
1017        case NFA_HCI_ADM_DELETE_PIPE:
1018            /*
1019             * As no response to the command sent on this pipe, we may assume the pipe is
1020             * deleted already. Just release the pipe.
1021             */
1022            if (nfa_hci_cb.pipe_in_use <= NFA_HCI_LAST_DYNAMIC_PIPE)
1023                nfa_hciu_release_pipe (nfa_hci_cb.pipe_in_use);
1024            evt_data.deleted.pipe = nfa_hci_cb.pipe_in_use;
1025            evt                   = NFA_HCI_DELETE_PIPE_EVT;
1026            break;
1027
1028        default:
1029            /*
1030             * As no response to the command sent on this pipe, we may assume the pipe is
1031             * deleted already and release the pipe. But still send delete pipe command to be safe.
1032             */
1033            delete_pipe                = nfa_hci_cb.pipe_in_use;
1034            break;
1035        }
1036        if (delete_pipe && (delete_pipe <= NFA_HCI_LAST_DYNAMIC_PIPE))
1037        {
1038            nfa_hciu_send_delete_pipe_cmd (delete_pipe);
1039            nfa_hciu_release_pipe (delete_pipe);
1040        }
1041        break;
1042    case NFA_HCI_STATE_DISABLED:
1043    default:
1044        NFA_TRACE_DEBUG0 ("nfa_hci_rsp_timeout () Timeout in DISABLED/ Invalid state");
1045        break;
1046    }
1047    if (evt != 0)
1048        nfa_hciu_send_to_app (evt, &evt_data, nfa_hci_cb.app_in_use);
1049}
1050
1051/*******************************************************************************
1052**
1053** Function         nfa_hci_set_receive_buf
1054**
1055** Description      Set reassembly buffer for incoming message
1056**
1057** Returns          status
1058**
1059*******************************************************************************/
1060static void nfa_hci_set_receive_buf (UINT8 pipe)
1061{
1062    if (  (pipe >= NFA_HCI_FIRST_DYNAMIC_PIPE)
1063        &&(nfa_hci_cb.type == NFA_HCI_EVENT_TYPE)  )
1064    {
1065        if (  (nfa_hci_cb.rsp_buf_size)
1066            &&(nfa_hci_cb.p_rsp_buf != NULL)  )
1067        {
1068            nfa_hci_cb.p_msg_data  = nfa_hci_cb.p_rsp_buf;
1069            nfa_hci_cb.max_msg_len = nfa_hci_cb.rsp_buf_size;
1070            return;
1071        }
1072    }
1073    nfa_hci_cb.p_msg_data  = nfa_hci_cb.msg_data;
1074    nfa_hci_cb.max_msg_len = NFA_MAX_HCI_EVENT_LEN;
1075}
1076
1077/*******************************************************************************
1078**
1079** Function         nfa_hci_assemble_msg
1080**
1081** Description      Reassemble the incoming message
1082**
1083** Returns          None
1084**
1085*******************************************************************************/
1086static void nfa_hci_assemble_msg (UINT8 *p_data, UINT16 data_len)
1087{
1088    if ((nfa_hci_cb.msg_len + data_len) > nfa_hci_cb.max_msg_len)
1089    {
1090        /* Fill the buffer as much it can hold */
1091        memcpy (&nfa_hci_cb.p_msg_data[nfa_hci_cb.msg_len], p_data, (nfa_hci_cb.max_msg_len - nfa_hci_cb.msg_len));
1092        nfa_hci_cb.msg_len         = nfa_hci_cb.max_msg_len;
1093        /* Set Reassembly failed */
1094        nfa_hci_cb.assembly_failed = TRUE;
1095        NFA_TRACE_ERROR1 ("nfa_hci_assemble_msg (): Insufficient buffer to Reassemble HCP packet! Dropping :%u bytes", ((nfa_hci_cb.msg_len + data_len) - nfa_hci_cb.max_msg_len));
1096    }
1097    else
1098    {
1099        memcpy (&nfa_hci_cb.p_msg_data[nfa_hci_cb.msg_len], p_data, data_len);
1100        nfa_hci_cb.msg_len += data_len;
1101    }
1102}
1103
1104/*******************************************************************************
1105**
1106** Function         nfa_hci_evt_hdlr
1107**
1108** Description      Processing all event for NFA HCI
1109**
1110** Returns          TRUE if p_msg needs to be deallocated
1111**
1112*******************************************************************************/
1113static BOOLEAN nfa_hci_evt_hdlr (BT_HDR *p_msg)
1114{
1115    tNFA_HCI_EVENT_DATA *p_evt_data = (tNFA_HCI_EVENT_DATA *)p_msg;
1116
1117#if (BT_TRACE_VERBOSE == TRUE)
1118    NFA_TRACE_EVENT4 ("nfa_hci_evt_hdlr state: %s (%d) event: %s (0x%04x)",
1119                      nfa_hciu_get_state_name (nfa_hci_cb.hci_state), nfa_hci_cb.hci_state,
1120                      nfa_hciu_get_event_name (p_evt_data->hdr.event), p_evt_data->hdr.event);
1121#else
1122    NFA_TRACE_EVENT2 ("nfa_hci_evt_hdlr state: %d event: 0x%04x", nfa_hci_cb.hci_state, p_evt_data->hdr.event);
1123#endif
1124
1125    /* If this is an API request, queue it up */
1126    if ((p_msg->event >= NFA_HCI_FIRST_API_EVENT) && (p_msg->event <= NFA_HCI_LAST_API_EVENT))
1127    {
1128        GKI_enqueue (&nfa_hci_cb.hci_api_q, p_msg);
1129    }
1130    else
1131    {
1132        switch (p_msg->event)
1133        {
1134        case NFA_HCI_RSP_NV_READ_EVT:
1135            nfa_hci_handle_nv_read (p_evt_data->nv_read.block, p_evt_data->nv_read.status);
1136            break;
1137
1138        case NFA_HCI_RSP_NV_WRITE_EVT:
1139            /* NV Ram write completed - nothing to do... */
1140            break;
1141
1142        case NFA_HCI_RSP_TIMEOUT_EVT:
1143            nfa_hci_rsp_timeout ((tNFA_HCI_EVENT_DATA *)p_msg);
1144            break;
1145
1146        case NFA_HCI_CHECK_QUEUE_EVT:
1147            if (HCI_LOOPBACK_DEBUG)
1148            {
1149                if (p_msg->len != 0)
1150                {
1151                    tNFC_DATA_CEVT   xx;
1152                    xx.p_data = p_msg;
1153                    nfa_hci_conn_cback (0, NFC_DATA_CEVT, (tNFC_CONN *)&xx);
1154                    return FALSE;
1155                }
1156            }
1157            break;
1158        }
1159    }
1160
1161    if ((p_msg->event > NFA_HCI_LAST_API_EVENT))
1162        GKI_freebuf (p_msg);
1163
1164    nfa_hci_check_api_requests ();
1165
1166    if (nfa_hciu_is_no_host_resetting ())
1167        nfa_hci_check_pending_api_requests ();
1168
1169    if ((nfa_hci_cb.hci_state == NFA_HCI_STATE_IDLE) && (nfa_hci_cb.nv_write_needed))
1170    {
1171        nfa_hci_cb.nv_write_needed = FALSE;
1172        nfa_nv_co_write ((UINT8 *)&nfa_hci_cb.cfg, sizeof (nfa_hci_cb.cfg),DH_NV_BLOCK);
1173    }
1174
1175    return FALSE;
1176}
1177
1178