1/******************************************************************************
2 *
3 *  Copyright (C) 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 *  Vendor-specific handler for HCI events
22 *
23 ******************************************************************************/
24#include "gki.h"
25#include "nfc_hal_api.h"
26#include "nfc_hal_int.h"
27#include "nfc_hal_nv_ci.h"
28#include "nfc_hal_nv_co.h"
29
30#include <string.h>
31#include "nfc_hal_nv_co.h"
32
33#ifndef NFC_HAL_HCI_NV_READ_TIMEOUT
34#define NFC_HAL_HCI_NV_READ_TIMEOUT    1000
35#endif
36
37#ifndef NFC_HAL_HCI_NFCC_RSP_TIMEOUT
38#define NFC_HAL_HCI_NFCC_RSP_TIMEOUT   3000
39#endif
40
41static void nfc_hal_hci_set_next_hci_netwk_config (UINT8 block);
42static void nfc_hal_hci_handle_nv_read (UINT8 block, tHAL_NFC_STATUS status, UINT16 size);
43static void nfc_hal_hci_init_complete (tHAL_NFC_STATUS status);
44static void nfc_hal_hci_vsc_cback (tNFC_HAL_NCI_EVT event, UINT16 data_len, UINT8 *p_data);
45
46/*******************************************************************************
47**
48** Function         nfc_hal_hci_evt_hdlr
49**
50** Description      Processing event for NFA HCI
51**
52** Returns          None
53**
54*******************************************************************************/
55void nfc_hal_hci_evt_hdlr (tNFC_HAL_HCI_EVENT_DATA *p_evt_data)
56{
57    switch (p_evt_data->hdr.event)
58    {
59    case NFC_HAL_HCI_RSP_NV_READ_EVT:
60        nfc_hal_hci_handle_nv_read (p_evt_data->nv_read.block, p_evt_data->nv_read.status, p_evt_data->nv_read.size);
61        break;
62
63    case NFC_HAL_HCI_RSP_NV_WRITE_EVT:
64        /* NV Ram write completed - nothing to do... */
65        break;
66
67    default:
68        break;
69    }
70}
71
72/*******************************************************************************
73**
74** Function         nfc_hal_hci_enable
75**
76** Description      Program nv data on to controller
77**
78** Returns          void
79**
80*******************************************************************************/
81void nfc_hal_hci_enable (void)
82{
83
84    UINT8 *p_hci_netwk_cmd;
85
86    if (nfc_hal_cb.hci_cb.p_hci_netwk_dh_info_buf)
87    {
88        p_hci_netwk_cmd = (UINT8 *) (nfc_hal_cb.hci_cb.p_hci_netwk_dh_info_buf - NCI_MSG_HDR_SIZE);
89        GKI_freebuf (p_hci_netwk_cmd);
90        nfc_hal_cb.hci_cb.p_hci_netwk_dh_info_buf = NULL;
91    }
92
93    if (nfc_hal_cb.hci_cb.p_hci_netwk_info_buf)
94    {
95        p_hci_netwk_cmd = (UINT8 *) (nfc_hal_cb.hci_cb.p_hci_netwk_info_buf - NCI_MSG_HDR_SIZE);
96        GKI_freebuf (p_hci_netwk_cmd);
97        nfc_hal_cb.hci_cb.p_hci_netwk_info_buf = NULL;
98    }
99
100    if ((p_hci_netwk_cmd = (UINT8 *) GKI_getbuf (NCI_MSG_HDR_SIZE + NFC_HAL_HCI_NETWK_INFO_SIZE)) == NULL)
101    {
102        NCI_TRACE_ERROR0 ("nfc_hal_hci_enable: unable to allocate buffer for reading hci network info from nvram");
103        nfc_hal_hci_init_complete (HAL_NFC_STATUS_FAILED);
104    }
105    else
106    {
107        nfc_hal_cb.hci_cb.p_hci_netwk_info_buf   = (UINT8 *) (p_hci_netwk_cmd + NCI_MSG_HDR_SIZE);
108        nfc_hal_cb.hci_cb.hci_netwk_config_block = 0;
109        memset (nfc_hal_cb.hci_cb.p_hci_netwk_info_buf, 0, NFC_HAL_HCI_NETWK_INFO_SIZE);
110        nfc_hal_nv_co_read ((UINT8 *) nfc_hal_cb.hci_cb.p_hci_netwk_info_buf, NFC_HAL_HCI_NETWK_INFO_SIZE, HC_F3_NV_BLOCK);
111        nfc_hal_main_start_quick_timer (&nfc_hal_cb.hci_cb.hci_timer, NFC_HAL_HCI_VSC_TIMEOUT_EVT, NFC_HAL_HCI_NV_READ_TIMEOUT);
112    }
113}
114
115/*******************************************************************************
116**
117** Function         nfc_hal_hci_handle_hci_netwk_info
118**
119** Description      Handler function for HCI Network Notification
120**
121** Returns          None
122**
123*******************************************************************************/
124void nfc_hal_hci_handle_hci_netwk_info (UINT8 *p_data)
125{
126    UINT8  *p = p_data;
127    UINT16 data_len;
128    UINT8  target_handle;
129    UINT8   hci_netwk_cmd[1 + NFC_HAL_HCI_SESSION_ID_LEN];
130
131    NCI_TRACE_DEBUG0 ("nfc_hal_hci_handle_hci_netwk_info()");
132
133    /* skip NCI header byte0 (MT,GID), byte1 (OID) */
134    p += 2;
135
136    STREAM_TO_UINT8 (data_len, p);
137    target_handle = *(UINT8 *) p;
138
139    if (target_handle == NFC_HAL_HCI_DH_TARGET_HANDLE)
140        nfc_hal_nv_co_write (p, data_len,HC_DH_NV_BLOCK);
141
142    else if (target_handle == NFC_HAL_HCI_UICC0_TARGET_HANDLE)
143    {
144        if (p[12] & 0x80)
145        {
146            /* HCI Network notification received for UICC 0, Update nv data */
147            nfc_hal_nv_co_write (p, data_len,HC_F3_NV_BLOCK);
148        }
149        else
150        {
151            NCI_TRACE_DEBUG1 ("nfc_hal_hci_handle_hci_netwk_info(): Type A Card Emulation invalid, Reset nv file: 0x%02x", p[15]);
152            hci_netwk_cmd[0] = NFC_HAL_HCI_UICC0_TARGET_HANDLE;
153            memset (&hci_netwk_cmd[1], 0xFF, NFC_HAL_HCI_SESSION_ID_LEN);
154            nfc_hal_nv_co_write (hci_netwk_cmd, 1, HC_F3_NV_BLOCK);
155        }
156    }
157    else if (target_handle == NFC_HAL_HCI_UICC1_TARGET_HANDLE)
158    {
159        if (p[12] & 0x80)
160        {
161            /* HCI Network notification received for UICC 1, Update nv data */
162            nfc_hal_nv_co_write (p, data_len,HC_F4_NV_BLOCK);
163        }
164        else
165        {
166            NCI_TRACE_DEBUG1 ("nfc_hal_hci_handle_hci_netwk_info(): Type A Card Emulation invalid, Reset nv file: 0x%02x", p[15]);
167            hci_netwk_cmd[0] = NFC_HAL_HCI_UICC1_TARGET_HANDLE;
168            /* Reset Session ID */
169            memset (&hci_netwk_cmd[1], 0xFF, NFC_HAL_HCI_SESSION_ID_LEN);
170            nfc_hal_nv_co_write (hci_netwk_cmd, 1, HC_F4_NV_BLOCK);
171        }
172    }
173}
174
175/*******************************************************************************
176**
177** Function         nfc_hal_hci_handle_hcp_pkt
178**
179** Description      Handle HCP Packet
180**
181** Returns          None
182**
183*******************************************************************************/
184void nfc_hal_hci_handle_hcp_pkt (UINT8 *p_data)
185{
186    UINT8   chaining_bit;
187    UINT8   pipe;
188    UINT8   type;
189    UINT8   inst;
190    UINT8   hci_netwk_cmd[1 + NFC_HAL_HCI_SESSION_ID_LEN];
191    UINT8   source_host;
192
193    chaining_bit = ((*p_data) >> 0x07) & 0x01;
194    pipe = (*p_data++) & 0x7F;
195
196    if (  (chaining_bit)
197        &&(pipe == NFC_HAL_HCI_ADMIN_PIPE)  )
198    {
199        type  = ((*p_data) >> 0x06) & 0x03;
200
201        if (type == NFC_HAL_HCI_COMMAND_TYPE)
202        {
203            inst  = (*p_data++ & 0x3F);
204
205            if (inst == NFC_HAL_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED)
206            {
207
208                STREAM_TO_UINT8 (source_host, p_data);
209
210                NCI_TRACE_DEBUG1 ("nfc_hal_hci_handle_hcp_pkt(): Received Clear All pipe command for UICC: 0x%02x", source_host);
211                if (source_host == NFC_HAL_HCI_HOST_ID_UICC0)
212                {
213                    hci_netwk_cmd[0] = NFC_HAL_HCI_UICC0_TARGET_HANDLE;
214                    /* Reset Session ID */
215                    memset (&hci_netwk_cmd[1], 0xFF, NFC_HAL_HCI_SESSION_ID_LEN);
216                    nfc_hal_nv_co_write (hci_netwk_cmd, 1, HC_F3_NV_BLOCK);
217                    NCI_TRACE_DEBUG1 ("nfc_hal_hci_handle_hcp_pkt(): Sent command to reset nv file for block: 0x%02x", HC_F3_NV_BLOCK);
218                }
219                else if (source_host == NFC_HAL_HCI_HOST_ID_UICC1)
220                {
221                    hci_netwk_cmd[0] = NFC_HAL_HCI_UICC1_TARGET_HANDLE;
222                    /* Reset Session ID */
223                    memset (&hci_netwk_cmd[1], 0xFF, NFC_HAL_HCI_SESSION_ID_LEN);
224                    nfc_hal_nv_co_write (hci_netwk_cmd, 1, HC_F4_NV_BLOCK);
225                    NCI_TRACE_DEBUG1 ("nfc_hal_hci_handle_hcp_pkt(): Sent command to reset nv file for block: 0x%02x", HC_F4_NV_BLOCK);
226                }
227            }
228        }
229    }
230}
231
232/*******************************************************************************
233**
234** Function         nfc_hal_hci_handle_nv_read
235**
236** Description      handler function for nv read complete event
237**
238** Returns          None
239**
240*******************************************************************************/
241void nfc_hal_hci_handle_nv_read (UINT8 block, tHAL_NFC_STATUS status, UINT16 size)
242{
243    NFC_HDR *p_data = NULL;
244    UINT8   *p;
245    UINT8   *p_hci_netwk_info = NULL;
246
247    /* Stop timer as NVDATA Read Completed */
248    nfc_hal_main_stop_quick_timer (&nfc_hal_cb.hci_cb.hci_timer);
249
250    switch (block)
251    {
252    case HC_F3_NV_BLOCK:
253    case HC_F4_NV_BLOCK:
254        if (  (status != HAL_NFC_STATUS_OK)
255            ||(size > NFC_HAL_HCI_NETWK_INFO_SIZE)  )
256        {
257            NCI_TRACE_DEBUG0 ("nfc_hal_hci_handle_nv_read: Invalid data from nv memory, Set DEFAULT Configuration!");
258            memset (nfc_hal_cb.hci_cb.p_hci_netwk_info_buf, 0, NFC_HAL_HCI_NETWK_INFO_SIZE);
259            nfc_hal_cb.hci_cb.p_hci_netwk_info_buf[0] = (block == HC_F3_NV_BLOCK) ? NFC_HAL_HCI_UICC0_TARGET_HANDLE : NFC_HAL_HCI_UICC1_TARGET_HANDLE;
260            memset (&nfc_hal_cb.hci_cb.p_hci_netwk_info_buf[1], 0xFF, NFC_HAL_HCI_SESSION_ID_LEN);
261            size = NFC_HAL_HCI_NETWK_INFO_SIZE;
262        }
263
264        p_hci_netwk_info = (UINT8 *) nfc_hal_cb.hci_cb.p_hci_netwk_info_buf - NCI_MSG_HDR_SIZE;
265        break;
266
267    case HC_DH_NV_BLOCK:
268        if (  (status == HAL_NFC_STATUS_OK)
269            &&(size <= NFC_HAL_HCI_DH_NETWK_INFO_SIZE)  )
270        {
271            p_hci_netwk_info = (UINT8 *) (nfc_hal_cb.hci_cb.p_hci_netwk_dh_info_buf - NCI_MSG_HDR_SIZE);
272        }
273        else
274        {
275            NCI_TRACE_ERROR0 ("nfc_hal_hci_handle_nv_read: Invalid data from nv memory, Skip DH Configuration!");
276        }
277        break;
278
279    default:
280        return;
281    }
282
283    if (p_hci_netwk_info)
284    {
285        p = p_hci_netwk_info;
286        /* Send HCI Network ntf command using nv data */
287        NCI_MSG_BLD_HDR0 (p, NCI_MT_CMD, NCI_GID_PROP);
288        NCI_MSG_BLD_HDR1 (p, NCI_MSG_HCI_NETWK);
289        UINT8_TO_STREAM (p, (UINT8) size);
290
291        nfc_hal_dm_send_nci_cmd (p_hci_netwk_info, (UINT16) (NCI_MSG_HDR_SIZE + size), nfc_hal_hci_vsc_cback);
292
293        nfc_hal_cb.hci_cb.hci_netwk_config_block = block;
294    }
295    else
296    {
297        /* Set next HCI Network configuration */
298        nfc_hal_hci_set_next_hci_netwk_config (block);
299    }
300}
301
302/*******************************************************************************
303**
304** Function         nfc_hal_hci_init_complete
305**
306** Description      Notify VSC initialization is complete
307**
308** Returns          None
309**
310*******************************************************************************/
311void nfc_hal_hci_init_complete (tHAL_NFC_STATUS status)
312{
313    UINT8 *p_hci_netwk_cmd;
314
315    if (nfc_hal_cb.hci_cb.p_hci_netwk_dh_info_buf)
316    {
317        p_hci_netwk_cmd = (UINT8 *) (nfc_hal_cb.hci_cb.p_hci_netwk_dh_info_buf - NCI_MSG_HDR_SIZE);
318        GKI_freebuf (p_hci_netwk_cmd);
319        nfc_hal_cb.hci_cb.p_hci_netwk_dh_info_buf = NULL;
320    }
321
322    if (nfc_hal_cb.hci_cb.p_hci_netwk_info_buf)
323    {
324        p_hci_netwk_cmd = (UINT8 *) (nfc_hal_cb.hci_cb.p_hci_netwk_info_buf - NCI_MSG_HDR_SIZE);
325        GKI_freebuf (p_hci_netwk_cmd);
326        nfc_hal_cb.hci_cb.p_hci_netwk_info_buf = NULL;
327    }
328
329    NFC_HAL_SET_INIT_STATE (NFC_HAL_INIT_STATE_IDLE);
330    nfc_hal_cb.p_stack_cback (HAL_NFC_POST_INIT_CPLT_EVT, HAL_NFC_STATUS_OK);
331}
332
333/*******************************************************************************
334**
335** Function         nfc_hal_hci_set_next_hci_netwk_config
336**
337** Description      set next hci network configuration
338**
339** Returns          None
340**
341*******************************************************************************/
342void nfc_hal_hci_set_next_hci_netwk_config (UINT8 block)
343{
344    UINT8 *p_hci_netwk_cmd;
345
346    switch (block)
347    {
348    case HC_F3_NV_BLOCK:
349        /* Send command to read nvram data for 0xF4 */
350        memset (nfc_hal_cb.hci_cb.p_hci_netwk_info_buf, 0, NFC_HAL_HCI_NETWK_INFO_SIZE);
351        nfc_hal_nv_co_read ((UINT8 *) nfc_hal_cb.hci_cb.p_hci_netwk_info_buf, NFC_HAL_HCI_NETWK_INFO_SIZE, HC_F4_NV_BLOCK);
352        nfc_hal_main_start_quick_timer (&nfc_hal_cb.hci_cb.hci_timer, NFC_HAL_HCI_VSC_TIMEOUT_EVT, NFC_HAL_HCI_NV_READ_TIMEOUT);
353        break;
354
355    case HC_F4_NV_BLOCK:
356        if ((p_hci_netwk_cmd = (UINT8 *) GKI_getbuf (NCI_MSG_HDR_SIZE + NFC_HAL_HCI_DH_NETWK_INFO_SIZE)) == NULL)
357        {
358            NCI_TRACE_ERROR0 ("nfc_hal_hci_set_next_hci_netwk_config: unable to allocate buffer for reading hci network info from nvram");
359            nfc_hal_hci_init_complete (HAL_NFC_STATUS_FAILED);
360        }
361        else
362        {
363            nfc_hal_cb.hci_cb.p_hci_netwk_dh_info_buf   = (UINT8 *) (p_hci_netwk_cmd + NCI_MSG_HDR_SIZE);
364            /* Send command to read nvram data for 0xF2 */
365            memset (nfc_hal_cb.hci_cb.p_hci_netwk_dh_info_buf, 0, NFC_HAL_HCI_DH_NETWK_INFO_SIZE);
366            nfc_hal_nv_co_read ((UINT8 *) nfc_hal_cb.hci_cb.p_hci_netwk_dh_info_buf, NFC_HAL_HCI_DH_NETWK_INFO_SIZE, HC_DH_NV_BLOCK);
367            nfc_hal_main_start_quick_timer (&nfc_hal_cb.hci_cb.hci_timer, NFC_HAL_HCI_VSC_TIMEOUT_EVT, NFC_HAL_HCI_NV_READ_TIMEOUT);
368        }
369        break;
370
371    case HC_DH_NV_BLOCK:
372        nfc_hal_hci_init_complete (HAL_NFC_STATUS_OK);
373        break;
374
375    default:
376        NCI_TRACE_ERROR1 ("nfc_hal_hci_set_next_hci_netwk_config: unable to allocate buffer to send VSC 0x%02x", block);
377        /* Brcm initialization failed */
378        nfc_hal_hci_init_complete (HAL_NFC_STATUS_FAILED);
379        break;
380    }
381}
382
383/*******************************************************************************
384**
385** Function         nfc_hal_hci_vsc_cback
386**
387** Description      process VS callback event from stack
388**
389** Returns          none
390**
391*******************************************************************************/
392static void nfc_hal_hci_vsc_cback (tNFC_HAL_NCI_EVT event, UINT16 data_len, UINT8 *p_data)
393{
394    UINT8 *p_ret = NULL;
395    UINT8 status;
396
397    p_ret  = p_data + NCI_MSG_HDR_SIZE;
398    status = *p_ret;
399
400    if (event  != NFC_VS_HCI_NETWK_RSP)
401        return;
402
403    if (status != HAL_NFC_STATUS_OK)
404        nfc_hal_hci_init_complete (HAL_NFC_STATUS_FAILED);
405
406    switch (nfc_hal_cb.hci_cb.hci_netwk_config_block)
407    {
408    case HC_F3_NV_BLOCK:
409    case HC_F4_NV_BLOCK:
410    case HC_DH_NV_BLOCK:
411        nfc_hal_hci_set_next_hci_netwk_config (nfc_hal_cb.hci_cb.hci_netwk_config_block);
412        break;
413
414    default:
415        /* Ignore the event */
416        break;
417    }
418}
419
420/*******************************************************************************
421**
422** Function         nfc_hal_nci_cmd_timeout_cback
423**
424** Description      callback function for timeout
425**
426** Returns          void
427**
428*******************************************************************************/
429void nfc_hal_hci_timeout_cback (void *p_tle)
430{
431    TIMER_LIST_ENT  *p_tlent = (TIMER_LIST_ENT *)p_tle;
432
433    NCI_TRACE_DEBUG0 ("nfc_hal_hci_timeout_cback ()");
434
435    if (p_tlent->event == NFC_HAL_HCI_VSC_TIMEOUT_EVT)
436    {
437        NCI_TRACE_ERROR0 ("nfc_hal_hci_timeout_cback: Timeout - NFC HAL HCI BRCM Initialization Failed!");
438        nfc_hal_hci_init_complete (HAL_NFC_STATUS_FAILED);
439    }
440}
441
442